mysql mvcc和行锁_mysql在RR的隔离级别下,究竟是通过MVCC解决幻读的还是通过行锁的next key算法解决的?...

首先,我们需要搞懂几个隔离级别的意思和每个隔离级别会出现的问题。隔离级别分为:读未提交,读提交,可重复读和可串行化。

读未提交是最低级别的隔离级别,表示当一个事务还没有提交时,他所做的变更就被别的事务读取到;在大部分场景下这显然是不允许的;

为了解决读未提交出现的问题,会将隔离级别设置为读提交,意思是只有一个事务被提交了他做的改变才会被别的事务看到;

但是读提交级别下还是会出现问题,最经典的场景就是银行转账,有这样2个事务A,B同时进行,A事务中账户拥有者将自己的钱从X账户转到Y账户,当钱还没有转到Y账户时,B事务查询了Y账户的钱,这时候事务A结束,钱已经从X账户扣除转给了Y账户,因为是读提交级别,事务提交了,修改也可见了,B事务继续查询自己X账户的钱,因为数据更新,在B事务中用户看到的情况是自己的总金额少了,这就出现了不可重复读的问题。

为了解决不可重复读的问题,出现了可重复读隔离级别,innodb使用MVCC解决了不可重复读的问题,也就实现了可重复读的隔离级别,MVCC机制是为每个事务提供快照隔离,事务执行期间对数据的可见性是有要求的,事务执行期间读到的数据和事务开始执行时的数据是一致,关于可见性有这样的原则:在事务A开始执行时,如果其他的事务B提交了那么数据更改是可见的,如果在事务A执行期间,其他事务B提交了,那么事务B所做的数据更改是不可见的。MVCC的实现原理是基于undo log实现。undo log是用类似链表的方式实现,当事务在RR级别会使用undo log推算当前视图下的数据。

但是在可重复读隔离级别下,还是会出现问题,那就是幻读,当事务在执行期间读数据会分为两种情况,一种是快照读,在这种情况下,读到的数据就是快照数据,看不到其他的数据更改,另一种是当前读,这种情况下会读到更新的数据,这时会对表加上行锁,对于数据(1 2 4 5),当查询小于4的数时候,会读到(1 2),这时候会对1 2加锁,保证数据不会被修改,但是如果其他事务插入了一个3,当事务再更新读的时候就会读到(1 2 3),因为3这个数之前没有出现过也就没法锁住,这时候就出现了幻读,在一个事务的两次当前读的时候出现数据不一致的情况就是幻读。因为没法锁住不存在的行。

为了解决这个问题,innodb使用next-key锁实现,next-key锁=行锁+间隙锁,而间隙锁就是用来锁住这些不存在的数据,锁住(2,3)这个间隙,保证不会被插入新的数据。所以就解决了幻读的问题。

总之,在标准的可重复读(RR)是无法解决幻读问题的,MySQL比较特殊在RR隔离级别也解决了幻读的问题,因为MySQL默认使用innodb作为存储引擎,而innodb使用next key锁解决了幻读的问题。

因为有些东西记不准了,有问题欢迎提出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值