InnoDB可重复读隔离级别下如何避免幻读

InnoDB可重复读隔离级别下如何避免幻读

主要通过以下两种情况避免幻读

  • 表象:快照读(非阻塞读)伪MVCC
    表象避免幻读,是RR下查找数据,第一次读取创建快照,后面读取都是读取本次快照,不论别的事务是否提交相关更改,我们都不知道,掩耳盗铃
  • 内在:next-key锁(行锁+gap锁)
    上了锁,你别的操作不会修改我锁定的区间了,我就不会幻读

首先我们理解下面两个概念,当前读和快照读

  • 当前读:select xxx lock in share mode,select xxx for update、update、delete、insert
    当前读就是加了锁(共享、排他都算)的增删改查,加锁后的记录不能被别的事务修改
    在这里插入图片描述
  • 快照读,非serializable模式下select为快照读
对主键索引或者唯一索引会用GAP锁么?
GAP区间

打开MySQL官网,我们看看它对gap区间的描述,分段进行区间划分
在这里插入图片描述

实战验证

创建一个表,id(唯一键unique_id)、name(主键),插入数据ID为1、2、3、5、6、9,name字段随意
我手动划分一下GAP区间【1,2】【2,3】【3,5】【5,6】【6,9】【9,+∞】

  1. 如果where条件全部命中,不会使用GAP锁,只会加记录锁(行锁)
    RR模式下,S1、S2开启事务,S1查询id为9,S2插入id为9,会被blocking,插入id为7则不会锁,说明他开的是行锁,因为锁9,GAP锁会锁住【6,9】区间
    在这里插入图片描述
  2. where条件未全部命中、全不命中会开GAP锁
    RR模式下,S1、S2开启事务,S1查询id为5、7、9(其中没有id为7的数据,部分命中),S2插入id为8,会被blocking,因为此时使用GAP锁,锁住区间【5,6】【6,9】
GAP锁会用在非唯一索引或者不走索引的当前读
  • 非唯一索引
    在这里插入图片描述
    如上图所示,S1、S2开启事务,S1查询id=9,区间【6,9】【9,11】被锁,想执行插入id为此区间内的,都被blocking
  • 不走索引
    在这里插入图片描述
    如图所示,id不是索引了哈!!,S1删除id=9,全表都被锁了(所有区间),尽量避免这种情况,会影响性能
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,InnoDB存储引擎在可重复读(Repeatable Read)隔离级别下采取了一些机制来解决幻读问题。 幻读是指在一个事务中多次执行相同的查询,但是得到的结果集却不同,这是由于其他事务在查询过程中插入或删除了符合查询条件的数据所导致的。为了解决幻读问题,InnoDB引擎实现了多版本并发控制(MVCC)机制,它通过在每行数据上添加版本号来实现数据的快照读取。 在可重复读隔离级别下,当一个事务开始时,InnoDB会创建一个一致性视图(Consistent Read View),该视图记录了事务开始时数据库中所有数据的版本号。在事务执行期间,所有的查询操作都会基于这个一致性视图来读取数据,而不受其他事务的修改影响。 当其他事务插入新数据或者删除已有数据时,InnoDB会在事务读取的行上添加间隙锁(Gap Lock),阻止其他事务在这个范围内插入新数据。这样可以保证在同一个事务中多次执行相同查询时,得到的结果集是一致的,避免幻读问题。 需要注意的是,对于某些特殊情况下的范围查询,InnoDB引擎可能需要升级间隙锁为锁定整个范围的 next-key 锁,以防止幻读问题。这些情况包括使用范围约束的 SELECT ... WHERE、SELECT ... ORDER BY 和 SELECT ... GROUP BY 查询。 因此,InnoDB存储引擎在可重复读隔离级别下通过MVCC和间隙锁机制,能够有效地解决幻读的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值