[TOC] # 回滚事务 回滚一个事务指将事务的修改全部撤销。可以回滚当前整个未提交事务,也可以回滚到事务中任意一个保存点。如果要回滚到某个保存点,必须将`ROLLBACK`和`TO SAVEPOINT`语句结合使用。 回滚整个事务: * 事务会结束。 * 所有的修改会被丢弃。 * 清除所有保存点。 * 释放事务持有的所有锁。 回滚到某个保存点: * 事务不会结束。 * 保存点之前的修改被保留,保存点之后的修改被丢弃。 * 清除保存点之后的保存点(不包括保存点自身)。 * 释放保存点之后事务持有的所有锁。 ## 回滚整个事务 回滚整个事务的示例如下: * MySQL 模式下,回滚事务的全部修改。 ~~~ obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | ID | NAME | VALUE | GMT_CREATE | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-02 17:52:31 | | 2 | US | 10002 | 2020-04-02 17:52:38 | | 3 | EN | 10003 | 2020-04-02 17:52:38 | +----+------+-------+---------------------+ 3 rows in set (0.00 sec) obclient> BEGIN; Query OK, 0 rows affected (0.00 sec) obclient> INSERT INTO t_insert(id, name, value) VALUES(4,'JP',10004); Query OK, 1 row affected (0.00 sec) obclient> INSERT INTO t_insert(id, name, value) VALUES(5,'FR',10005),(6,'RU',10006); Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | ID | NAME | VALUE | GMT_CREATE | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-02 17:52:31 | | 2 | US | 10002 | 2020-04-02 17:52:38 | | 3 | EN | 10003 | 2020-04-02 17:52:38 | | 4 | JP | NULL | 2020-04-02 17:53:34 | | 5 | FR | 10005 | 2020-04-02 17:54:53 | | 6 | RU | 10006 | 2020-04-02 17:54:53 | +----+------+-------+---------------------+ 6 rows in set (0.00 sec) obclient> ROLLBACK; Query OK, 0 rows affected (0.00 sec) obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | ID | NAME | VALUE | GMT_CREATE | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-02 17:52:31 | | 2 | US | 10002 | 2020-04-02 17:52:38 | | 3 | EN | 10003 | 2020-04-02 17:52:38 | +----+------+-------+---------------------+ 3 rows in set (0.00 sec) ~~~ ## 回滚到某个保存点 以下示例展示了一个事务中包含多个 DML 语句和多个保存点,当回滚到其中一个保存点后,仅丢弃了保存点后面的那部份修改。 * MySQL 模式 1. 查看表当前记录。 ~~~ obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-03 16:05:45 | | 2 | US | 10002 | 2020-04-03 16:05:54 | | 3 | UK | 10003 | 2020-04-03 16:05:54 | +----+------+-------+---------------------+ 3 rows in set (0.00 sec) ~~~ 2. 开启一个事务,设置多个保存点信息。 ~~~ obclient> SET SESSION autocommit=off; Query OK, 0 rows affected (0.00 sec) obclient> BEGIN; Query OK, 0 rows affected (0.00 sec) obclient> INSERT INTO t_insert(id, name) VALUES(6,'FR'); Query OK, 1 row affected (0.00 sec) obclient> SAVEPOINT fr; Query OK, 0 rows affected (0.00 sec) obclient> INSERT INTO t_insert(id, name) VALUES(7,'RU'); Query OK, 1 row affected (0.00 sec) obclient> SAVEPOINT ru; Query OK, 0 rows affected (0.00 sec) obclient> INSERT INTO t_insert(id, name) VALUES(8,'CA'); Query OK, 1 row affected (0.00 sec) obclient> SAVEPOINT ca; Query OK, 0 rows affected (0.00 sec) ~~~ 3. 查看当前会话中,事务未提交的所有修改。 ~~~ obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-03 16:05:45 | | 2 | US | 10002 | 2020-04-03 16:05:54 | | 3 | UK | 10003 | 2020-04-03 16:05:54 | | 6 | FR | NULL | 2020-04-03 16:26:22 | | 7 | RU | NULL | 2020-04-03 16:26:32 | | 8 | CA | NULL | 2020-04-03 16:26:42 | +----+------+-------+---------------------+ 6 rows in set (0.00 sec) ~~~ 4. 回滚事务到其中一个保存点。 ~~~ obclient> ROLLBACK TO SAVEPOINT ru; Query OK, 0 rows affected (0.00 sec) obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-03 16:05:45 | | 2 | US | 10002 | 2020-04-03 16:05:54 | | 3 | UK | 10003 | 2020-04-03 16:05:54 | | 6 | FR | NULL | 2020-04-03 16:26:22 | | 7 | RU | NULL | 2020-04-03 16:26:32 | +----+------+-------+---------------------+ 5 rows in set (0.01 sec) ~~~ 5. 提交事务,确认表最新修改包含保存点之前的修改。 ~~~ obclient> COMMIT; Query OK, 0 rows affected (0.00 sec) obclient> SELECT * FROM t_insert; +----+------+-------+---------------------+ | id | name | value | gmt_create | +----+------+-------+---------------------+ | 1 | CN | 10001 | 2020-04-03 16:05:45 | | 2 | US | 10002 | 2020-04-03 16:05:54 | | 3 | UK | 10003 | 2020-04-03 16:05:54 | | 6 | FR | NULL | 2020-04-03 16:26:22 | | 7 | RU | NULL | 2020-04-03 16:26:32 | +----+------+-------+---------------------+ 5 rows in set (0.00 sec) ~~~