不可重复读和幻读有什么区别
toqiye 2025-01-21 21:39 9 浏览 0 评论
也不是啥难题,但是上周确确实实有两个简历上八年经验的人没答出来(这两个八年经验的小伙伴,一个是资深一个是高级)。
不过松哥的读者藏龙卧虎,相信在座的各位回答这道题没什么压力。
题目就是:不可重复读和幻读有什么区别
一 不可重复读 (Non-Repeatable Read)
不可重复读是指在一个事务内多次读取同一数据的时候,由于其他事务对这些数据进行了修改并提交,导致读取的结果不一致。换句话说,在同一个事务中,如果两次读取之间有另一个事务修改了数据并提交,那么第一次读取和第二次读取可能会得到不同的结果。
举个简单例子:
- 事务 A 读取行 x = 100。
- 另一个事务 B 更新行 x 为 200 并提交。
- 事务 A 再次读取行 x,发现其值变为 200。
在这种情况下,事务A第一次读取到的数据与第二次读取到的数据不一致,即使两次读取操作都在同一个事务中进行。
这就是不可重复读,可以看到,不可重复读强调的是同一条数据被修改。
二 幻读 (Phantom Read)
幻读是指在一个事务内多次执行相同的查询时,由于其他事务插入或删除了一些记录,导致返回的记录数量或具体内容发生变化的现象。这种现象之所以被称为“幻读”,是因为原本不存在的记录似乎突然出现(或者消失),就像幽灵一样。
举个简单的例子:
- 事务 A 执行 SELECT * FROM table WHERE id > 5,返回 n 条记录。
- 另一个事务 B 插入了一条 id=6 的记录并提交。
- 事务 A 再次执行相同的查询,这次返回 n+1 条记录。
在这种情况下,事务 A 第一次查询到的记录数与第二次查询到的记录数不同,即使两次查询操作都在同一个事务中进行。
总结下就是:
不可重复读和幻读都是在同一个事务中执行相同的 SQL 多次,结果不同。在这个过程中,不可重复读说的是读取的记录被 update,而幻读则强调读取的记录中出现了 insert 或者 delete 操作。
三 连环追问
3.1 不可重复读和幻读分别是如何解决的
这里就涉及到两个关键的概念:MVCC 和 Gap Lock。
MVCC 和 Gap Lock 松哥之前都有专门的文章和大家聊过,这里就不啰嗦了,就和大家捋一捋思路。
MVCC 的核心思路就是在事务启动的一瞬间,给数据库表中的数据拍一张照片,接下来在整个事务执行期间,查询的数据都是从这张照片上查询,这样即使有其他的事务对表中的数据做了修改,也查不到。这样就解决了不可重复读问题了。
从表面上看,MVCC 似乎解决了幻读问题了,因为在当前事务执行期间,别的事务对表的修改都是不可见的,也就是别的事务插入或者删除了数据,当前事务也是不可见的。要从这个角度看,MVCC 确实在一定程度解决了幻读。
但是,这种 MVCC 解决幻读的方式更类似于一种“掩耳盗铃”的方式,因为别的事务还是可以插入和删除,只不过你自己看不见而已。
这块有的小伙伴可能会有疑问,数据修改了不可见就没问题,为啥插入和删除不可见就不行?这里涉及到一个锁的问题。给大家举个简单的案例:
现在 A 事务执行如下 SQL:
update t1 set age=age+1 where id>5;
假设表中有 id 为 6、7、8 的记录,这个例子中,在事务提交之前,按理说 id>5 的记录都会被锁定,也就是 id 为 6、7、8 的记录会被锁定,锁定了就不能操作了。但是,你会发现能够插入 id 为 6 的记录,原因在于 id 为 6 的记录锁定了,但是 6 和 7 之间有缝隙,这个缝隙没锁定,所以可以往缝隙里插入数据,既然可以插入,也就可以删除,这边就造成 id 为 6 的记录似乎没锁定的观感。
当然,实际上这个问题是不存在的,因为 MySQL 中有一个 Gap Lock 就是用来解决这个问题的。
Gap Lock,也就是间隙锁,利用间隙锁将被操作记录两端的缝隙都锁住,这样就直接阻止了其他事务执行 insert 或者 delete 了。
因此,Gap Lock 和 MVCC 实际上互为补充,MVCC 解决了不可重复读问题,同时 MVCC 也解决了快照读的幻读问题,Gap Lock 则从源头上禁止插入和删除,来进一步辅助 MVCC 去解决幻读问题。
当然,说到 Gap Lock,往往还有两个相关的概念,Record Lock 和 Next-Key Lock,这块我就不展开了,不了解的小伙伴可以看下松哥之前的文章,一般来说这几个锁会连在一起提问,包括锁的退化问题都会在这里问到。
3.2 可重复读隔离级别是否存在幻读
有的人可能会歪打正着的把这个问题回答对。
按理说,MVCC+Gap Lock 已经解决了幻读问题了,所以一般理解 MySQL 默认的可重复读隔离级别就不存在幻读问题了。
没错,在可重复读隔离级别下,大部分的幻读都被解决了,但是也有例外。
例如:
- 如果两个事务,事务 A 先进行快照读,然后事务 B 插入了一条记录并提交,再在事务 A 中进行 update 新插入的这条记录,发现可以更新,这就是发生了幻读。
- 事务 A 先进行快照读,然后事务 B 插入了一条记录并提交,在事务 A 中进行了当前读之后,再进行快照读也会发生幻读。
所以,在 MySQL 的 RR 隔离级别下,也是存在幻读问题的。
相关推荐
- Star 17.3k!给它一张屏幕截图,即可一键克隆网页!
-
本文为大家分享一款本周爆火的GPT开源项目。前言你敢信,只凭借着一张屏幕截图即可转换生成HTML/TailwindCSS代码。可以算得上是前端工程师的福音。它就是screenshot-to-...
- AI从截图直接生成代码、前端程序员的福利!
-
简介项目可以将任何屏幕截图或设计转换为干净的代码(支持大多数框架)。来自领先公司的开发人员和设计师使用的排名第一的工具。完全开源,在GitHub上拥有超过35,000颗星。非常受欢迎。各位小伙...
- 一款高颜值、跨平台、自托管的免费开源CRM项目——Twenty
-
前言大家好,这里是可爱的Cherry。作为一个“甲方”,Cherry其实挺知道客户管理的重要的。但是对于客户管理怎么做,以及CRM的作用,我却是一无所知。之前有朋友在评论区留言,说有没有开源的CRM系...
- 解放双手,前端界面再也不用自己写了?
-
随着AI技术的发展,现在有越来越多的尝试将AI应用于UI设计和开发中,以期提高效率和降低成本。今天就给大家介绍一个开源的AI网页生成工具:OpenUIOpenUIOpenUI是一个创...
- 代码调试,教给你(代码调试是什么意思)
-
昨天我和一些朋友一起调试代码,他们做程序员这一行都不太久,我向他们展示了一些代码调试技巧。今天早上我在想,我应该如何教授他们学习代码调试?我在Twitter上发了一条推文说,我从来没有见过任何好的调试...
- Screenshot-to-code:用屏幕截图生成代码
-
Screenshot-to-code是一个简单的工具,可使用AI将屏幕截图、模型和Figma设计转换为干净、实用的代码。现在支持ClaudeSonnet3.5和GPT-4o!Scre...
- next实现原理(next method)
-
Next.js是一个基于React的服务器端渲染(SSR)和静态生成(SSG)框架,它的实现原理涉及多个关键技术点,包括服务端渲染(SSR)、静态生成(SSG)、客户端渲染(CSR)、...
- 可逐步操作的具体流程(可逐步操作的具体流程包括)
-
假设你是一个单人开发者,使用主流技术栈(React+Node.js+MySQL),以下是详细步骤:---###**一、需求分析与原型设计**1.**核心功能清单**-用户能添加、删除、...
- 截图转代码只需1步!你离高效开发只差这款神器
-
引言在现代前端开发中,将设计稿转换为代码是一个既重要又耗时的环节。手动编写HTML结构、调试CSS样式、调整布局对齐,不仅耗费时间,还容易出错。而Screenshot-to-Code这款革...
- web开发 前端 后端(web开发前端后端)
-
区别:1、前端是指用户可见的界面,而后端是指用户看不到的东西,考虑底层业务逻辑的实现,平台的稳定性、性能等。2、前端开发用到的技术有HTML5、CSS3、JS、jQuery、Bootstrap、Nod...
- 手把手教你Dify私有化部署,打造专属AI平台
-
一、Dify是什么?Dify是一款极具创新性的开源LLM应用开发平台,它就像是一把万能钥匙,为开发者们打开了通往生成式AI应用开发新世界的大门。其融合了后端即服务(BackendasS...
- 前后端分离架构设计:提升开发效率与业务支撑力的密钥
-
前后端分离架构设计解析一、定义与核心思想前后端分离是一种将用户界面(前端)与业务逻辑(后端)解耦的架构模式,通过RESTfulAPI或GraphQL实现数据交互。前端专注于视图渲染与交互逻辑...
- Kubernetes最小部署单元Pod(kubernetes最小部署单元)
-
一、Kubernetes与Pod简介在当今云计算和容器化技术盛行的时代,Kubernetes已然成为容器编排领域的中流砥柱。它是一个开源的容器编排平台,由Google基于其内部使用的Bo...
- 【程序员必藏!零基础本地部署DeepSeek大模型保姆级教程】
-
为什么选择本地部署?数据安全:敏感代码/业务数据永不外传闪电响应:局域网推理延迟<100ms,告别云端排队深度定制:自由修改模型代码,打造专属AI助手准备工具(5分钟搞定)1核心工具下载...
- 【Python程序开发系列】使用Flask实现前后端分离(案例)
-
这是我的第398篇原创文章。一、引言随着web开发的不断发展,前后端分离已成为越来越流行的架构设计。Flask是一个轻量级的Pythonweb框架,非常适合用于构建API,然后配合前端框...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- minorgc (62)
- systemproperties (77)
- vue3-template-admin (63)
- electronsqlite3 (65)
- npm版本管理 (61)
- materialtheme (86)
- node-ssh (68)
- 图床搭建 (62)
- vue3addeventlistener (60)
- mybatisselectone (78)
- css圆形进度条 (69)
- androidble蓝牙开发 (62)
- android-gif-drawable (60)
- appender-ref (64)
- springbootmockito (68)
- 依赖注入的方式 (62)
- cookie跨域共享 (63)
- easyexcel导出图片 (77)
- dp数组 (61)
- js获取兄弟节点 (68)
- sysctl-a (60)
- window.target (62)
- apimodel注解的作用 (60)
- window.onerror (66)
- springmvc教程 (65)