mysql事务不提交会发生什么_mysql数据一致性分析

来源:这里教程网 时间:2026-02-28 20:46:09 作者:

事务未提交时数据对其他会话不可见

MySQL 默认隔离级别是

REPEATABLE READ
,未提交的事务修改只在当前会话内可见。其他会话查不到这些变更,也不会被阻塞(除非涉及行锁冲突)。这常被误认为“没影响”,其实已悄悄占用资源。

未提交事务会持续持有行锁或间隙锁,可能造成其他会话
UPDATE
SELECT ... FOR UPDATE
阻塞
INFORMATION_SCHEMA.INNODB_TRX
中能看到该事务状态为
RUNNING
,且
TRX_STATE
ACTIVE
长时间未提交会拖慢
purge
线程,导致
undo log
无法及时回收,
ibdata1
文件持续膨胀

连接断开后未提交事务自动回滚

MySQL 客户端异常断连(比如网络中断、应用崩溃、超时断开),服务端检测到连接关闭后,会立即执行隐式回滚。这点和 Oracle 不同——Oracle 断连后事务仍保持活跃,直到被杀或超时。

可通过
SHOW VARIABLES LIKE 'wait_timeout'
interactive_timeout
查看超时阈值,默认 28800 秒(8 小时)
若应用使用连接池(如 HikariCP),需确认是否开启
connection-test-query
validation-timeout
,避免拿到已失效但未清理的连接
注意:
mysql -e "UPDATE t SET x=1;"
这类单命令执行完即退出,事务不会自动提交——除非显式加
-e "START TRANSACTION; UPDATE ...; COMMIT;"

autocommit=0 时忘记 COMMIT 是最常见一致性破环点

当会话执行过

SET autocommit = 0
,后续所有 DML 都进入手动事务模式。此时即使只执行一条
UPDATE
,不
COMMIT
ROLLBACK
,就等于挂起一个未决事务。

典型表现:
SELECT
能看到刚改的值,但其他会话查不到;应用重启后该修改彻底消失
开发调试时常用
mysql -u root -p --init-command="SET autocommit=0"
,极易遗忘
COMMIT
建议在连接初始化时统一设为
autocommit=1
,仅在明确需要多语句原子性时用
BEGIN
/
COMMIT

长事务导致 MVCC 快照过旧与主从延迟加剧

未提交事务越久,其事务 ID 越“老”,InnoDB 为维持一致性读(consistent read),必须保留早于该事务开始的所有版本记录。这直接拖累 purge 效率,并放大主从延迟。

主库上长事务会让
show master status
File
Position
滞后,因为 binlog 只在
COMMIT
时写入
从库 SQL 线程等待主库该事务提交后才能继续,表现为
Seconds_Behind_Master
持续增长
监控关键指标:
SELECT TRX_ID, TRX_STARTED, TIME_TO_SEC(NOW() - TRX_STARTED) AS duration FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY duration DESC LIMIT 5;

事务没提交这事本身不报错,但它像后台静默运行的定时器——锁、日志、快照、复制链路,全在悄悄承压。最容易被忽略的是:你以为只是“还没点保存”,系统却已在底层扛着整个一致性模型往前挪。

相关推荐