简聊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…...
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. 查看链接器参数(如果没有勾选上面…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
