MySQL可重复读-问题实践

article/2025/9/28 10:21:33

MySQL可重复读之幻读问题

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

模拟均基于下表:

CREATE TABLE `user` (`id` int NOT NULL AUTO_INCREMENT COMMENT '自增id',`username` varchar(20) NOT NULL COMMENT '用户名',`password` varchar(20) NOT NULL COMMENT '密码',`name` varchar(20) DEFAULT NULL COMMENT '真实姓名',`age` tinyint DEFAULT NULL COMMENT '用户年龄',`address` varchar(30) DEFAULT NULL COMMENT '现居地址',PRIMARY KEY (`id`),KEY `idx_name_age` (`name`,`age`),KEY `idx_username` (`username`)
) ENGINE=InnoDB

表中具有如下数据:

在这里插入图片描述

不可重复读问题

我们首先通过如下示例看看MySQL的InnoDB究竟是否能避免不可重复读问题

以下测试基于MySQL8

首先查看MySQL的默认隔离级别:

# 查看当前会话下的隔离级别
select @@transaction_isolation;
# 查看全局隔离级别
select @@global.transaction_isolation;

在这里插入图片描述

可以发现,当前会话的隔离级别为REPEATABLE-READ,可重复读

首先,我们来看看可重复读的情况下是否会出现不可重复读的问题

什么是不可重复读: 在一个事务中,前后相同的两次查询,结果应当是一样的,但是查询返回的结果确不同。也就是说,同一份数据在同一个事务中不能被重复读。出现这种情况的可能原因是,当一个事务执行某个查询后,数据被另一个事务更新,当前事务再次执行该查询会得到更新后的数据。它违背了数据库设计的ACID原则

模拟不可重复读的场景:

1、开启两个MySQL客户端连接,并且分别开启事务(分别为事务1和事务2):

开启事务的语句如下:

begin;

在这里插入图片描述

2、在事务1中通过如下SQL语句查询数据库的数据:

select * from user where id = 4;

结果如下:

在这里插入图片描述

3、在事务2中对user表中id为4的数据进行修改,并查看修改结果:

update user set password = '4' where id = 4;
select * from user where id = 4;

结果如下:
在这里插入图片描述

可以发现在当前事务修改已生效,在另一个事务中进行查询

4、在事务1中查询user表中id为4的数据:

select * from user where id = 4;

结果:可以发现这里password还是5,事务2的未提交的修改并未影响事务1的结果,这里可以证明可重复读避免了脏读的问题

在这里插入图片描述

5、事务2提交修改:

commit;

6、事务1继续进行查询:

select * from user where id = 4;

结果如下:可以发现即使事务2提交了,事务1在读取的过程中,数据也没有改变,这里可以证明可重复读避免了不可重复的问题,一个事务的修改即使提交了,也不会影响另一个事务的读取

在这里插入图片描述

7、事务1提交后再读取数据:

commit;
select * from user where id = 4;

结果如下:

在这里插入图片描述

幻读问题

MySQL可重复读隔离级别下会不会出现幻读问题,接下来在模拟中看看实际效果

什么是幻读:假设有两个事务,分别是事务A和事务B,事务A首先以某一where条件读取数据集合;随后事务B向数据库中插入满足事务A查询where条件的数据,并且提交;事务A再次以相同的where条件查询数据时,读取到的数据集合与之前读取的数据集合不同(多了一条数据或少了一条数据),这种情况就是幻读问题

模拟幻读问题:

1、开启两个客户端连接,并分别开启事务(分别为事务1和事务2):

begin;

2、事务1通过如下查询语句查询数据:

select * from user where id > 1 and id < 6;

结果如下:

在这里插入图片描述

3、事务2向user表中插入id为5的数据:

insert into user(id, username, password, name, age, address) values(5, '5', '5', '王五', 12, 'hubei');
select * from user;

结果如下:

在这里插入图片描述

可以发现当前事务已经存在id为5的数据了,然后我们直接提交事务2

commit;

再次查询:

select * from user;

结果如下:可以发现数据已经插入数据库中

在这里插入图片描述

4、事务1再以相同条件查询数据:

select * from user where id > 1 and id < 6;

结果如下:可以发现并未查询到id为5的数据,这里可以证明可重复读隔离级别避免了幻读问题

在这里插入图片描述

5、在事务1中对id为5的数据进行修改,然后再次以相同的条件进行查询:

update user set password = '6' where id = 5;
select * from user where id > 1 and id < 6;

结果如下:可以发现这次查询又查到了id为5的数据,这里就出现了幻读的问题

在这里插入图片描述

从上面的模拟中可以发现,MySQL可重复读隔离级别在大部分场景下是可以避免幻读问题的,但是在第5中场景下是无法避免幻读问题,也就是:

  • 当事务2向数据库中插入满足事务1查询where条件的数据后,并且commit,此时事务1以相同的where条件查询时是不会读取到新插入的数据的,这就避免了幻读问题
  • 当事务1修改了事务2插入的数据之后,也就是update语句修改了事务2插入的数据,再次以相同的条件查询数据库时,会发现查询出来事务2插入的数据,出现了幻读问题

总结:MySQL可重复读隔离级别在当前事务不修改其他事务插入的数据时,是可以避免幻读的;但是当前事务修改了其他事务插入的数据之后,还是会出现幻读的问题

本篇文章从实践的角度讲解了MySQL可重复读隔离级别下避免脏读、不可重复读、幻读的场景,也把可能出现的幻读问题进行模拟

接下来会从MVCC原理的角度来讲解MySQL的可重复读是如何实现的,敬请期待


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

相关文章

可重复读下的幻读

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

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

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

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

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

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

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

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

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

可重复读实现原理

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

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

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

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

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

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

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

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

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

a标签下载pdf文件

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

a标签实现文件下载功能

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

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

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

a标签的download属性(荐)

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

html a标签下载文件

<a href"/user/test/xxxx.txt" download"文件名.txt">点击下载</a>

前端a标签实现文件下载

a标签实现文件下载 如果想通过纯前端技术实现文件下载&#xff0c; 下载的静态文件放项目路径下&#xff0c;A标签下载&#xff0c;herf指定项目路径&#xff0c;加上download属性。a链接默认的是在同一页面打开&#xff0c;如果我们需要打开新的页面&#xff0c;就需要添加t…

html利用a标签实现下载本地的文件

在写html页面的时候&#xff0c;需要在网页上提供一个下载按钮可以下载我自己电脑中的文件。我已经知道了该文件的路径&#xff0c;但是之前看了很多文章都没找到正确办法&#xff0c;一直不知道如何能够下载本地的文件&#xff0c;经过不断实验发现&#xff0c;可以利用a标签中…

一、<a>标签如何实现下载

实习期间负责的第一个项目&#xff1a;广东互联网协会官网。其中有一个很常见的功能----点击下载。 页面截图 在此之前&#xff0c;我所认识的<a>标签只是用于页面跳转的&#xff0c;实现文件下载是如何做到的呢&#xff1f; 答案是&#xff1a;使用href与download属性 …

面试官:如何用a标签实现文件下载?(一文带你手撕知识点)

前言 大家好&#xff0c;今天给大家带来前端小知识&#xff1a;前端利用a标签实现文件&#xff08;图片&#xff09;下载&#xff0c;也就是教大家利用a标签或者是 window.open() 来实现下载功能。 文章目录 前言常用方式方法分析代码实现 常用方式 <a href"url"…

Jquery之遍历元素

J q u e r y Jquery Jquery之遍历元素 使用 e a c h ( ) each() each()方法传入函数两个参数分别为 i n d e x , d o m index,dom index,dom对象。 <body><div>1</div><div>2</div><div>3</div> </body> <script src&quo…