MySQL保存点是事务内设的标记点,允许回滚到中间状态而非整个事务;必须在显式开启事务(START TRANSACTION)且autocommit=0时使用,仅InnoDB支持,DDL或事务终结会使保存点失效。

MySQL 保存点是什么,什么时候必须用
保存点(SAVEPOINT)是事务内设的标记点,允许你在不回滚整个事务的前提下,只撤回到某个中间状态。它不是替代事务,而是给长事务加“分段刹车”——比如批量导入时前100条成功、第101条报错,你不想重跑全部,就靠它回滚最后几条。
注意:SAVEPOINT 只在事务中有效,且仅对当前连接可见;一旦 COMMIT 或 ROLLBACK 整个事务,所有保存点自动失效。
怎么定义和回滚到保存点
语法简单,但顺序和命名容易出错:
-
SAVEPOINT sp1;—— 定义名为sp1的保存点,名字不能重复,否则覆盖旧的 -
ROLLBACK TO SAVEPOINT sp1;—— 回滚到该点,之后的修改丢弃,但事务仍活跃,可继续执行 -
RELEASE SAVEPOINT sp1;—— 手动释放保存点(非必须,事务结束时自动清理)
示例:
START TRANSACTION;
INSERT INTO users(name) VALUES('Alice');
SAVEPOINT after_alice;
INSERT INTO users(name) VALUES('Bob');
INSERT INTO users(name) VALUES('Charlie'); -- 假设这里违反唯一约束
ROLLBACK TO SAVEPOINT after_alice; -- 只撤销 Bob 和 Charlie,Alice 保留
INSERT INTO users(name) VALUES('David');
COMMIT;常见错误:为什么 ROLLBACK TO SAVEPOINT 报错 Unknown savepoint
这个错误几乎都源于三个原因:
- 保存点名写错或大小写不一致(MySQL 保存点名区分大小写)
- 在未开启事务时执行
SAVEPOINT(某些版本会静默忽略,后续ROLLBACK TO就找不到) - 事务已被
COMMIT或ROLLBACK终止,但代码仍尝试回滚到已销毁的保存点
调试建议:执行 SELECT @@in_transaction; 确认是否真在事务中;用 SHOW ENGINE INNODB STATUS\G 查看当前事务状态(需有 PROCESS 权限)。
保存点 + 自动提交关掉才能生效
默认 MySQL 是自动提交模式(autocommit=1),此时每个语句都是独立事务,SAVEPOINT 设了也立刻失效。
- 必须先执行
SET autocommit = 0;或显式START TRANSACTION; - 应用层(如 Python 的
pymysql或 Java 的JDBC)也要确认连接没开 auto-commit - 某些 ORM(如 Django)默认关闭 auto-commit,但显式调用
transaction.atomic()才真正启用保存点支持
一个容易被忽略的细节:MySQL 8.0+ 对保存点嵌套层级没有硬限制,但过多保存点会轻微增加事务内存开销——日常用 3–5 个足够,别为每条 INSERT 都设一个。


















