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

可重复读(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隔离级别支持)

相关推荐
over6973 小时前
从 LLM 到全栈 Agent:MCP 协议 × RAG 技术如何重构 AI 的“做事能力”
面试·llm·mcp
SuperEugene4 小时前
Vue状态管理扫盲篇:如何设计一个合理的全局状态树 | 用户、权限、字典、布局配置
前端·vue.js·面试
Sailing6 小时前
🚀 别再乱写 16px 了!CSS 单位体系已经进入“计算时代”,真正的响应式布局
前端·css·面试
SuperEugene9 小时前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试
Hilaku9 小时前
我会如何考核一个在简历里大谈 AI 提效的高级前端?
前端·javascript·面试
前端Hardy9 小时前
别再用 $emit 满天飞了!Vue 3 组件通信的 4 种正确姿势,第 3 种 90% 的人不知道
前端·vue.js·面试
我叫黑大帅9 小时前
前端如何利用 GitHub Actions 自动构建并发布到 GitHub Pages?
前端·面试·github
我叫黑大帅9 小时前
前端总说的防抖与节流到底是什么?
前端·javascript·面试
掘金安东尼9 小时前
从平面到空间:用 React Three Fiber 构建 3D 产品网格
前端·javascript·面试
swipe10 小时前
#用这 9 个浏览器 API,我把页面从“卡成 PPT”救回到 90+(每个都有能直接抄的例子)
前端·javascript·面试