mysql中回滚仅对未提交的事务有效,已commit的数据无法通过rollback恢复,必须依赖备份或binlog;需确保使用innodb引擎、显式start transaction开启事务,并避免ddl等隐式提交操作。

MySQL 中手动开启事务不能“修复”已提交的脏数据,只能防止它写入——回滚只对未提交的变更有效。如果你已经 COMMIT 了错误 SQL,ROLLBACK 就完全没用,必须靠备份或 binlog 恢复。
用 START TRANSACTION 包住操作,别依赖 SET autocommit = 0
显式开启事务是最可控的方式。直接执行 SET autocommit = 0 会让后续所有语句都进入同一个隐式事务,直到你手动 COMMIT 或 ROLLBACK,容易漏掉提交、锁表时间过长,还可能被连接中断自动回滚,反而更难排查。
-
START TRANSACTION和BEGIN等效,但前者更符合 SQL 标准,推荐统一使用 - 开启后立即执行你的 DML(
INSERT/UPDATE/DELETE),中间不要穿插SELECT以外的管理语句(如USE、SET) - 事务块内不支持 DDL(如
ALTER TABLE),一旦执行会隐式触发COMMIT,导致前面的修改提前落库
出错时立刻 ROLLBACK,别等程序报错后再处理
很多开发者习惯在应用层捕获异常再调用 rollback(),但 MySQL 客户端本身就能感知语法错误、约束冲突等。只要语句执行失败,当前事务就处于“半失效”状态,继续执行其他语句可能报错或行为异常。
- 在命令行或工具中执行时,看到
ERROR 1062 (23000): Duplicate entry这类报错后,第一反应就是输入ROLLBACK;,别试图补救 - 如果用了保存点(
SAVEPOINT sp1),可以用ROLLBACK TO sp1撤销部分操作,但注意:保存点不能跨连接,且每次RELEASE SAVEPOINT或事务结束都会清除它 -
ROLLBACK不会报错,即使当前没在事务中执行,它也安静返回Query OK,所以不能靠有没有报错来判断是否成功回滚
确认引擎是 InnoDB,否则 ROLLBACK 彻底无效
MyISAM 表不支持事务,无论你写多少遍 START TRANSACTION 和 ROLLBACK,数据都会实时写盘。必须先验证表结构:
SHOW CREATE TABLE your_table;
输出里必须含 ENGINE=InnoDB。如果看到 ENGINE=MyISAM,得先转换:
ALTER TABLE your_table ENGINE = InnoDB;
- 转换过程会锁表,大表慎用;生产环境建议在低峰期执行
- 即便表是 InnoDB,如果事务中混用了临时表(
CREATE TEMPORARY TABLE),那些临时表的操作也不受事务控制 - 全局变量
innodb_support_xa应保持默认ON,否则分布式事务场景下回滚可能不完整
真正棘手的是:事务只能拦住“还没提交”的错误。一旦 COMMIT 成功,undo 日志就被清理,ROLLBACK 再无意义——这时候想恢复,就得翻 binlog 找那条语句,或者从最近一次 mysqldump 导入。别把事务当成后悔药,它只是保险绳。











