在一个事务里用SAVEPOINT分段,验证ROLLBACK TO SAVEPOINT真实撤销了哪些数据改动,再用真实并发会话检验那些被撤销的改动,对应的锁是不是也一起被释放了。
代码START TRANSACTION; UPDATE accounts SET balance=balance-100 WHERE id=10; SAVEPOINT sp1; UPDATE accounts SET balance=balance-200 WHERE id=20; ROLLBACK TO sp1; COMMIT;
回滚前: id=10 → 900.00(-100生效) id=20 → 800.00(-200生效)
ROLLBACK TO sp1 之后:
id=10 → 900.00(真实保留,在savepoint之前)
id=20 → 1000.00(真实撤销,回到savepoint时的状态)
最终COMMIT之后,数据保持不变这部分和SAVEPOINT的教科书描述完全一致:ROLLBACK TO sp1真实只撤销了savepoint之后发生的改动(id=20),savepoint之前的改动(id=10)真实原封不动地保留了下来,最后一起提交。
并发更新 id=10(从未被回滚过的行): ERROR 1205 (HY000): Lock wait timeout exceeded ← 真实被挡住 并发更新 id=20(数据已经被ROLLBACK TO SAVEPOINT撤销): ERROR 1205 (HY000): Lock wait timeout exceeded ← 真实同样被挡住!
每一步都是本文上面用真实并发会话跑出来的原始结果。
SAVEPOINT / ROLLBACK TO savepoint_name