简聊MySQL并发事务中幻读、虚读问题的解决方案
在MySQL数据库中,事务的幻读和虚读问题是并发控制中的关键挑战。以下是针对这两个问题的解决方案及原理说明,并附上相关示例。
一、幻读问题及其解决方案
-
幻读问题的定义
幻读是指一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行,这通常是由于其他事务在这个范围内插入了新的数据。
-
解决方案及原理
- 提高事务隔离级别:将事务的隔离级别设置为串行化(Serializable)可以彻底避免幻读问题。在这种隔离级别下,事务会完全隔离,其他事务无法在其执行期间插入新的数据。然而,这种解决方案会导致性能显著下降,因为串行化隔离级别会限制并发性。
- 使用MVCC(多版本并发控制):MVCC通过为每个事务分配一个唯一的事务ID和版本号,来保证每个事务读取到的数据都是一致的。当一个事务开始时,它会生成一个快照,后续的读取操作都会从这个快照中获取数据,从而避免了幻读问题。MySQL在可重复读(Repeatable Read)隔离级别下,通过MVCC机制来减少幻读问题的发生。
- 引入Next-Key Lock:在InnoDB存储引擎中,除了行锁之外,还引入了间隙锁(Gap Lock)和Next-Key Lock来解决幻读问题。Next-Key Lock是行锁和间隙锁的组合,它锁定了一个范围,包括索引记录以及它们之间的空隙。当执行范围查询并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁,同时也会对键值在条件范围内但并不存在的记录(即间隙)加锁。这样,其他事务就无法在这个范围内插入新的数据,从而避免了幻读问题。
-
示例
- 假设有一个名为
products的表,其中包含id和name两列。 - 事务A执行查询操作:
SELECT * FROM products WHERE id > 100; - 事务B在事务A查询的范围内插入一条新的数据:
INSERT INTO products (id, name) VALUES (150, 'New Product');并提交事务。 - 事务A再次执行相同的查询操作:
SELECT * FROM products WHERE id > 100;- 在没有使用间隙锁的情况下,事务A的第二次查询将会返回新增的数据,导致幻读的问题出现。
- 如果在事务A的查询语句中加入
FOR UPDATE,即SELECT * FROM products WHERE id > 100 FOR UPDATE;,这样事务A在读取数据的同时,会对查询范围内的间隙进行锁定,从而阻止了其他事务的插入操作,避免了幻读的发生。
- 假设有一个名为
二、虚读问题及其解决策略
虚读问题通常是指在可重复读(Repeatable Read)隔离级别下,一个事务读取到另一个事务已经提交但尚未对当前事务可见的数据。然而,在MySQL的InnoDB存储引擎中,由于实现了MVCC机制,实际上在可重复读隔离级别下并不会发生虚读问题。因为MVCC确保事务读取到的数据是事务开始时的快照,即使其他事务在之后对数据进行了修改或提交,也不会影响到当前事务的读取结果。
三、总结
MySQL通过提高事务隔离级别、使用MVCC机制以及引入Next-Key Lock等策略,有效地解决了幻读问题。同时,由于MVCC机制的实现,MySQL在可重复读隔离级别下实际上并不会发生虚读问题。在实际应用中,开发者需要根据具体的业务场景和需求选择合适的解决方案,以确保数据的一致性和系统的性能。
四、解释“SELECT ...... FOR UPDATE;”
当您在MySQL的InnoDB存储引擎中使用SELECT ... FOR UPDATE语句时,如果查询条件涉及范围查询(如id > 100),InnoDB会自动为该查询添加Next-Key Lock。Next-Key Lock是InnoDB实现的一种锁策略,它结合了行锁(Record Lock)和间隙锁(Gap Lock)来避免幻读问题。
具体来说,当您执行SELECT * FROM products WHERE id > 100 FOR UPDATE;时,InnoDB会:
- 对满足条件
id > 100的每一行数据加上行锁(Record Lock),确保其他事务不能修改或删除这些行。 - 同时,InnoDB还会对
id值在100到查询结果中最小id值之间的间隙(Gap)加上间隙锁(Gap Lock),以及查询结果中最大id值到正无穷大之间的间隙加上间隙锁(如果存在的话,实际上在大多数情况下,我们不会关心正无穷大这个边界的间隙锁,因为它不影响插入操作)。这样,其他事务就不能在这个间隙内插入新的数据行。
通过结合行锁和间隙锁,Next-Key Lock能够确保在事务执行期间,查询结果集不会被其他事务修改或插入新行,从而避免了幻读问题。
需要注意的是,虽然SELECT ... FOR UPDATE会添加Next-Key Lock,但只有在事务隔离级别为可重复读(Repeatable Read)或更高(实际上是串行化,但串行化通常不会用于实际应用中,因为它会极大地降低并发性能)时,这种锁策略才会生效。在读已提交(Read Committed)隔离级别下,InnoDB不会使用间隙锁,因此可能会遇到幻读问题。
五、注意navicat中测试记录锁Gap Locks示例:
确保事务隔离级别是RR:
1、打开两个查询窗口:
相当于开启了两个事务;
窗口1是开启事务并加记录锁;
窗口2是执行update、insert、delete等DML操作;
窗口1内容: 
解释:测试时, “运行已选择的” 图表灰色不可点击说明是开启事务成功;“停止”图表亮起,表示添加行锁记录锁;阻塞了,其他窗口就不能对此行记录进行操作了。
窗口2内容: 
解释:同窗口1的解释。执行update语句没有成功,在等待其他事务释放锁。
2、两个窗口分别关掉停止
窗口1关掉停止,显示:
SELECT * FROM EMP WHERE ID=1001 FOR UPDATE
> 1205 - Lock wait timeout exceeded; try restarting transaction
> 时间: 50.591s
窗口2关掉停止,显示:
update EMP set ename='天天向上杰4' where ID=1001
> 1205 - Lock wait timeout exceeded; try restarting transaction
> 时间: 51.439s
3、注意⚠️错误示范
千万不要在一个查询窗口中执行啊,切记!错误示范:

(有不对的地方,大家多多批评,并发表出您的真知,感谢) 上述这样不会执行成功的。因为在同一个会话中,执行语句的顺序是从上到下,相当于在极短的时间内开启事务后,迅速就提交了。在按照顺序执行过程中,等不及锁加载和阻塞,直接就提交执行下一个事务了。
用plsqldev.exe操作Oracle时是很好测试的。(略)
祝大家测试成功!
六、间隙锁简易示例:
间隙锁用于锁定索引记录之间的“间隙”,但不锁定索引记录本身。
示例:
- 假设表
your_table的id字段是索引,且有值1、3、5。事务1开始,查询id在1到3之间(不包含1和3)的数据并加锁,会在这个间隙上加间隙锁:-
SELECT * FROM your_table WHERE id > 1 AND id < 3 FOR UPDATE;
-
- 事务2开始,尝试插入
id = 2的数据(会被阻塞,因为有间隙锁):-
INSERT INTO your_table (id, name) VALUES (2, 'new_entry');
-
在这个例子中,事务1在1和3之间的间隙上加了间隙锁,事务2尝试插入id = 2的数据时就会被阻塞。
(望各位潘安、各位子健不吝赐教!多多指正!🙏)
相关文章:
简聊MySQL并发事务中幻读、虚读问题的解决方案
在MySQL数据库中,事务的幻读和虚读问题是并发控制中的关键挑战。以下是针对这两个问题的解决方案及原理说明,并附上相关示例。 一、幻读问题及其解决方案 幻读问题的定义 幻读是指一个事务在前后两次查询同一个范围的时候,后一次查询看到了…...
【搭建JavaEE】(2)Tomcat安装配置和第一个JavaEE程序
Tomcat–容器(Container) 下载 Apache Tomcat - Welcome! 下载完成 请求/响应 结构 测试 查看Jdk版本 改端口号localhost8080–>8099 学学人家以后牛逼了可以用自己名字当文件夹名 配置端口8099 找到server文件 用记事本打开 再打开另一个logging文件 ”乱码解决“步骤&…...
【Qt】01-了解QT
踏入QT的殿堂之路 前言一、创建工程文件1.1 步骤介绍1.2 编译介绍方法1、方法2、编译成功 二、了解框架2.1 main.cpp2.2 .Pro文件2.2.1 注释需要打井号。2.2.2 F1带你进入帮助模式2.2.3 build文件 2.3 构造函数 三、编写工程3.1 main代码3.2 结果展示 四、指定父对象4.1 main代…...
websocket股票行情接口
股票行情区别 交易所出来的数据,不管通过什么渠道,延时一般都不会差太远,估计一般也就几十ms的差别。 但是如果是通过http轮询,不太可能几十ms全部轮询一次。所以,做量化的话,用http协议是最次的选择。 …...
朴素贝叶斯分类器
目录 一、生成模型(学习)(Generative Model) vs 判别模型(学习)(Discriminative Model) 1、官方说明 2、通俗理解 3、举例 二、生成学习算法 1、数学符号说明 2、贝叶斯公式 …...
智能化植物病害检测:使用深度学习与图像识别技术的应用
植物病害一直是农业生产中亟待解决的问题,它不仅会影响作物的产量和质量,还可能威胁到生态环境的稳定。随着人工智能(AI)技术的快速发展,尤其是深度学习和图像识别技术的应用,智能化植物病害检测已经成为一…...
vim基本命令(vi、工作模式、普通模式、插入模式、可视模式、命令行模式、复制、粘贴、插入、删除、查找、替换)
1. Vim的作用 1.1. 文本编辑 1.1.1. 基础文本编辑功能 Vim是一个功能强大的文本编辑器,它可以用来创建、修改和保存各种文本文件。无论是编写简单的文本笔记,还是复杂的代码文件,Vim都能胜任。例如,我们可以用它来编写Python脚…...
Qt 自动根据编译的dll或exe 将相关dll文件复制到目标文件夹
Qt 自动根据编译的dll或exe 将相关dll文件复制到目标文件夹 如果你在使用 windeployqt 时遇到错误 “windeployqt 不是内部或外部命令”,说明你的命令行环境没有正确配置 Qt 工具路径。windeployqt 是 Qt 工具的一部分,它用于自动将所有必要的 Qt 库和插…...
探索新能源汽车“芯”动力:AUTO TECH China 2025广州国际新能源汽车功率半导体技术展盛况空前
广州,2025年11月20日 —— 在全球新能源车市场蓬勃发展的背景下,AUTO TECH China 2025 广州国际新能源汽车功率半导体技术展览会将于2025年11月20-22日在广州保利世贸博览馆盛大开幕。此次展会作为亚洲领先的车用功率半导体技术专业盛会,本…...
Kafka权威指南(第2版)读书笔记
目录 Kafka生产者——向Kafka写入数据生产者概览创建Kafka生产者bootstrap.serverskey.serializervalue.serializer 发送消息到Kafka同步发送消息 Kafka生产者——向Kafka写入数据 不管是把Kafka作为消息队列、消息总线还是数据存储平台,总是需要一个可以往Kafka写…...
WORD转PDF脚本文件
1、在桌面新建一个文本文件,把下列代码复制到文本文件中。 On Error Resume Next Const wdExportFormatPDF 17 Set oWord WScript.CreateObject("Word.Application") Set fso WScript.CreateObject("Scripting.Filesystemobject") Set fdsf…...
electron 打包后的 exe 文件,运行后是空白窗口
一、代码相关问题 1. 页面加载失败 1.1 原因 在 Electron 应用中,若loadFile或loadURL方法指定的页面路径或 URL 错误,就无法正确加载页面,导致窗口空白。 1.2. 解决 仔细检查loadFile或loadURL方法中传入的路径或 URL 是否正确…...
数据库重连 - 方案
要解决 SQL Server 连接失效后导致的错误问题,可以考虑以下几种解决方案: 1. 连接池机制: 通过实现一个连接池,确保连接失效后可以重新建立连接,而不会直接导致整个程序出错。连接池可以帮助在连接中断时自动恢复连接,而不必每次手动重连。 例如,可以通过以下方式定期…...
从 PostgreSQL 中挽救损坏的表
~/tmp-dir.dab4fd85-8b47-4d9a-b15c-18312ef61075 pg_dump -U postgres -h locathost www_p1 > wow_p1.sqlpg_dump:错误:转储表 “page_views” 的内容失败:PQgetResult() 失败。pg_dump:详细信息:来自服务器的错误…...
【Vue3 入门到实战】1. 创建Vue3工程
目录 编辑 1. 学习目标 2. 环境准备与初始化 3. 项目文件结构 4. 写一个简单的效果 5. 总结 1. 学习目标 (1) 掌握如何创建vue3项目。 (2) 了解项目中的文件的作用。 (3) 编辑App.vue文件,并写一个简单的效果。 2. 环境准备与初始化 (1) 安装 Node.js 和 …...
rtthread学习笔记系列(10/11) -- 系统定时器
文章目录 10. 系统定时器10.1 跳跃表[定时器跳表 (Skip List) 算法](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/timer/timer?id定时器跳表-skip-list-算法) 10.2 硬件定时器10.2.1 初始化&&删除10.2.2 sta…...
mock服务-通过json定义接口自动实现mock服务
go-mock介绍 不管在前端还是后端开发过程中,当我们需要联调其他服务的接口,而这个服务还没法提供调用时,那我们就要用到mock服务,自己按接口文档定义一个临时接口返回指定数据,以供本地开发联调测试。 怎么快速启动一…...
像JSONDecodeError: Extra data: line 2 column 1 (char 134)这样的问题怎么解决
问题介绍 今天处理返回的 JSON 的时候,出现了下面这样的问题: 处理这种问题的时候,首先你要看一下当前的字符串格式是啥样的,比如我查看后发现是下面这样的: 会发现这个字符串中间没有逗号,也就是此时的J…...
C#版 软件开发6大原则与23种设计模式
开发原则和设计模式一直是软件开发中的圣经, 但是这仅仅适用于中大型的项目开发, 在小型项目的开发中, 这些规则会降低你的开发效率, 使你的工程变得繁杂. 所以只有适合你的才是最好的. 设计模式六大原则1. 单一职责原则(Single Responsibility Principle࿰…...
java8 springboot 集成javaFx 实现一个客户端程序
1. 先创建一个springboot 程序(此步骤不做流程展示) 2. 更改springboot的版本依赖和导入所需依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.7</versio…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
