COMMIT使事务变更永久生效,触发redo log刷盘、undo log清理和行锁释放;ROLLBACK撤销未提交修改,依赖undo log快速回滚;autocommit=0才具备事务控制权,DDL等语句会隐式提交。

事务提交(COMMIT)是让变更永久生效
执行 COMMIT 后,当前事务中所有 INSERT、UPDATE、DELETE 操作真正写入磁盘(或至少进入持久化队列),其他事务能立即看到这些结果。它不是“只是通知数据库”,而是触发了 InnoDB 的 redo log 刷盘、undo log 清理、行锁释放等一整套动作。
常见误操作:
– 在自动提交(autocommit=1)模式下,每条 DML 都隐式 COMMIT,你以为在事务里,其实没有;
– 手动开启事务后忘了 COMMIT,连接断开时可能被自动回滚(取决于客户端行为和 MySQL 版本);
– 在存储过程中调用 COMMIT 会强制结束当前事务,导致后续语句不在同一事务上下文中。
事务回滚(ROLLBACK)是撤销未提交的变更
ROLLBACK 会丢弃当前事务中所有尚未提交的修改,恢复到 BEGIN 或上一个 SAVEPOINT 的状态。它依赖的是 undo log,不涉及磁盘写入,所以通常比 COMMIT 快,但前提是事务没太大——大事务回滚可能卡住并阻塞其他操作。
典型场景:
– 执行一组关联更新,中间某步出错(比如外键约束失败、除零错误),直接 ROLLBACK 最安全;
– 测试 SQL 逻辑时加 BEGIN + ROLLBACK 包裹,避免污染数据;
– 使用 SAVEPOINT 可实现局部回滚,例如:SAVEPOINT sp1 → 出错 → ROLLBACK TO sp1,之后还能继续 COMMIT。
autocommit 关闭后才真正有“事务控制权”
MySQL 默认开启 autocommit=1,此时每条语句都是独立事务,START TRANSACTION 和 COMMIT 看似没效果。必须先执行 SET autocommit = 0(或显式 BEGIN),才能把多条语句纳入同一个事务单元。
注意点:
– DDL 语句(如 CREATE TABLE、ALTER TABLE)在大多数 MySQL 版本中会隐式触发 COMMIT,导致当前事务提前结束;
– 某些命令(如 LOCK TABLES)也会强制提交;
– 连接池场景下,务必确认连接复用前已清理事务状态,否则可能拿到一个“半提交”的连接。
回滚失败或卡住?大概率是 undo log 或锁的问题
如果 ROLLBACK 执行很久甚至超时,常见原因不是语法错,而是底层资源争用:
– 大事务生成了巨量 undo log,回滚需逐条逆向应用;
– 其他事务正在读取该事务修改过的行(一致性读依赖 undo),导致回滚被阻塞;
– 表上有长持有锁(比如另一个会话正在做全表扫描更新),而回滚需要获取行级锁来清理标记。
可查状态:
– SHOW ENGINE INNODB STATUS\G 查看 TRANSACTIONS 部分的回滚进度;
– information_schema.INNODB_TRX 中 TRX_STATE 为 ROLLING BACK,且 TRX_ROWS_MODIFIED 很大;
– 不要 kill 正在回滚的线程,可能引发更严重的数据不一致。










