MySQL事务隔离级别
事务的基本要素(ACID)
- 原子性(Atomicity):整个事务是一个整体,要么全部成功,要么全部失败;
- 一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态。比如事务执行后仍然能保证数据库的完整性约束,例如:唯一性约束。此外,还需要保证逻辑上的一致性,例如:A转给B 10元,A少了10元,B一定要多了10元,不能出现A+B小于执行前的状况;
- 隔离性(Isolation):隔离性指的是事务与事务之间是相互隔离的,每个事务都感觉不到有其他事务在并发地执行,本文介绍的隔离级别,便是对隔离的程度进行介绍;
- 持久性(Durability):持久性是指一个事务一旦提交,对数据的操作就是永久性的,在数据库遇到故障的情况下也不会产生已经提交的事务被回滚的现象。
什么是事务隔离级别
这个看起来很难懂的概念,其实很好理解。顾名思义,就是事务与事务之间资源隔离的程度。例如:当A事务,修改了TEST表某行数据,那在B事务中读取到的是A事务修改后的数据还是修改之前的数据。
设置事务隔离级别能解决哪些问题
设置合适的事务隔离级别可以解决:脏读、不可重复读、幻读的问题。
脏读
脏读是一种在A事务中读取到了B事务未提交的更改的现象。例如:B事务修改张三的性别为女,A事务读取到了张三的性别,此时如果B事务回滚,那么A事务相当于对一个没有正式确定的“假”数据进行了操作。
1.事务A:开启事务;
2.事务B:开启事务;
3.事务B:更改张三性别为女;
4.事务A:读取张三未提交的更改,此时读取张三性别为女;
5.事务B:回滚事务;
6.事务A:使用了张三性别为女的数据进行其他数据库操作;
不可重复读
不可重复读是指在一个事务中,没有对查询到的数据进行修改,但是再次查询时,却发现数据与上次查询不一致的现象。也就是读取到了其他事务已提交的更改,或未提交的更改。例如:
1.事务A:开启事务;
2.事务B:开启事务;
3.事务A:查询得到三条记录;
4.事务B:插入第四条记录;
5.事务B:提交事务;
6.事务A:查询得到四条记录;
如果第5条语句未执行,此处便查询到第四条记录,就是脏读,也是不可重复读;但是如果第5条语句执行了,才会查询到第四条记录,只能称为不可重复读,不能称为脏读。也就是说脏读也是一种不可重复读,但是不可重复读不一定是脏读。
幻读
幻读是指事务B开启后,事务A新增一条新行或修改一条原有行并提交,事务B此时并不会查询到这条新行或原有行的变更,但是当事务B修改条件覆盖到这一行的时候,会发现这行的存在,并对事务A提交后的状态进行修改,操作后可以查询到这行记录的现象,我们称之为“幻影行”。幻读还有一种特殊的现象,当事务B开启后,事务A将某一行删除并提交,这时事务B查询会发现这条记录仍然存在,但是却无法对其进行修改和删除。
MySQL数据库包含哪些事务隔离级别
读未提交(read uncommit)
读未提交的状态下,B事务会读取到A事务修改后但未提交的更改;这种状态下会引发脏读,不可重复读;
PS:个人认为幻读只有在RR隔离级别下才会出现,(B事务修改了A事务提交的数据后再次查询出现幻读,无论A事务修改后提交或不提交,只要B事务在未修改幻影行的情况下使用快照读,都不会读取到B事务的更改),所以读未提交状态下是否会引发幻读问题还需要进一步讨论。
读已提交(read commit)
读已提交的状态下,B事务会读取到A事务修改并提交的更改;这种状态下不会引发脏读,但会引发不可重复读;关于读已提交状态下是否会引发幻读问题与上文一致。
可重复读(repeatable read)
可重复读状态下,B事务没有修改A事务修改并提交的数据行的情况下,不会出现自身未修改数据,却出现查询的结果集与上次查询结果集不一样的情况。即不会出现不可重复读问题,但会出现幻读问题。
串行(serializable)
串行状态下读写数据会锁住相关行,各事务排队执行,不会出现脏读,不可重复读,幻读的情况。
总结
从上到下四种隔离级别,越往下级别越高,数据库的隔离性和一致性也越高,性能越低。