未提交事务在MySQL中仅当前会话可见,但会持锁、阻塞其他操作、拖慢purge、加剧主从延迟,并在连接断开时自动回滚;autocommit=0下遗忘COMMIT是最常见一致性破坏点。

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










