尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

MVCC、幻读、间隙锁与临键锁

MVCC、幻读、间隙锁与临键锁
📅 发布时间:2026/6/20 13:03:37

一、MVCC 解决了什么问题?

🌱 背景:并发读写冲突

当多个事务同时操作同一行时,最经典的冲突是:

  • A 在读;

  • B 在写;

  • A 还没提交,B 改了数据;

  • 如何让 A 看到一致的结果?

MVCC(Multi-Version Concurrency Control,多版本并发控制)
👉 解决的核心问题是:

✅ 在高并发环境下,读写不阻塞,并且保证事务隔离一致性(尤其是可重复读 / Repeatable Read)。

也就是说,MVCC 让:

  • “读操作”不用加锁就能读到事务一致视图;

  • “写操作”也能正常进行,不会阻塞读;

  • 事务之间看到的数据是一致的(基于事务启动时的快照)。


二、MySQL 幻读解决了吗?

要看事务隔离级别和读类型:

读类型读已提交 (RC)可重复读 (RR)说明
普通快照读 (SELECT …) ✅ 幻读存在 ✅ 已解决 RR 下 MVCC + 间隙锁配合消除幻读
当前读 (SELECT … FOR UPDATE / UPDATE / DELETE) ✅ 幻读存在 ✅ 已解决 RR 下间隙锁和临键锁阻止插入

✅ 结论:

在 可重复读(RR) 隔离级别下,InnoDB 已经彻底解决了幻读问题。


三、MVCC 的实现原理(核心机制)

InnoDB 通过 隐藏列 + Undo Log + Read View 三个机制实现多版本并发控制。

1️⃣ 隐藏列(3个)

每行数据除了用户字段外,InnoDB 内部维护三个隐藏列:

  • DB_TRX_ID:最后修改该行的事务 ID。

  • DB_ROLL_PTR:指向 undo log 的指针(用于找到旧版本)。

  • DB_ROW_ID:行的自增主键(非显式主键时存在)。


2️⃣ Undo Log(版本链)

每当事务修改一行数据时:

  • 不直接覆盖,而是把旧值写入 undo log;

  • 并在当前行的 DB_ROLL_PTR 指向该 undo log;

  • 从而形成一个“版本链”:

 
最新行 (trx_id=100) → undo_log_99 → undo_log_80 → ...

每个版本都有自己的事务 ID。


3️⃣ Read View(读视图)

当事务执行第一个一致性读时(例如 SELECT),InnoDB 会生成一个 Read View,记录以下信息:

字段含义
m_ids 当前系统中活跃事务的 ID 列表
min_trx_id 当前活跃事务中最小的事务 ID
max_trx_id 当前还未分配的下一个事务 ID(上限)
creator_trx_id 当前事务自身 ID

4️⃣ MVCC 读版本规则(判断可见性)

InnoDB 判断一行是否对当前事务可见,遵循如下规则:

设该行版本的 trx_id = X

条件是否可见
X < min_trx_id ✅ 已提交的旧事务,数据可见
X ∈ m_ids ❌ 正在执行的事务,不可见
X > max_trx_id ❌ 新事务创建的数据,不可见

如果该版本不可见,就顺着 undo log 找上一个版本,直到找到可见版本。

👉 这就是“多版本”:读事务读的是自己快照中可见版本的链。


四、幻读问题 & 间隙锁 / 临键锁如何解决

1️⃣ 什么是幻读

幻读:事务 A 重复执行相同的查询,却发现多了(或少了)几行记录。

例:

 
-- 事务A SELECT * FROM user WHERE age > 18; -- 查询到10条 -- 事务B INSERT INTO user(age=20); -- 事务A 再次执行同样查询,发现11条 -> 幻读

2️⃣ MVCC 能防幻读吗?

👉 只对已存在的行有效;
但是对新插入的行(不存在的版本链)无能为力。
所以要用锁机制配合。


3️⃣ 间隙锁(Gap Lock)

作用于“记录之间的空隙”,阻止其他事务在间隙内插入数据。

例:

 
SELECT * FROM user WHERE age > 18 FOR UPDATE;

假设表中有 age=10, 20, 30
事务 A 会锁定:

 
(10,20), (20,30), (30, +∞)

→ 其他事务不能在这些区间插入新的行。

📌 解决了“幻读”的核心问题:

防止别的事务在当前事务扫描范围内插入新数据。


4️⃣ 临键锁(Next-Key Lock)

是 记录锁(Record Lock) + 间隙锁(Gap Lock) 的组合。
锁定“当前行 + 前一个间隙”。

例如:

 
SELECT * FROM user WHERE age = 20 FOR UPDATE;

假设有行 (age=20),临键锁会锁定区间 (10,20]。

📌 优势:

  • 保证唯一性;

  • 避免插入相同主键;

  • 避免幻读(锁定扫描范围内的间隙)。


五、例子总结:快照读 vs 当前读

场景使用方式锁类型是否受MVCC影响是否防幻读
快照读 SELECT ... 无锁 ✅ 是 ✅ RR 下已解决
当前读 SELECT ... FOR UPDATE、UPDATE、DELETE 临键锁 / 间隙锁 ❌ 否 ✅ 防止插入幻读

六、总结对比表

机制解决问题原理是否加锁是否防幻读
MVCC 读写并发、可重复读 undo log + Read View ❌ ✅(快照读)
间隙锁 防止插入幻读 锁定记录间隙 ✅ ✅
临键锁 防止幻读 + 保证唯一性 记录锁 + 间隙锁 ✅ ✅

✅ 一句话总结:

MVCC 让读写不互斥(靠版本链解决读一致性);
间隙锁 & 临键锁让写不产生幻读(靠锁定范围防插入)。

郭慕荣博客园

相关新闻

  • 读AI赋能01超级能动性
  • SGD 到 AdamW 优化器的实践选型指南
  • # TLP电池管理工具:Linux笔记本续航优化的终极指南

最新新闻

  • 嵌入式GUI开发实战:emWin窗口管理器消息机制、ToolTips与多图层应用详解
  • 简单理解:为什么SVPWM没看到提反Clarke变换
  • public-apis 项目深度解析:442K Stars的免费API大全
  • 在哪个软件找工作真实可靠?五大招聘平台实测对比 - 博客万
  • Gemini 3.5国内一键可用:服务发现层软适配实战指南
  • 2026年6月最新江诗丹顿中国官方售后联系电话与客户服务中心网点地址 - 江诗丹顿服务中心

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号