InnoDB如何解决幻读?深入解析MySQL的并发控制机制
---
## 一、什么是幻读(Phantom Read)?
**幻读**是数据库事务隔离性中的一个典型问题,具体表现为:
在同一个事务中,多次执行相同的范围查询(Range Query)时,**后一次查询看到了前一次查询未出现的新记录**。这种现象通常发生在事务未完全隔离的场景下,尤其是在**可重复读(Repeatable Read)**和**读未提交(Read Uncommitted)**隔离级别中。
### 示例场景
1. **事务A**执行查询:`SELECT * FROM users WHERE age > 20;`(返回3条记录)。
2. **事务B**插入一条新记录:`INSERT INTO users (age) VALUES (25);`。
3. **事务A**再次执行相同的查询,发现多了一条记录(共4条)。
这种现象称为“幻读”,如同幻觉般出现了新的数据。
---
## 二、InnoDB如何解决幻读?
InnoDB通过两种核心机制解决幻读问题:
1. **多版本并发控制(MVCC)**
2. **间隙锁(Gap Lock) + 临键锁(Next-Key Lock)**
### 1. 多版本并发控制(MVCC)
MVCC通过为每个事务生成一个**一致性视图(Consistent Read View)**,确保事务在多次查询中看到相同的数据快照。
- **快照读(Snapshot Read)**:普通的`SELECT`语句使用MVCC,读取的是事务开始时的数据版本,不会看到其他事务的插入或删除操作。
- **当前读(Current Read)**:加锁的`SELECT ... FOR UPDATE`或`SELECT ... LOCK IN SHARE MODE`会读取最新数据并加锁。
**MVCC的作用**:
- 在`Repeatable Read`隔离级别下,快照读可以避免幻读。
- 但若事务中存在当前读操作,仍需依赖锁机制。
### 2. 间隙锁(Gap Lock)与临键锁(Next-Key Lock)
#### (1) 间隙锁(Gap Lock)
间隙锁锁定的是索引记录之间的“间隙”,防止其他事务在范围内插入新数据。
例如,表中现有记录的`age`值为`[10, 20, 30]`,执行`SELECT * FROM users WHERE age > 20 FOR UPDATE`时,InnoDB会锁定`(20, +∞)`的区间。
#### (2) 临键锁(Next-Key Lock)
临键锁是**记录锁(Record Lock) + 间隙锁(Gap Lock)**的组合,锁定索引记录及其之前的间隙。
例如,索引值为`20`的记录,临键锁会锁定区间`(-∞, 20]`。
**作用**:
- 防止其他事务在锁定范围内插入新数据,从而避免幻读。
---
## 三、实战验证:InnoDB如何阻止幻读?
### 实验环境
- 数据库:MySQL 8.0
- 表结构:
```sqlCREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,age INT NOT NULL,INDEX idx_age (age));```
### 步骤1:事务A执行范围查询并加锁
```sql
-- 事务A
BEGIN;
SELECT * FROM users WHERE age > 20 FOR UPDATE; -- 当前读,触发临键锁
-- 此时锁定区间 (20, +∞)
```
### 步骤2:事务B尝试插入数据
```sql
-- 事务B
BEGIN;
INSERT INTO users (age) VALUES (25); -- 被阻塞!
```
事务B的插入操作会被阻塞,直到事务A提交或超时。
### 结果分析
- InnoDB通过临键锁锁定了`age > 20`的范围,阻止事务B插入`age=25`的记录。
- 因此,事务A的两次查询结果一致,避免了幻读。
---
## 四、InnoDB解决幻读的局限性
1. **仅对当前读有效**
MVCC的快照读可以避免幻读,但若事务中混合快照读和当前读,仍需显式加锁。
2. **索引依赖**
间隙锁和临键锁依赖于索引。若查询未使用索引,InnoDB会退化为表锁,严重影响性能。
3. **隔离级别限制**
- 在`Repeatable Read`级别下,InnoDB默认通过临键锁解决幻读。
- 在`Read Committed`级别下,间隙锁会被禁用,无法完全避免幻读。
---
## 五、最佳实践
1. **合理选择隔离级别**
- 默认使用`Repeatable Read`,兼顾性能与一致性。
- 在需要更高并发时,可降级为`Read Committed`,但需手动处理幻读风险。
2. **显式加锁**
对关键范围查询使用`SELECT ... FOR UPDATE`,强制触发临键锁。
3. **优化索引设计**
确保查询条件命中索引,避免锁升级为表锁。
---
## 六、总结
InnoDB通过**MVCC的快照读**和**临键锁的当前读**双重机制,在`Repeatable Read`隔离级别下解决了幻读问题。
- **MVCC**:保证快照读的一致性视图。
- **临键锁**:通过锁定索引范围,阻止其他事务插入新数据。
理解这些机制有助于在实际开发中合理设计事务和查询逻辑,确保数据一致性并提升并发性能。
相关文章:
InnoDB如何解决幻读?深入解析MySQL的并发控制机制
--- ## 一、什么是幻读(Phantom Read)? **幻读**是数据库事务隔离性中的一个典型问题,具体表现为: 在同一个事务中,多次执行相同的范围查询(Range Query)时,**后一次…...
栈的深度解析:从基础实现到高级算法应用——C++实现与实战指南
一、栈的核心算法与应用场景 栈的先进后出特性使其在以下算法中表现优异: 括号匹配:校验表达式合法性。表达式求值:中缀转后缀,逆波兰表达式求值。深度优先搜索(DFS):模拟递归调用。单调栈&am…...
IDEA集成DeepSeek
引言 随着数据量的爆炸式增长,传统搜索技术已无法满足用户对精准、高效搜索的需求。 DeepSeek作为新一代智能搜索技术,凭借其强大的语义理解与深度学习能力,正在改变搜索领域的游戏规则。 对于 Java 开发者而言,将 DeepSeek 集成…...
Oracle Trace文件突然增长很多的原因分析及解决办法
Oracle Trace文件突然增长很多可能是由多种原因引起的,例如SQL语句的长时间跟踪、错误的跟踪设置、大量的错误和警告信息等。 一、以下是一些解决Trace文件增长过快的方法: 1.清理旧的Trace文件 可以通过以下命令删除超过一定天数的Trace文件,例如删除3天前的Trace文件: …...
leetcode:627. 变更性别(SQL解法)
难度:简单 SQL Schema > Pandas Schema > Salary 表: ----------------------- | Column Name | Type | ----------------------- | id | int | | name | varchar | | sex | ENUM | | salary | int …...
SQLMesh系列教程-3:SQLMesh模型属性详解
SQLMesh 的 MODEL 提供了丰富的属性,用于定义模型的行为、存储、调度、依赖关系等。通过合理配置这些属性,可以构建高效、可维护的数据管道。在 SQLMesh 中,MODEL 是定义数据模型的核心结构,初学SQLMesh,定义模型看到属…...
Java 中的 HashSet 和 HashMap 有什么区别?
一、核心概念与用途 特性HashSetHashMap接口实现实现 Set 接口(存储唯一元素)实现 Map 接口(存储键值对)数据存储存储单个对象(元素唯一)存储键值对(键唯一,值可重复)典…...
Kubernetes-master 组件
以下是Kubernetes Master Machine的组件。 etcd 它存储集群中每个节点可以使用的配置信息。它是一个高可用性键值存储,可以在多个节点之间分布。只有Kubernetes API服务器可以访问它,因为它可能具有一些敏感信息。这是一个分布式键值存储,所…...
【Leetcode 952】按公因数计算最大组件大小
题干 给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图: 有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记;只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之…...
js考核第三题
题三:随机点名 要求: 分为上下两个部分,上方为显示区域,下方为控制区域。显示区域显示五十位群成员的学号和姓名,控制区域由开始和结束两个按钮 组成。点击开始按钮,显示区域里的内容开始滚动,…...
【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)— 4.6 RNN与LSTM的变体与发展趋势】
引言:时间序列的魔法钥匙 在时间的长河中,信息如同涓涓细流,绵延不绝。而如何在这无尽的数据流中捕捉、理解和预测,正是循环神经网络(RNN)及其变体长短时记忆网络(LSTM)所擅长的。今天,我们就来一场深度探索,揭开RNN与LSTM的神秘面纱,看看它们如何在时间序列的海洋…...
简单几个步骤完成 Oracle 到金仓数据库(KingbaseES)的迁移目标
作为国产数据库的领军选手,金仓数据库(KingbaseES)凭借其成熟的技术架构和广泛的市场覆盖,在国内众多领域中扮演着至关重要的角色。无论是国家电网、金融行业,还是铁路、医疗等关键领域,金仓数据库都以其卓…...
Java和JavaScript当中的json对象和json字符串分别讲解
Java和JavaScript当中的json对象和json字符串分别讲解 一、Java当中的json对象和json字符串 在 Java 中,JSON 对象和 JSON 字符串有不同的表示和操作方式。 1. JSON 对象: 如果你使用的是 org.json 库,创建 JSON 对象的代码如下࿱…...
【第11章:生成式AI与创意应用—11.2 音频与音乐生成的探索与实践】
凌晨三点的录音棚里,制作人小林对着空荡荡的混音台抓狂——广告方临时要求将电子舞曲改编成巴洛克风格,还要保留"赛博朋克"元素。当他在AI音乐平台输入"维瓦尔弟遇见霓虹灯"的瞬间,一段融合羽管键琴与合成器的奇妙旋律喷涌而出,这场人与机器的音乐狂想…...
八、SPI读写XT25数据
8.1 SPI 简介 SPI(Serial Peripheral Interface,串行外设接口)是一种同步串行通信协议,广泛用于嵌入式系统中连接微控制器与外围设备,如传感器、存储器、显示屏等。 主要特点 1. 全双工通信:支持同时发送…...
Visionpro 齿轮测量
效果展示 一、题目要求 求出最大值,最小值,平均值 二、分析 1.首先要进行模板匹配 2.划清匹配范围 3.匹配小三角的模板匹配 4.卡尺 5.用找圆工具 工具 1.CogPMAlignTool 2.CogCaliperTool 3.CogFindCircleTool 4.CogFixtureTool 三、模板匹…...
Ubuntu20.04部署stable-diffusion-webui环境小记
Ubuntu20.04部署stable-diffusion-webui环境小记 文章目录 前言后视镜视角查看安装文档聊聊我踩的那些坑python3.11的安装执行sudo apt update报错显卡驱动内存优化网络问题无法打开系统设置和网络设置查询GPU使用情况 总结 Stable Diffusion web UI A web interface for Stabl…...
索引以及索引底层数据结构
一、什么是索引? 索引(index)是数据库高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构(B树),这些数据结构以某种方式指向真在…...
开业盛典活动策划方案拆解
道叔来给大家详细剖析咱们方案库里刚收录的这份《蜀大侠火锅店武侠风开业盛典活动策划方案》了,保证让你看完直呼过瘾,收获满满! 一、主题创意:武侠风,直击人心 首先,咱们得夸一下这活动的主题——“XXX‘…...
API 接口自动化
HTTP协议 - 白月黑羽 HTTP协议简介 如果客户端是浏览器,如何在chrome浏览器中查看 请求和响应的HTTP消息?按f12-》network 清除当前信息 响应的消息体在Response里看 点preview,可以看响应的消息体展开的格式 HTTP请求消息 请求头 reques…...
安全测试|SSRF请求伪造
前言 SSRF漏洞是一种在未能获取服务器权限时,利用服务器漏洞,由攻击者构造请求,服务器端发起请求的安全漏洞,攻击者可以利用该漏洞诱使服务器端应用程序向攻击者选择的任意域发出HTTP请求。 很多Web应用都提供了从其他的服务器上…...
ML.NET库学习008:使用ML.NET进行心脏疾病预测模型开发
文章目录 ML.NET库学习008:使用ML.NET进行心脏疾病预测模型开发1. 项目主要目的和原理2. 项目概述实现的主要功能:主要流程步骤:关键技术: 3. 主要功能和步骤数据加载与路径处理模型训练与评估模型保存与加载 4. 代码中的数据结构…...
了解rtc_time64_to_tm()和rtc_tm_to_time64()
rtc_time64_to_tm()和rtc_tm_to_time64()主要用于RTC的驱动程序,在Linux外部RTC驱动中较常见。 打开“drivers/rtc/lib.c” /* * rtc_time64_to_tm - Converts time64_t to rtc_time. * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. */ //将ti…...
verilog程序设计及SystemVerilog验证
1.Verilog测试程序设计基础 1.1Testbench及其结构 在仿真的时候Testbench用来产生测试激励给待验证设计( Design Under Verification, DUV),或者称为待测设计(Design UnderTest, DUT) 。 测试程序的一般结构: Testbench是一个测试平台,信号…...
智能编程助手功能革新与价值重塑之:GitHub Copilot
引言: GitHub Copilot 的最新更新为开发者带来了显著变化,其中 Agent Mode 功能尤为引人注目。该模式能够自动识别并修复代码错误、自动生成终端命令,并具备多级任务推理能力,这使得开发者在开发复杂功能时,可大幅减少…...
物联网行业通识:从入门到深度解析
物联网行业通识:从入门到深度解析 (图1:物联网生态示意图) 一、引言:万物互联时代的到来 根据IDC最新预测,到2025年全球物联网设备连接数将突破410亿,市场规模达1.1万亿美元。物联网ÿ…...
ABP - 事件总线之分布式事件总线
ABP - 事件总线之分布式事件总线 1. 分布式事件总线的集成1.2 基于 RabbitMQ 的分布式事件总线 2. 分布式事件总线的使用2.1 发布2.2 订阅2.3 事务和异常处理 3. 自己扩展的分布式事件总线实现 事件总线可以实现代码逻辑的解耦,使代码模块之间功能职责更清晰。而分布…...
【硬件设计细节】缓冲驱动器使用注意事项
一、缓冲驱动器核心功能与选型原则 信号增强与隔离 驱动能力匹配:根据负载电流需求选择缓冲器,例如CMOS缓冲器驱动能力通常为4-8mA,需搭配大电流负载时选用图腾柱输出或专用驱动芯片(如TI的SN74LVC系列)。电压域转换&…...
驱动开发系列38 - Linux Graphics 3D 绘制流程(一)- 创建画布
一:概述 当应用程序创建 OpenGL 上下文时,它通常需要申请帧缓冲(Framebuffer,即画布)。在 X11 体系下,应用程序不会直接向内核的 DRM 模块请求创建帧缓冲,而是通过 X 服务器进行申请。 虽然从技术上讲,应用程序可以直接使用 DRM 接口创建帧缓冲对象(BO),但为了将其与…...
再谈SpringCloud Gateway源码
再谈SpringCloud Gateway源码 一、整体请求流程二、前置对象准备1、实例化HandlerMapping2、实例化Route3、实例化WebHandler 三、实践业务扩展点1、定义扩展Route对象2、Filter能做什么3、定义扩展Filter对象4、定义父类Filter简化请求参数处理 前言: 之前有阅读过…...
