start transaction后才能用commit/rollback;默认autocommit=1下单独执行二者无效,因无活跃事务;ddl会隐式提交;commit不等于立即刷盘,取决于innodb_flush_log_at_trx_commit配置;rollback默认回退至事务起点,局部回滚需savepoint。

START TRANSACTION后才能用COMMIT/ROLLBACK
直接执行 COMMIT 或 ROLLBACK 很可能报错或无效——因为当前没有活跃事务。MySQL 默认 autocommit = 1,每条 INSERT/UPDATE/DELETE 都自动提交,根本没“可回滚的内容”。
必须先显式开启事务上下文:
-
START TRANSACTION(推荐)或BEGIN,二者等价,会隐式关闭当前会话的 autocommit - 不建议用
SET autocommit = 0单独关自动提交,容易遗漏后续COMMIT导致长事务挂起 - DDL 语句(如
ALTER TABLE、DROP INDEX)会**隐式触发 COMMIT**,之后的 DML 不再属于原事务
COMMIT不是“立刻落盘”,而是“进入持久化队列”
COMMIT 返回成功,只代表事务已进入 InnoDB 的“已提交但未刷盘”状态,是否真正写入磁盘取决于 innodb_flush_log_at_trx_commit 配置:
-
= 1(默认):每次COMMIT都调用fsync()写 redo log 到磁盘,崩溃不丢事务,但 IO 开销大 -
= 2:只写 OS cache,由系统异步刷盘;OS 崩溃可能丢数据 -
= 0:每秒刷一次日志,COMMIT后宕机最多丢 1 秒事务
无论设成几,COMMIT 后其他事务按隔离级别(如 READ-COMMITTED)就能看到新值——可见性 ≠ 持久性。
ROLLBACK只能回滚到事务起点,SAVEPOINT是例外
ROLLBACK 默认撤销从 START TRANSACTION 开始的所有 DML,不能只撤某一条语句。真要局部回退,得靠 SAVEPOINT:
- 定义保存点:
SAVEPOINT sp_a; - 回滚到它:
ROLLBACK TO sp_a;(注意不是ROLLBACK TO SAVEPOINT sp_a) - 错误写法:
ROLLBACK TO non_exist_sp会报错ERROR 1305 (42000): SAVEPOINT does not exist,且事务仍处于活动状态,必须再ROLLBACK或COMMIT显式结束 -
RELEASE SAVEPOINT sp_a可删除保存点,但不影响事务本身
连接断开时事务自动回滚,但你未必知道
客户端异常退出(网络中断、kill connection、wait_timeout 超时)会导致 MySQL 自动 ROLLBACK 当前事务。问题在于:这个动作静默发生,应用层收不到通知,可能误以为“操作没执行”。
更隐蔽的风险是长事务:
- 一个运行 5 分钟未
COMMIT的事务,会阻止 undo log 清理,导致ibdata1文件持续膨胀且不可收缩 - 监控活跃事务用:
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G,重点关注TRX_STARTED和TRX_STATE - 别依赖“手动回滚”,该
COMMIT就COMMIT,该ROLLBACK就ROLLBACK,别让事务卡在中间态











