MySQL事务
事务特性
- 原子性:事务是一个原子操作。在当原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
- 一致性:事务开始到结束的实践段内,数据都必须保持一致状态。
- 隔离性:数据库提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。
- 持久性:事务完成后,它对于数据的修改一是永久性的,即使出现系统故障也能够保持。
事务常见问题
-
脏读(Dirty Reads)
原因:事务A读取了事务B已经修改但尚未提交的数据。若事务B回滚数据,事务A的数据存在不一致性的问题。
-
不可重复度(Non-Repeatable Reads)
原因:事务A第一次读取最初数据,第二次读取事务B已经提交的修改数据。导致两次读取数据不一致。不符合事务的隔离性。
-
幻读(Phantom Reads)
原因:事务A根据相同条件第二次查询到事务B提交的新增或删除数据,两次数据结果集不一致。不符合事务的隔离性。
不可重复读的重点是修改,在一次事务中,同样条件下,两次读取发现值不一样了
幻读的重点是新增或删除,在一次事务中,同样条件下,两次读取发现记录数变了
事务的隔离级别
-
READ UNCOMMITTED(未提交读)
事务中的修改,即使该事务未提交,对其他的事务也是可见的。可以读取到其他事务中的数据,又被成为脏读,在时机数据库事务中,脏读会破坏数据的一致性,对业务的影响大,所以一般不推荐事务使用READ UNCOMMITED隔离级别。
#事务 1 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;#设置会话事务隔离级别为 READ UNCOMMITTED start transaction; select * from xxx;#此时为空,事务未提交 #事务 2 start transaction; insert into xxx values(x);#未提交事务中,插入数据 #事务 1 select * from xxx;#读取到事务2中未提交的数据
-
READ COMMITTED(提交读)
在提交读级别中,数据库将保证如果一个事务没有完全执行成功(commit完成),事务中的操作对其他事务是不可见的。在该隔离级别下,虽然杜绝了脏读的发生,但是还是会存在着不可重复读及幻读的问题。
不可重复读发生在事务A读取了一行数据,事务B接着修改或删除了改行数据并提交,当A事务再次读取同一行数据的时候,发现数据已经修改或者被删除。见下方案例
#事务 1 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;#设置事务隔离级别为READ COMMITTED start transaction;#开启事务 select * from xxx where id=1;#第一次查询 #事务 2 update xxx set xxx=newvalue where id=1;#事务 2更新了第一次查询结果的值 #事务 1 select * from xxx where id=1;#事务 1第二次查询结果和第一次不一致
幻读发生在事务A读取了满足条件的一个数据集,事务B此时插入了一行或者多行满足A查询条件的数据并提交,当事务A再次采用相同的条件进行读取时,得到与第一次不同的结果集。见下方案例
#事务 1 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;#设置事务隔离级别为READ COMMITTED start transaction;#开启事务 select * from xxx;#第一次查询 #事务 2 start transaction;#开启事务 insert into xxx values(2);#添加数据 commit;#提交事务 #事务 1 select * from xxx;#两次查询结果记录数不一致
-
REPEATABLE READ(可重复读)
REPEATABLE READ是MySQL的默认隔离级别,它确保同一个事务的多个实例在并发读取数据时,会看到同样的数据。按照该隔离级别的定义,还是会存在幻读的问题。MySQL通过InnoDB存储引擎的多版本并发控制机制(MVVC)解决了部分该问题的场景,但任然存在。
#事务 1 #由于REPEATABLE READ是MySQL的默认隔离级别,因此这里就不设置了 start transaction;#开启事务 select * from xxx;#第一次查询 #事务 2 start transaction;#开启事务 insert into xxx values(2);#添加数据 commit;#提交事务 #事务 1 select * from xxx;#两次查询结果记录数不一致
-
SERIALIZABLE(串行化)
串行化是最严格的隔离级别,通过给事务中的每次读写操作都加锁,保证了不产生任何脏读、不可重复读以及幻读问题,但是随之引入的是大量的读超时以及锁竞争,导致数据库的性能严重下降。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | 允许 | 允许 | 允许 |
READ COMMITTED | 不允许 | 允许 | 允许 |
REPEATABLE READ | 不允许 | 不允许 | 允许 |
SERIALIZABLE | 不允许 | 不允许 | 不允许 |
事务的控制语句
BEGIN/START TRANSACTION 显示开启事务
ROLLBACK 回滚结束用户的事务,并撤销正在进行的所有未提交的修改
COMMIT COMMIT会提交事务,并使已对数据库进行的所有修改成为永久性的
SAVEPOINT point 在事务中创建一个保存点point,一个事务可以有多个保存点
RELEASE SAVEPOINT point 删除一个事务的保存点point
ROLLBACK TO point 回滚事务到保存点point
SET TRANSACTION 设置事务的隔离级别
SET AUTOCOMMIT=1/0(on/off) 开启或禁止自动提交
参考链接
https://zhuanlan.zhihu.com/p/85990712
http://blog.itpub.net/31556440/viewspace-2642668/