可重复读如何解决幻读

article/2025/9/28 10:23:55

学习之前的疑问:
可重复读的概念 与 不可重复读的概念
行锁+gap锁(间隙锁)
快照读 与 当前读区别
快照读中的MVCC
当前读中的gap锁 和 行锁

前几天面试时被问到了mysql可重复读如何解决幻读的问题,之前脑子中的概念只有增加了共享锁和排他锁进行避免,没有实践或者清晰的概念,今天首先实践验证和理解mysql下可重复读对于幻读的避免和原理。参考博文:https://blog.csdn.net/Y0Q2T57s/article/details/103708206

首先整体了解数据库的隔离级别:

读未提交 -------------- 可能产生脏读,幻读,不可重复读
读已提交(不可重复读)----------------- 可能产生不可重复读,幻读
可重复读 ---------------------------------可能产生幻读
序列化 -----------------------------------无

可重复度和不可重复读

  • 概念:
  1. 不可重复读指的是事务1和事务2同时获取数据,在此时事务2进行插入行或者修改行操作,这时事务1再次进行select时会发现多了几行数据或者数据不一致,这就称为幻读
  2. 可重复读,也就是在RR隔离级别下,为了避免不可重复读的幻读情况发生,事务2修改数据的结果 在事务1是无法获取的,进行了隔离,这个实现后面会介绍到MVCC。

在了解了mysql的几个隔离级别后,针对可重复读是如何防止产生幻读的?

  • 先来通过实践验证简单的:如何防止如不可重复读的情况
    首先创建一张表
Create Table: CREATE TABLE `dept` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8

开启两个事务
在这里插入图片描述
表中没有数据,现在我们往右边事务中插入一条数据,如果在不可重复的隔离级别下在左边事务再select会发现新插入数据,而可重复读的情况下左边的select数据一直不变。
在这里插入图片描述

  • 解释:这一现象的原理是RR即可重复读的隔离级别下用到了MVCC,多版本并发控制,每个事务在开启时会有一个版本号,不管其他事务如何数据,而当前事务中的版本号不会变化,所以左边事务一直select的数据都是一个版本中的,所以不会读取到右边事务插入后的数据。
在左边事务中发现内容为空,我们插入一个id=29的数据行,看看会发生什么

在这里插入图片描述

  • 解释:这是什么情况呢?这是因为在select时会使用到快照读,但是在例如上面insert时会进行当前读, 如字面意思解释,快照读即事务开启时产生的版本号一般,进行了数据表当前的数据“复制”,在事务中select时只会用到快照读,但是如果进行insert/ update / select … for update 这种语句时,会进行当前读,访问数据表中“最新”的数据,这时尽管右边的insert未提交,但当前读还是会读到, 那么根据报错的信息,lock,得知在右边事务insert一行之后会进行加锁 (X锁),不允许其他事务修改,但能读取当前数据(当前读)即获取当前行的S锁,左边insert需要在右边事务释放锁之后才能进行insert/update操作(commit或者rollback)

下面对X锁和S锁进行学习

  • X锁称为排他锁(悲观锁) ----- 对目标行添加当前事务的X锁,即可修改或删除操作
  • S锁称为共享锁(共享锁) ----- 对目标行添加当前事务的S锁,即可读当前行的数据
    S锁是可以兼容的,即多个事务都可以持有对某行的读权限, 而X锁是不兼容的,即最多只有一个事务能获取当前行的修改或删除权限, 若其他事务需要获取X锁,必须等当前拥有X锁权限的事务释放X锁才能获取。

而上面出现的情况是因为 右边事务在Insert时便对id=29的行数据添加了X锁,而这时左边事务要对id=29的行进行X操作,那么首先需要获取已经被右边事务拥有的X锁,那么需要等右边事务释放X锁权限(commit或者rollback)才能获取.

  • 还有如下情况: 在这里插入图片描述
    如上面解释,如果右边事务插入id=99的数据行,如果左边事务修改id范围不包含99的话应该可以操作,但是左边事务也遇到了锁,导致不能修改成功,这是因为上面的X锁不仅包含了当前一行,还有(-无穷大, 10) 和 (10,+无穷大)加锁, 在左边事务update时,会遇到间隙锁(GAP锁),导致需要等待右边事务释放锁后才能更新。

通过上面可重复读中几种情况,总结:可重复读本身还是存在幻读的,但是因为在可重复读上添加了NEXE-KEY锁(即行锁+gap锁)避免了幻读的产生。


http://chatgpt.dhexx.cn/article/mhLADQom.shtml

相关文章

MySQL(四)—MVCC实现可重复读的原理

文章目录 一、MVCC概况二、MVCC实现原理1.两或三个隐藏字段。2.undo log3.一个数组4.ReadView 三、举例验证MVCC原理参考文献 一、MVCC概况 MVCC是什么?MVCC即多版本控制协议,InnoDB实现了MVCC作版本控制,防止不该被当前事务看到的数据看到。…

可重复读

《循序渐进DB2-系统管理、运行维护与应用案例》第10章锁和并发,本章首先介绍了通用的事务概念,并指出DB2在用户读取、写入数据时的加锁策略、锁模式、兼容性等。本章还介绍了在并发控制中常碰到的4种数据异常现象,同时讲述了DB2如何使用锁克服…

mysql不可重复读和重复读_脏读、幻读、不可重复读的区别是什么

脏读、幻读、不可重复读的区别:1、脏读就是指当一个事务正在访问数据,并且对数据进行了修改;2、不可重复读是指在一个事务内,多次读同一数据;3、幻读是指当事务不是独立执行时发生的一种现象。 【相关学习推荐&#xf…

Mysql如何实现可重复读

首先对于mysql来说相信也并不陌生,mysql默认的事务的隔离级别是3,即可以实现可重复读,那mysql又是怎样实现可重复读的呢? 下边进行简单的介绍 这里就要提到了mvcc,即多版本并发控制 首先先来看一个事务的执行图 此时…

MySQL 可重复读隔离级别,完全解决幻读了吗?

我在上一篇文章中提到,MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了),解决的方案有两种: 针对快照读(普通 select 语句)&am…

MySQL可重复读-问题实践

MySQL可重复读之幻读问题 MySQL事务存储引擎InnoDB的默认隔离级别为可重复读,在该隔离级别下,可以很大程度上避免幻读的问题,完全避免脏读和不可重复读问题,接下来通过实际的测试看看这些场景是否真的能够被完全避免 模拟均基于…

可重复读下的幻读

在事务执行过程中,另一个事务将新记录添加到正在读取的事务中时,会发生幻读(事务隔离级别为可重复读REPEATABLE-READ)。当执行SELECT … WHERE语句时未对where范围锁定,则可能会发生幻读。幻读是不可重复读的一种特殊情…

MySQL可重复读应用场景_mysql-repeatable read 可重复读隔离级别-幻读实例场景

本文详解 repeatable read 可重复读 隔离级别产生的影响(幻读) -- SERIALIZABLE serializable 序列化 ;一个个事务排成序列的形式。事务一个挨一个执行,等待前一个事务执行完,后面的事务才可以顺序执行 -- REPEATEABLE READ repeatable read …

MySQL可重复读级别能够解决幻读吗

引言 之前在深入了解数据库理论的时候,了解到事物的不同隔离级别可能存在的问题。为了更好的理解所以在MySQL数据库中测试复现这些问题。关于脏读和不可重复读在相应的隔离级别下都很容易的复现了。但是对于幻读,我发现在可重复读的隔离级别下没有出现&…

mysql不可重复读和重复读_MySql隔离级别:RU / RC / RR / S + 脏读 / 不可重复读 / 幻读 / 可重复读...

MySQL 事务 本文所说的 MySQL 事务都是指在 InnoDB 引擎下,MyISAM 引擎是不支持事务的。 数据库事务指的是一组数据操作,事务内的操作要么就是全部成功,要么就是全部失败,什么都不做,其实不是没做,是可能做…

mysql可重复读 加锁_mysql可重复读隔离级别加锁分析

问题 myql可重复读隔离级别下可能会导致插入阻塞,问题复现如下 表中有3列都是int类型 其索引情况如下: id为主索引,c,d为普通索引 现在开始制作问题: 在这里我分别开启两个事务:第一个事务中执行一个update 语句更新一…

可重复读实现原理

不可重复读:事务A多次读取同一个数据,事务B在事务A多次读取的过程中,对数据作了更新,导致事务A多次读取同一个数据时,结果不一致。(比如修改行数据) 幻读:事务A 按照一定条件进行数据…

mysql “可重复读“ 解决了哪些问题,没有解决哪些问题?

可重复读解决了更新带来的不可重复读问题,但是没有解决插入或者删除带来的幻读问题。这句话,是老八股文了。 但真实情况是这样的吗?这个验证不麻烦,我们可以动手来验证一下。 我使用的是免安装版本的windows mysql8.0.31&#xff…

透彻解读mysql的可重复读、幻读及实现原理

目录 一、事务的隔离级别 二、mysql怎么实现的可重复读 举例说明MVCC的实现 MVCC逻辑流程-插入 MVCC逻辑流程-删除 MVCC逻辑流程-修改 MVCC逻辑流程-查询 三、幻读 快照读和当前读 四、如何解决幻读 事务隔离级别有四种,mysql默认使用的是可重复读&#x…

前端开发:a标签实现下载功能

应用背景 前端项目实现下载文件的功能,在后台没给我们撸接口的情况下,我们可以利用a标签实现下载功能,而且贼简单~ 实现原理 通过a标签的download的属性,将需要下载的文件放在前端项目中,然后href属性访问文件路径&a…

a标签/js下载文件(2020)

a标签/js 下载服务器文件 一、二进制式下载1、responseType(请求)2、Content-Type(响应)判断是普通数据还是文件流(可选)3、Content-Disposition(响应)和文件名(可选&…

a标签下载pdf文件

通过a标签的download属性可以实现下载pdf文件,不过有一个弊端:网站和pdf文件必须在同一域名下才可行,不然就是先打开一个新标签预览,然后点击下载按钮进行下载。

a标签实现文件下载功能

文件下载原理: java后台只能做到返回二进制流或文件给前端,最终在前端页面创建一个a,然后触发a的点击事件实现点击下载效果。 1.无需token的 2.请求头需要token 接口: 点击事件:

前端-基于a标签实现下载功能

最近在一个项目中需要实现下载功能,在前期与后端多次联调尝试使用接口下载文件无果后,最后抱着试一试的心态使用了A标签下载,方法是有效的,但是有部分局限性!!! 使用a标签实现下载的步骤如下&am…

a标签的download属性(荐)

在html 中 a 链接有 download 这样一个属性 它有什么用呢?! 我们在页面中提供下载的时候,都需要去配置一些服务端的东西,比如指定 zip 文件就通知浏览器下载这个文件。 但是,比如 .jpg 这样的图片文件,如…