mysql可重复读的实现

开篇先引用一篇文章解释下 快照读、当前读 的概念,以及快照读的RR实现原理

正确的理解MySQL的MVCC及实现原理

接下来分析下当前读的RR实现原理,本质是通过锁来实现的。

mysql的锁机制

行锁&表锁
mysql的官方文档上,有提到四种锁(S、X、IS、IX)。其中IS和IX都是表级锁,S和X既有表级锁又有行级锁。

间隙锁
除了上述四种锁以外,mysql在innodb引擎中,还引入了 gap lock (间隙锁),间隙锁本身是不互斥的,但是间隙锁的存在,会导致DB索引之间的间隙被锁住,无法进行数据的插入。关于何为“间隙”,其实跟mysql的索引树的结构有关,mysql的索引是B+树,B+树的叶子结点,是靠指针相连在一块的,两个相邻叶子节点的间隙,即为间隙锁加锁的地方,需要注意的是,头尾节点相邻的无穷区间,也是间隙。当表新插入数据的时候,反馈在索引树上,必然有新的叶子节点落在原来的某个间隙上,具体会落到什么间隙上,其实是可以预见的。比如表中数据如果已经存在1,2,4,5。此时再插入数据3的话,则3必定出现在2与4之间。

基于上述描述,在RR隔离级别下,考虑一个case
A事务
1.begin
2.update table set val=‘xxx’ where id>=1 and id<=5;
3.commit;

B事务
1.begin
2.insert table (id,val) value(3,“yyyy”);
3.commit;

如果A事务先进行2阶段,事务未提交情况下,B事务执行完毕。此时A事务再次执行2阶段,update 执行当前读的时候,发现符合where条件的数据多了一条id=3的,符合幻读的描述 。即然RR隔离级别解决了幻读,为什么幻读还会出现呢?
可以看到,这个问题是不能用MMVC来解决的,如果在实际DB中执行这两个事务,在A事务提交前,B事务的2阶段是无法执行的,线程处于阻塞状态,因为A事务的update 已经锁住了叶子节点1和叶子节点5之间的所有间隙,包括其中的叶子节点。在这些间隙中插入新数据是不被允许的。由这些叶子节点和间隙锁组合成了新的一种锁类型 next-key lock(临键锁)。这种锁是RR隔离级别下,innodb引擎中的默认锁实现。
用锁机制来实现当前读的RR,即不允许修改,读多少次结果都是一样的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值