引言
savepoint 关键字用于在数据库事务中设置一个存储点,在一个较长的事务中暂存数据,如果在事务末尾执行回滚,可选择性的回滚到 savepoint 设置的暂存点。
本文承接上一篇博客《MySQL 基础 ————事务与隔离级别总结》,进一步探讨事务在实际生产中的重要场景——回滚。
一、SAVEPOINT 语法
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
数据库的 InnoDB 存储引擎(一般情况下都是指此引擎,该引擎是MySQL默认存储引擎,因为另一个比较常见的存储引擎MyISAM不支持事务)支持的 SAVEPOINT 语句,包括上述三种。
SAVEPOINT 通过自定义的名称设置一个存储点,如果当前事务已经有了一个同名的 SAVEPOINT ,那么旧的将会被替代。
ROLLBACK TO SAVEPOINT 子句可以将当前事务回退到自定义的存储点位置,而不会结束事务,InnoDB 不会释放内存中的行锁(对于新插入的行,锁信息是由存储在行中的事务ID携带,而不会单独存储在内存中,那么对于这类锁,是会被释放的),存储点之后语句都会撤销执行,包括新设置的存储点,也同样会被删除。
RELEASE SAVEPOINT 子句,会从当前的事务 SAVEPOINT 集合中,移除指定名称的 SAVEPOINT 。
另外,执行 COMMIT 或 ROLLBACK (未指定 SAVEPOINT)都会清空当前事务的所有 SAVEPOINT。
二、演示
员工表:
操作过程是,开启事务,然后执行两条更新语句,第一条更新 6 号员工的工资,然后设置一个 SAVEPOINT ,第二条更新 9 号员工的工资,执行完成后,回滚到 SAVEPOINT ,然后 COMMIT ,查看6 号 和 9 号员工的工资各有什么变化。
1、开启事务:
SET autocommit = 0;
2、执行更新 6 号员工工资的语句:
UPDATE emp SET salary = 4000 WHERE emp_id = 6;
3、执行 SAVEPOINT:
SAVEPOINT id_6_updated;
4、再执行第二条语句,更新 9 号员工的工资:
UPDATE emp SET salary = 6000 WHERE emp_id = 9;
5、然后,回滚到 SAVEPOINT id_6_updated:
ROLLBACK TO SAVEPOINT id_6_updated;
6、提交更新:
COMMIT;
7、查看最后的更新结果:
可以看到, 6 号员工的工资成功被修改,而 9 号员工的工资虽然执行了更新,但是因为回滚到了执行语句之前的 SAVEPOINT 而没有被更新。