前言
在博文(事务与隔离—概念篇)中,笔者讲述了MySQL中有关事务的基本概念,本文将重点讲诉事务控制中的相关SQL命令,并尽量模拟相关例子。
事务控制语言
MySQL有关事务控制SQL语句(关键词)如下:
SET AUTOCOMMIT:自动提交;
START TRANSACTION (or BEGIN):显示的开始一个新的事物;
SAVEPOINT:设置一个保存点,用于后续(回滚)引用;
COMMIT:提交,永久保存事务修改;
ROLLBACK:取消当前事务的所有修改(回滚);
ROLLBACK TO SAVEPOINT:回滚到savepoint;
RELEASE SAVEPOINT: 删除所有保存点;
以上SQL语句中,除SET AUTOCOMMIT属系统配置外,其他均为事务中的逻辑控制语句,一个全面的事务控制样例图如下:
AUTOCOMMIT 自动提交
MySQL默认开启AUTOCOMMIT模式,即将每个SQL语句看作一个事务,用户可以使用BEGIN或START TRANSACTION覆盖此自动提交,而新开启一个事务。
命令
- 查看AUTOCOMMIT模式
mysql> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.33 sec)
- 设置AUTOCOMMIT模式(会话级、全局级)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.01 sec)
测试
首先设置会话的autocommit为OFF/0,并插入两行数据(test_1、test_2),未提交,但select能显示出来。之后,通过rollback回滚上述修改,发现此前insert的语句不存在了。此处是否代表发生了幻读??
mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
mysql> insert into zavier.char_test (char_col) values ('test_2');
Query OK, 1 row affected (0.00 sec)
mysql> select * from zavier.char_test;
+----------+
| char_col |
+----------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
| test_1 |
| test_2 |
+----------+
7 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.04 sec)
mysql> select * from zavier.char_test;
+----------+
| char_col |
+----------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
+----------+
5 rows in set (0.00 sec)
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)
Implicit Commit隐式提交
隐式提交表示没有明确的commit语句,对数据库的修改还是被commit了,无法rollback。MySQL中一般非事务性语句都会引起隐式提交,如:
- DFL:alter、create、drop等;
- administrative statement:grant、revoke、set password等;
一般建议将所有的非DML都视为引起隐式提交。
SAVEPOINT保存点
The SAVEPOINT statement sets a named transaction savepoint with a name of identifier. If the current transaction has a savepoint with the same name, the old savepoint is deleted and a new one is set.
SAVEPOINT语句用于设置事务的一个命名保存点,用于后续ROLLBACK TO SAVEPOINT 语句回滚到此保存点;
All savepoints of the current transaction are deleted if you execute a COMMIT, or a ROLLBACK that does
not name a savepoint.
注意:保存点为事务层的概念,出了事务,所有的保存点都会被删除。
一个完整的事务例子
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from zavier.char_test;
+----------+
| char_col |
+----------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
+----------+
5 rows in set (0.00 sec)
mysql> insert into zavier.char_test (char_col) values ('before_save');
Query OK, 1 row affected (0.00 sec)
mysql> select * from zavier.char_test;
+-------------+
| char_col |
+-------------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
| before_save |
+-------------+
6 rows in set (0.00 sec)
mysql> savepoint sp1;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into zavier.char_test (char_col) values ('after_save');
Query OK, 1 row affected (0.00 sec)
mysql> select * from zavier.char_test;
+-------------+
| char_col |
+-------------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
| before_save |
| after_save |
+-------------+
7 rows in set (0.00 sec)
mysql> rollback to savepoint sp1;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from zavier.char_test;
+-------------+
| char_col |
+-------------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
| before_save |
+-------------+
6 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.24 sec)
mysql> select * from zavier.char_test;
+-------------+
| char_col |
+-------------+
| string1 |
| string2 |
| string3 |
| string4 |
| string4 |
| before_save |
+-------------+
6 rows in set (0.00 sec)
说明:
- 首先通过begin语句显式的开启了一个事务(以关闭自动提交);
- 第一次select查看表内容;
- 第一次insert插入'before_save'内容;
- 第二次select查看表内容,出现'before_save' ----- 幻读;
- savepoint设置保存点;
- 第二次insert插入'after_save'内容;
- 第三次select查看表内容,出现'before_save'、'after_save' ----- 幻读;
- rollback to savepoint sp1;回滚到保存点1;
- 第四次select查看,'after_save '被回滚掉;
- commit;提交事务
- 第五次select,果然没有'after_save '内容
总结
本文给出了MySQL中支持的事务控制语句,包括AUTOCOMMIT、savepoint、rollback(rollback to savepoint XX)、begin、commit等,深刻的掌握的这些语句可使读者在后续实际工作中面对复杂的事务控制逻辑做到胸有成竹,游刃有余。