MySQL 事务 (Transaction)
MySQL 事务 (Transaction)
基本条件和语法
事务的四个条件(ACID):
原子性(Atomicity)
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性(Consistency):
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性(Isolation,又称独立性):
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。
事务隔离级别包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性(Durability):
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
事务控制语句:
BEGIN 或 START TRANSACTION 显式地开启一个事务;
COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的;
ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;
SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT;
RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;
ROLLBACK TO identifier 把事务回滚到标记点;
SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
MYSQL 事务处理的两种方法:
用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始一个事务,ROLLBACK 事务回滚,COMMIT 事务确认
直接用 SET 来改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0 禁止自动提交, SET AUTOCOMMIT=1 开启自动提交
例子
#成功提交事务
mysql> begin; # 开始事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)
mysql> select * from runoob_transaction_test;
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.01 sec)
#回滚事务
mysql> begin; # 开始事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
mysql> rollback; # 回滚
Query OK, 0 rows affected (0.00 sec)
mysql> select * from runoob_transaction_test; # 因为回滚所以数据没有插入
+------+
| id |
+------+
| 5 |
| 6 |
+------+
2 rows in set (0.01 sec)
隔离级别
事务隔离级别包括读未提交(Read uncommitted)、读提交(Read committed)、可重复读(Repeatable read)和串行化(Serializable)。MySQL 默认为可重复度 Repeatable read。
讨论隔离级别的场景,主要是在多个事务并发的情况下
可能出现的问题:
- 脏读:事务B可能读取了事务A尚未提交的数据
- 不可重复读:事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
- 幻读:事务A读取一次后,事务B插入一行满足事物A的新数据,当事物A再次进行相同的条件查询会看见事物A插入的新数据。
隔离级别 | 可以解决的问题 | 默认采用的数据库 |
---|---|---|
读未提交 Read Uncommitted | - | - |
读提交 Read Committed 事务A不能读取事务B已修改但是尚未提交的数据值。 | 脏读 | SQL Server , Oracle |
重复读 Repeatable Read 事务A开始读取后,事务B不能对该记录进行修改 | 脏毒 不可重复读 | MySQL |
序列化 Serializable 在A事务完成之前,事务B不能向事务A已读取的范围插入新行 | 脏毒 不可重复读 幻读 |