能回滚,但需满足事务未提交且不在autocommit=1模式下;必须显式begin/start transaction后执行insert,出错立即rollback才生效,已commit或隐式提交(如ddl)则不可逆。

能回滚,但前提是事务还没提交,且你没在 autocommit=1 模式下直接执行 INSERT。
MySQL 默认不支持自动回滚失败的 INSERT
很多人以为 INSERT 报错(比如主键冲突、NOT NULL 字段为空)后数据会自动撤销——不会。MySQL 默认 autocommit=1,每条 INSERT 都是独立事务,一执行完就永久落库,ROLLBACK 对它完全无效。
- 必须先显式开启事务:
BEGIN或START TRANSACTION - 再执行 INSERT(可多条)
- 出错后,立刻执行
ROLLBACK—— 这时才真正起作用 - 如果已经执行了
COMMIT,或连接断开前没手动ROLLBACK,那就无法用标准方式恢复
Python / Java / PHP 应用中必须主动捕获异常再回滚
数据库客户端不会替你决定“要不要回滚”。哪怕 psycopg2 或 pymysql 抛出 IntegrityError,你也得自己调 conn.rollback(),否则连接可能还挂着未提交状态。
- 不要只 catch 异常就完事:有些驱动(如 MySQL 的
INSERT IGNORE)只发 warning,rowcount可能为 0,但程序没报错 - 别依赖
autocommit=False就万事大吉:DDL 语句(如CREATE TABLE)、SET AUTOCOMMIT=1、ALTER都会隐式触发提交,清空当前事务上下文 - 连接池复用时尤其危险:上一个请求没
rollback(),下一个请求可能继承脏事务状态
想局部回滚?用 SAVEPOINT,不是嵌套事务
SQL 不支持真正嵌套事务。所谓“在 INSERT 中间回滚一部分”,靠的是 SAVEPOINT,它只是事务内的标记点,不是独立事务。
- 写法:
SAVEPOINT sp1→ 出错后ROLLBACK TO sp1 - 注意:
sp1名称不能重复,否则后一次会覆盖前一次 - PostgreSQL 支持
RELEASE SAVEPOINT sp1;MySQL 不支持该语法 -
ROLLBACK TO只撤销之后的操作,之前已执行的 INSERT 仍有效 —— 所以它解决的是“部分失败继续执行”,不是“原子性保障”
已 COMMIT 的 INSERT 真的不能回滚
一旦 COMMIT 成功返回,InnoDB 就把 Undo Log 相关记录标记为可清理,ROLLBACK 失效。Redo Log 是为了崩溃恢复,不是反向操作日志。
- 误删/误插已提交数据,唯一靠谱路径是解析
binlog找到对应事件,用mysqlbinlog --stop-datetime或工具(如flashback)逆向生成补偿 SQL - 没开
binlog?没做定期逻辑备份?那基本只能从应用日志或上游系统重建数据 - 日常开发务必关掉默认
autocommit,并在事务块里写注释说明业务意图,比如-- 转账:扣款+记账+发通知,三者必须原子










