MySQL 可重复读隔离级别,完全解决幻读了吗?
我在上一篇文章 (opens new window)提到MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」但是它很大程度上避免幻读现象并不是完全解决了解决的方案有两种针对快照读普通 select 语句是通过 MVCC 方式解决了幻读因为可重复读隔离级别下事务执行过程中看到的数据一直跟这个事务启动时看到的数据是一致的即使中途有其他事务插入了一条数据是查询不出来这条数据的所以就很好地避免了幻读问题。针对当前读select ... for update 等语句是通过 next-key lock记录锁间隙锁方式解决了幻读因为当执行 select ... for update 语句的时候会加上 next-key lock如果有其他事务在 next-key lock 锁范围内插入了一条记录那么这个插入语句就会被阻塞无法成功插入所以就很好地避免了幻读问题。这两个解决方案是很大程度上解决了幻读现象但是还是有个别的情况造成的幻读现象是无法解决的。这次就跟大家好好聊这个问题。#什么是幻读首先来看看 MySQL 文档是怎么定义幻读Phantom Read的:The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.翻译当同一个查询在不同的时间产生不同的结果集时事务中就会出现所谓的幻象问题。例如如果 SELECT 执行了两次但第二次返回了第一次没有返回的行则该行是“幻像”行。举个例子假设一个事务在 T1 时刻和 T2 时刻分别执行了下面查询语句途中没有执行其他任何语句SELECT * FROM t_test WHERE id 100;只要 T1 和 T2 时刻执行产生的结果集是不相同的那就发生了幻读的问题比如T1 时间执行的结果是有 5 条行记录而 T2 时间执行的结果是有 6 条行记录那就发生了幻读的问题。T1 时间执行的结果是有 5 条行记录而 T2 时间执行的结果是有 4 条行记录也是发生了幻读的问题。#快照读是如何避免幻读的可重复读隔离级是由 MVCC多版本并发控制实现的实现的方式是开始事务后执行 begin 语句后在执行第一个查询语句后会创建一个 Read View后续的查询语句利用这个 Read View通过这个 Read View 就可以在 undo log 版本链找到事务开始时的数据所以事务过程中每次查询的数据都是一样的即使中途有其他事务插入了新纪录是查询不出来这条数据的所以就很好地避免了幻读问题。做个实验数据库表 t_stu 如下其中 id 为主键。然后在可重复读隔离级别下有两个事务的执行顺序如下从这个实验结果可以看到即使事务 B 中途插入了一条记录事务 A 前后两次查询的结果集都是一样的并没有出现所谓的幻读现象。#当前读是如何避免幻读的MySQL 里除了普通查询是快照读其他都是当前读比如 update、insert、delete这些语句执行前都会查询最新版本的数据然后再做进一步的操作。这很好理解假设你要 update 一个记录另一个事务已经 delete 这条记录并且提交事务了这样不是会产生冲突吗所以 update 的时候肯定要知道最新的数据。另外select ... for update这种查询语句是当前读每次执行的时候都是读取最新的数据。接下来我们假设select ... for update当前读是不会加锁的实际上是会加锁的在做一遍实验。这时候事务 B 插入的记录就会被事务 A 的第二条查询语句查询到因为是当前读这样就会出现前后两次查询的结果集合不一样这就出现了幻读。所以Innodb 引擎为了解决「可重复读」隔离级别使用「当前读」而造成的幻读问题就引出了间隙锁。假设表中有一个范围 id 为35间隙锁那么其他事务就无法插入 id 4 这条记录了这样就有效的防止幻读现象的发生。举个具体例子场景如下事务 A 执行了这面这条锁定读语句后就在对表中的记录加上 id 范围为 (2, ∞] 的 next-key locknext-key lock 是间隙锁记录锁的组合。然后事务 B 在执行插入语句的时候判断到插入的位置被事务 A 加了 next-key lock于是事务 B 会生成一个插入意向锁同时进入等待状态直到事务 A 提交了事务。这就避免了由于事务 B 插入新记录而导致事务 A 发生幻读的现象。#幻读被完全解决了吗可重复读隔离级别下虽然很大程度上避免了幻读但是还是没有能完全解决幻读。我举例一个可重复读隔离级别发生幻读现象的场景。#第一个发生幻读现象的场景还是以这张表作为例子事务 A 执行查询 id 5 的记录此时表中是没有该记录的所以查询不出来。# 事务 A mysql begin; Query OK, 0 rows affected (0.00 sec) mysql select * from t_stu where id 5; Empty set (0.01 sec)然后事务 B 插入一条 id 5 的记录并且提交了事务。# 事务 B mysql begin; Query OK, 0 rows affected (0.00 sec) mysql insert into t_stu values(5, 小美, 18); Query OK, 1 row affected (0.00 sec) mysql commit; Query OK, 0 rows affected (0.00 sec)此时事务 A 更新 id 5 这条记录对没错事务 A 看不到 id 5 这条记录但是他去更新了这条记录这场景确实很违和然后再次查询 id 5 的记录事务 A 就能看到事务 B 插入的纪录了幻读就是发生在这种违和的场景。# 事务 A mysql update t_stu set name 小林coding where id 5; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql select * from t_stu where id 5; ------------------------ | id | name | age | ------------------------ | 5 | 小林coding | 18 | ------------------------ 1 row in set (0.00 sec)整个发生幻读的时序图如下在可重复读隔离级别下事务 A 第一次执行普通的 select 语句时生成了一个 ReadView之后事务 B 向表中新插入了一条 id 5 的记录并提交。接着事务 A 对 id 5 这条记录进行了更新操作在这个时刻这条新记录的 trx_id 隐藏列的值就变成了事务 A 的事务 id之后事务 A 再使用普通 select 语句去查询这条记录时就可以看到这条记录了于是就发生了幻读。因为这种特殊现象的存在所以我们认为MySQL Innodb 中的 MVCC 并不能完全避免幻读现象。#第二个发生幻读现象的场景除了上面这一种场景会发生幻读现象之外还有下面这个场景也会发生幻读现象。T1 时刻事务 A 先执行「快照读语句」select * from t_test where id 100 得到了 3 条记录。T2 时刻事务 B 往插入一个 id 200 的记录并提交T3 时刻事务 A 再执行「当前读语句」 select * from t_test where id 100 for update 就会得到 4 条记录此时也发生了幻读现象。要避免这类特殊场景下发生幻读的现象的话就是尽量在开启事务之后马上执行 select ... for update 这类当前读的语句因为它会对记录加 next-key lock从而避免其他事务插入一条新记录。#总结MySQL InnoDB 引擎的可重复读隔离级别默认隔离级根据不同的查询方式分别提出了避免幻读的方案针对快照读普通 select 语句是通过 MVCC 方式解决了幻读。针对当前读select ... for update 等语句是通过 next-key lock记录锁间隙锁方式解决了幻读。我举例了两个发生幻读场景的例子。第一个例子对于快照读 MVCC 并不能完全避免幻读现象。因为当事务 A 更新了一条事务 B 插入的记录那么事务 A 前后两次查询的记录条目就不一样了所以就发生幻读。第二个例子对于当前读如果事务开启后并没有执行当前读而是先快照读然后这期间如果其他事务插入了一条记录那么事务后续使用当前读进行查询的时候就会发现两次查询的记录条目就不一样了所以就发生幻读。所以MySQL 可重复读隔离级别并没有彻底解决幻读只是很大程度上避免了幻读现象的发生。要避免这类特殊场景下发生幻读的现象的话就是尽量在开启事务之后马上执行 select ... for update 这类当前读的语句因为它会对记录加 next-key lock从而避免其他事务插入一条新记录。

相关新闻

回溯算法进阶:排列组合问题解析与实战

回溯算法进阶:排列组合问题解析与实战

1. 代码随想录算法训练营Day28内容概览作为一名参加过多个算法训练营的老学员,我清楚地记得Day28在整个训练周期中的关键地位。这一天通常会聚焦回溯算法的进阶应用,特别是解决排列组合类问题的经典模式。不同于基础阶段对单个算法的学习,Day…

2026/8/2 6:03:34 阅读更多 →
Python后端工程师成长路线:从零到一掌握企业级开发核心技能

Python后端工程师成长路线:从零到一掌握企业级开发核心技能

1. 从零到一:Python后端工程师的成长地图如果你刚接触编程,或者从其他语言转过来,想用Python找一份后端开发的工作,那你大概率会感到迷茫。网上资料太多,Python能做的方向也杂,从数据分析到人工智能&#x…

2026/8/3 7:03:40 阅读更多 →
AI环境监测系统部署失败率高达63%?3步精准诊断法,72小时内重建高精度感知网络

AI环境监测系统部署失败率高达63%?3步精准诊断法,72小时内重建高精度感知网络

更多请点击: https://kaifayun.com 第一章:AI环境监测系统部署失败率的行业真相 在工业物联网与智慧城市项目中,AI驱动的环境监测系统(如PM2.5、温湿度、NO₂多模态感知节点)正被大规模推广,但实际落地效果…

2026/8/2 21:51:46 阅读更多 →

最新新闻

WPF中HLSL着色器与Clip实现歌词高亮效果

WPF中HLSL着色器与Clip实现歌词高亮效果

1. 项目概述:WPF中HLSLClip实现歌词高亮光照效果 在WPF应用开发中,多媒体播放器的歌词可视化效果一直是UI设计的重点难点。传统实现方式通常依赖纯色填充或简单渐变,难以实现专业级的光照质感。通过HLSL(High Level Shader Langua…

2026/8/3 7:33:41 阅读更多 →
非常棒的向量数据库chroma的前端管理工具

非常棒的向量数据库chroma的前端管理工具

非常棒的向量数据库chroma的前端管理工具 简介 Chroma-Walnut-UI是一款优秀的Chroma向量数据库前端管理工具。安装步骤包括:克隆仓库、安装Python依赖(推荐使用uv或pip)、安装前端npm依赖。运行命令为uv run python main.py,Win…

2026/8/3 7:33:41 阅读更多 →
GESP C++四级考试备考指南与核心考点解析

GESP C++四级考试备考指南与核心考点解析

1. GESP C四级考试全面解析 GESP(Grade Examination of Software Programming)作为国内权威的软件编程能力认证体系,其C四级考试是中级开发者能力的重要分水岭。2024年9月这场考试不仅检验基础语法掌握程度,更侧重算法思维和工程实…

2026/8/3 7:33:41 阅读更多 →
DeepMind Crome因果鲁棒奖励建模框架深度解析:反事实数据增强破解奖励黑客与因果对齐新范式

DeepMind Crome因果鲁棒奖励建模框架深度解析:反事实数据增强破解奖励黑客与因果对齐新范式

DeepMind Crome因果鲁棒奖励建模框架深度解析:反事实数据增强破解奖励黑客与因果对齐新范式 一、引言:当奖励模型成为对齐的瓶颈 大语言模型(LLM)的对齐技术——RLHF(基于人类反馈的强化学习)——本质上依赖一个关键组件:奖励模型(Reward Model, RM) 。RM负责对模型…

2026/8/3 7:33:41 阅读更多 →
Flutter布局核心:Row、Column与Container实战指南

Flutter布局核心:Row、Column与Container实战指南

1. Flutter布局基础:从入门到精通的实战指南在移动应用开发领域,Flutter以其出色的跨平台能力和高效的渲染性能赢得了众多开发者的青睐。作为一名长期使用Flutter进行应用开发的工程师,我深刻体会到布局系统是整个Flutter开发中最基础也最核心…

2026/8/3 7:33:41 阅读更多 →
C#编码规范与命名规则最佳实践

C#编码规范与命名规则最佳实践

1. C#编码习惯与命名规则概述在C#开发领域,良好的编码习惯和命名规则就像建筑师的施工规范一样重要。我见过太多因为命名混乱、风格不统一导致的项目维护噩梦——三个月前写的代码连自己都看不懂,更别说团队协作了。根据微软官方指南和15年行业实践&…

2026/8/3 7:32:41 阅读更多 →

日新闻

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南

3个让你工作效率翻倍的Umi-OCR实战技巧:免费离线文字识别完全指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片,PDF文档识别,排除水印/页眉页脚,扫描/生成二维码。…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

[具身智能-181]:PC+服务器+具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构

PC服务器具身机器人:构建具身智能从仿真到量产的闭环迭代混合架构一、前言:具身智能需要“混合算力闭环系统”传统人工智能依赖云端静态数据集训练,不具备物理交互能力,无法适应真实世界的不确定性。具身智能(Embodied…

2026/8/3 0:00:47 阅读更多 →
[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

[具身智能-181]:大分布式通信模型对比:看懂为什么 DDS 是 ROS2 底层通信最优解

前言构建机器人、具身智能这类分布式实时系统,通信底座直接决定整套系统的实时性、容错性、组网能力。分布式领域长期存在 4 类经典通信架构:点对点模式、Broker 中间代理模式、广播模式、以数据为中心(DDS)模式。很多开发者疑惑&…

2026/8/3 0:00:47 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/3 4:58:13 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/3 1:53:31 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/3 4:36:35 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/2 6:34:16 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/3 5:19:38 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/2 0:23:22 阅读更多 →