面试之可重复读是否可以解决幻读

可重复读(repeatable read)定义:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据时是一致的。

不过理论上 是会出现幻读的,简单的来说幻读指的是当用户读取某一范围的数据行时,另外一个事务又在该范围插入了新行,当用户再次读取该范围的数据时会发现 出现新的幻影行。

注意可重复读隔离级别下,普通的查询是快照读,是不会看到别的事物插入的数据的。因此,当前在"当前读"下才会出现 幻读。

在mvcc并发控制中,读操作可以分为两类:快照读 和当前读。

快照读:

快照读 :是 在读取的数据 时 不是读取最新版本的数据。而是基于历史版本读取的一个快照信息(mysql 读取 undo log 历史版本),快照读可以使用普通的select 读取时不用在对表数据 及逆行加锁,从而解决了因为数据库表的加锁而导致的两个问题

1:解决了因加锁导致的修改数据时无法对胡数据读取问题

2:解决了因加锁导致读取数据时无法对进行修改的问题。

当前读:读取的数据最新的数据,当前读和快照读不同,因为读取最新的数据而且保证事务的隔离性,所以当前读 是需要对数据进行加锁的。

下面举个列子:

表结构

id key value
0 0 0
1 1 1

假设 select * from where value=1 for update,只在这一行加锁(注意这只是假设),其它行不加锁,那么就会出现如下场景:

Session A的三次查询Q1-Q3都是select * from where value=1 for update,查询的value=1的所有row。

  • T1:Q1只返回一行(1,1,1);

  • T2:session B更新id=0的value为1,此时表t中value=1的数据有两行

  • T3:Q2返回两行(0,0,1),(1,1,1)

  • T4:session C插入一行(6,6,1),此时表t中value=1的数据有三行

  • T5:Q3返回三行(0,0,1),(1,1,1),(6,6,1)

  • T6:session A事物commit。

其中Q3读到value=1这一样的现象,就称之为幻读,幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行

产生幻读的原因是:行锁只能锁住行,但是新插入记录的这个动作,要更新的是记录之间的'间隙'。因此,Innodb 引擎 为了解决 可重读隔离级别下 当前读而造成的幻读问题,就引出了 next_key锁,就是记录锁和 间隙锁的组合。

1:RecordLock锁:锁定单个行记录的锁。

2:CapLock锁:间隙锁,锁定索引记录间隙,确保索引记录的间隙不变(范围锁,RR隔离级别支持)

3:Next-key Lock 锁: 记录时锁和间隙锁组合。锁住数据的同时,并且锁住 数据前后范围。(记录锁+范围锁,RR隔离级别支持)

相关推荐
Randyliu6 分钟前
20260508-Agent搭建记录以及对ReAct框架的理解
面试·agent
ZzT1 小时前
公司用 AI 筛简历,他写了个 AI 帮你挑公司
面试·aigc·ai编程
PBitW2 小时前
GPT训练我的第四天,被打惨了!!!😭😭😭
前端·javascript·面试
云技纵横6 小时前
@Transactional 到底要不要加 rollbackFor?一次数据不一致事故讲清楚
后端·面试
Moment6 小时前
牛逼,NextJs 从 16.3 开始全面拥抱 Agent Native 🥰🥰🥰
前端·后端·面试
胡萝卜术7 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
胡萝卜术8 小时前
从暴力到Z字形消元:力扣240「搜索二维矩阵II」的降维打击之路
前端·javascript·面试
洛卡卡了1 天前
我们在用 AI 写代码时,为什么建议要好好维护 AGENTS.md 呢?
面试·agent·claude
PBitW1 天前
GPT训练我的第三天,明白了应该咋说满分回答!😕😕😕
前端·javascript·面试
自由路飞1 天前
RAG 混合检索深挖:BM25 和向量分数为什么不能直接相加?
面试