mysql中commit/rollback生效的前提是autocommit=0且事务已显式开启;autocommit=1时每条dml自动提交,begin无效;ddl、truncate、myisam操作不可回滚;savepoint支持部分回滚。

MySQL中事务提交和回滚只有两个明确动作:执行 COMMIT 或 ROLLBACK,但前提是事务必须已开启且未自动提交。 直接敲 COMMIT 却没效果?大概率是 autocommit 仍为 1,或者事务根本没真正启动。
为什么 COMMIT 没反应?检查 autocommit 状态
MySQL 默认开启自动提交(autocommit=1),此时每条 INSERT/UPDATE/DELETE 都立刻生效,COMMIT 和 ROLLBACK 完全无效。
- 查当前会话 autocommit 值:
SELECT @@autocommit;—— 返回 1 就说明自动提交开着 - 关掉它:
SET autocommit = 0;—— 这步之后,后续 DML 才会进入“待提交”状态 - 注意:
SET GLOBAL autocommit = 0影响所有新连接,但已有连接不受影响;重启后会恢复默认值
BEGIN 和 START TRANSACTION 都能开启事务,但别混用
两者等价,都显式标记事务起点。关键在于:它们只在 autocommit=0 时才有意义;若 autocommit=1,执行完 BEGIN 立刻执行 DML,仍会自动提交。
- 推荐统一用
START TRANSACTION,语义更清晰 - 不要在 autocommit=1 的会话里先
BEGIN再COMMIT——COMMIT会报 “No transaction in progress” 错误 - 事务开启后,只要没
COMMIT或ROLLBACK,连接断开也会自动回滚(除非是长连接且设置了 wait_timeout 外的其他行为)
回滚不是万能的:哪些操作不能被 ROLLBACK 撤销
ROLLBACK 只对事务内 DML(INSERT/UPDATE/DELETE)有效,以下操作一旦执行就不可逆:
-
DROP TABLE、ALTER TABLE、CREATE INDEX等 DDL 语句 —— MySQL 中它们会隐式触发COMMIT -
TRUNCATE TABLE—— 虽然语法像 DML,但实际是 DDL 行为,执行即提交 - 涉及非事务型存储引擎的表(如 MyISAM)—— 即使在事务块中,修改也会立即落盘
-
SELECT不参与事务控制,但SELECT ... FOR UPDATE或LOCK IN SHARE MODE会加锁,这些锁会在COMMIT/ROLLBACK时释放
保存点(SAVEPOINT)让回滚更精细
当一个事务包含多步操作,只想撤销其中一部分时,SAVEPOINT 是唯一选择。
- 设保存点:
SAVEPOINT sp1; - 执行几条 DML 后出错,只撤回到该点:
ROLLBACK TO sp1; - 之后还能继续操作并最终
COMMIT,或再设新保存点 - 注意:
RELEASE SAVEPOINT sp1只是删除保存点定义,不影响数据;而ROLLBACK TO sp1会真实撤销其后的修改
最容易被忽略的是:事务是否真正“活”着,不取决于你写了 BEGIN,而取决于 autocommit 是否为 0 且后续没有隐式提交的语句。DDL、部分系统函数、甚至某些客户端工具的自动刷新行为,都可能悄悄终结事务上下文。











