SAVEPOINT必须在显式事务中使用,autocommit=1时无效;ROLLBACK TO SAVEPOINT不释放锁,同名保存点静默覆盖,DDL会隐式提交致其失效。
autocommit=1 时执行 SAVEPOINT sp1 看似成功(返回 Query OK),但后续 ROLLBACK TO SAVEPOINT sp1 一定报错:ERROR 1305 (42000): SAVEPOINT sp1 does not exist。这不是语法问题,而是事务根本没启动。
确认当前会话状态:执行 SELECT @@autocommit, @@in_transaction;,两个值都必须是 1 和 1 才算真正进入事务。仅 SET autocommit = 0 不够,必须配 BEGIN 或 START TRANSACTION。
COMMIT 或 ROLLBACK,当前请求一发 SAVEPOINT 就可能失败,MySQL 认为事务状态异常SAVEPOINT,PyMySQL 等原生驱动需确保所有操作走同一个 Connection 实例这是最常被误读的“业务避让”幻觉来源:回滚到保存点后,你查表数据确实恢复了,但其他事务仍可能被阻塞。因为 InnoDB 不释放该点之后操作持有的锁。
INSERT INTO t VALUES (1) + SAVEPOINT sp + ROLLBACK TO SAVEPOINT sp → 行已删,但该行的插入意向锁(IX)和隐式锁仍持有,直到整个事务 COMMIT 或全量 ROLLBACK。
SELECT ... FOR UPDATE 后设点再回滚,锁完全不受影响information_schema.INNODB_TRX 和 INNODB_LOCK_WAITS
ROLLBACK TO SAVEPOINT 解决并发冲突——它只改数据,不改锁执行两次 SAVEPOINT loop_step,第二次会静默覆盖第一次,不报错、不警告。结果 ROLLBACK TO SAVEPOINT loop_step 总回到最后一次设点位置,而非你预期的某次迭代起点。
名字长度超 64 字符会被截断,大小写不敏感(SP1 和 sp1 视为同一保存点)。建议用短前缀+业务标识+序号,例如 sp_ord_123、sp_batch_007。
RELEASE SAVEPOINT sp_name 是唯一显式清理方式;不释放也不报错,但下次同名仍覆盖ALTER TABLE)会隐式 COMMIT,所有保存点瞬间失效——这不是 bug,是设计使然它本质是 InnoDB 在事务结构体里记的一个 undo log 偏移位置,开销极小,但功能有限:不能选择性撤销某条语句,只能丢弃该点之后所有变更(包括 DML 和部分 DDL)。
常见误解是以为可以“撤回某一条 UPDATE”,实际做不到——只要没在它之前设 SAVEPOINT,就只能连带回滚后续所有操作。
ROLLBACK TO SAVEPOINT 撤销(除非触发器自己设点并回滚)SAVEPOINT 不可用RELEASE 是为了明确意图,不是必须动作