关于数据库隔离级别为RR(可重复读)下是否解决幻读问题

 一.数据库隔离级别

隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

     ---在传统的数据库的执行引擎中,标准的可重复读是没有彻底解决幻读的,这也是大家经常说的数据库的可重复读并没有彻底解决幻读的原因


 上述为官方对幻读的解释:只要在一个事务中,第二次select多出了row就算幻读

下面简单的介绍一下RR幻读的解决方式

      在一个事务中,查询时分为快照读和当前读,标准的可重复读没有彻底解决幻读的意思也就是:快照读解决了幻读,但是当前读并没有解决,所以总体上来说并没有彻底解决幻读

1.MVCC

      在快照读当中,解决幻读是使用MVCC来解决的,MVCC全称Multi-Version Concurrency Control,即多版本的并发控制协议,为什么说是多版本呢,见下图:

 

undo log中的版本链是指一条数据被多个事务一次修改而形成的一个历史记录版本,undo log和redo log是数据库对于原子性,持久性,隔离性的实现,本文不赘述。

       RR隔离级别下,手动启动一个事务,进行select操作,他会生成一个readview模板,可以理解为将当前数据库的数据复制一份,在当前事务中,之后不管进行多少次select查询,都是在模板中去取数据,所以不管数据库中是否对数据进行了改变,都不会影响当前事务数据的读取,从而避免了幻读。

       但是如果在当前事务中使用了下图语句进行当前读:

for update是进行当前读的操作,他会重新从数据库去加载当前的最新的数据,每执行一次加载一次,如果在此时,另外一个事务为数据库添加了一个事务,再进行查询,会发现查询的数据与之前相比多了或者少了,这也就是幻读现象。

2.Mysql的innodb引擎彻底解决RR下的幻读现象

       上述都是在标准的可重复读下的情况,在innodb存储引擎中对可重复读进行了改造,为当前读加上了 Next-key Lock,也就是间隙锁和行锁的统称,行锁防止了别的事务修改或者删除,间隙锁防止了别的事务新增。也就是在进行上面的for update事务中,其他的事务不能对数据进行增删操作,执行会报错

 

注意:如果A事务如果进行了快照读,然后通过B事务对数据就行增删,然后紧接着A事务进行当前读操作,两次读取数据不一致,不能算作幻读,因为幻读定义是同一个select语句,快照读和当前读的查询语句是不一样的

总结:

  1.  在标准的RR下并没有彻底解决幻读,但是在Mysql的innodb引擎中彻底解决了
  2.  innodb通过 Next-Key lock解决的幻读问题,其实也就是阻塞串行化了
  3. 不能把快照读和当前读在一个事务中进行比较是否出现幻读,两者不是同一个select,不满足幻读的官方定义
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值