一文搞懂事务隔离级别
前言
在高并发和大负载业务场景下,数据库的事务在此发挥了巨大作用。
本文首先介绍数据库并发时会出现的问题;然后针对这些问题,对事务设置的各个级别;最后,
对各种隔离级别,MySQL数据库又是如何实现的。结合实际案例,阐述个人理解。
1、并发可能产生的问题
我们都知道数据库有四个特点,就是ACID,分别是原子性、一致性、隔离性及持久性,本文主要讲隔离性。所谓隔离性是指各个事务之间互不影响,彼此独立。最理想的情况下,每个事务在开始和结束时,对数据表中记录的操作的都能完全一致,不会存在脏读、不可重复读和幻读的问题,达到序列化的隔离级别(为整个表加锁)。但是现实场景中,一般不会这样设置数据库隔离级别。
1.1 脏读
脏读就是事务A读到了事务B并未提交的数据,也可以说是事务A读到了不该独到的数据,
比如下图就是事务A读到了事务B的原本打算回滚的数据。
1.2 不可重复读
不可重复读的意思是事务A第一次读取到这条数据,再读的话,
由于事务B修改了数据,导致事务A第二次读到的D1和第一次读到的D1不一样。如下图:
1.3 幻读
幻读的意思是,事务A两次查询到的数据结果不一致,如下图示,
事务A第一次查到D1,第二次查到了D1,D2,而且是在一个事务中,这种情况就叫幻读。
2、MySQL的隔离级别
2.1 读未提交
该隔离级别最低,上面提到的问题在这种级别的隔离的数据库中,都会出现
2.2 读已提交
这种情况可以防止出现脏读问题
2.3 可重复读
这是MySQL的默认隔离级别,可以防止出现脏读和不可重复读的问题
2.4 串行化
3、实现隔离的方式
MySQL上实现可重复读的隔离级别,可以通过加锁的方式来实现
3.1 共享锁
为表记录加上读锁
3.2 排它锁
为表中记录加上写锁
实际上实现隔离的方式是通过MVCC
3.2 MVCC
MySQL中采取的就是这种方式,按照之前的理论,实现可重复读的方式就是给表中记录加上读锁,不允许其他事务修改当前的事务正在读的数据,但是MVCC并不是使用枷锁的方式,而是使用快照的方式来实现同样的效果,不论什么时候去读,同一个事务第一次看到的数据和最后一次看到的数据都是一样的。这种快照的方式十分巧妙,每个事务都可以看到自己想看的,通过一个ReadView的东西
总结
数据库中事务没提交之前,MVCC一直存在
所以验证步骤,就是开启多个事务,看看各个事务之间有没有影响,尤其在进行insert或者update操作的时候,还有delete的操作,这些关键字,在MySQL中都是有特殊处理的。
验证insert into或者update操作的时候,只要事务没有被提交,那么其他事务就看到的一直是一样的数据
而且当前事务没有提交之前,其他事务也不能对这条数据进行其他任何操作。