当前位置: 首页 > news >正文

MySQL-MVCC核心原理-版本链ReadView与可见性判断

MVCC 全称是 Multi-Version Concurrency Control,也就是多版本并发控制。它的核心思想是:为同一行数据维护多个版本,让读写在很多情况下不用互相阻塞。

没有 MVCC 时,读写冲突通常要大量依赖锁。MVCC 让普通select可以读一个可见的数据版本,而不是必须等待正在修改这行数据的事务结束。

MVCC 依赖哪三样东西

InnoDB 的 MVCC 主要依赖:

  1. 记录中的隐藏字段。
  2. undo log 版本链。
  3. ReadView 读视图。

这三者配合,解决一个问题:当前事务应该看到这行数据的哪个版本?

记录中的隐藏字段

InnoDB 每行记录除了业务字段,还会维护一些隐藏字段。

隐藏字段含义
DB_TRX_ID最近一次修改这行记录的事务 ID
DB_ROLL_PTR回滚指针,指向 undo log 中的上一个版本
DB_ROW_ID隐藏行 ID,没有主键时可能使用

其中DB_TRX_IDDB_ROLL_PTR是理解 MVCC 的关键。

undo log 版本链

当一行数据被多个事务修改时,undo log 会形成一条版本链。链表头部通常靠近较新的旧版本,沿着roll_pointer可以找到更早的版本。

例如一条记录从A1被改成A2,又被改成A3。当前数据页里是最新值,而 undo log 中保存旧值。不同事务根据可见性规则,可能读到A3A2A1

当前读和快照读

不是所有读都走 MVCC 快照。

类型SQL 示例特点
当前读select ... for updateupdatedeleteinsert读取最新版本,并加锁
快照读普通select读取可见版本,不加锁,非阻塞

MVCC 主要服务于快照读。普通select不加锁也能在并发写入时稳定读取,就是因为它读的是某个可见版本。

ReadView 是什么

ReadView 是快照读执行时生成的读视图,用来判断版本链上的某个版本是否对当前事务可见。

ReadView 中有四个核心字段:

字段含义
creator_trx_id创建这个 ReadView 的事务 ID
m_ids创建 ReadView 时活跃且未提交的事务 ID 集合
min_trx_id活跃事务中的最小 ID
max_trx_id下一个将要分配的事务 ID

版本可见性规则

当沿着版本链找到某个版本时,会拿这个版本的trx_id和 ReadView 比较。

这块最适合按流程走。每遇到一个版本,就问几个问题:

快照读开始

生成或复用 ReadView

读取当前记录版本

trx_id 是否等于 creator_trx_id

版本可见

trx_id 是否小于 min_trx_id

trx_id 是否大于等于 max_trx_id

版本不可见

trx_id 是否在 m_ids 中

沿 undo log 版本链找上一个版本

规则可以简化为:

  1. trx_id == creator_trx_id:自己改的,能看见。
  2. trx_id < min_trx_id:这个版本在 ReadView 生成前已经提交,能看见。
  3. trx_id >= max_trx_id:这个版本在 ReadView 生成后才出现,不能看见。
  4. min_trx_id <= trx_id < max_trx_id:如果trx_id不在m_ids中,说明已提交,能看见;如果在m_ids中,说明当时还活跃,不能看见。

这些规则的目的很朴素:只让当前事务看到它应该看到的已提交版本。

RC 和 RR 的区别

READ COMMITTEDREPEATABLE READ的核心差异之一,是生成 ReadView 的时机不同。

隔离级别ReadView 生成时机结果
READ COMMITTED每次执行快照读都生成新的 ReadView同一事务内多次查询可能看到新提交数据
REPEATABLE READ第一次快照读生成 ReadView,后续复用同一事务内多次查询结果更稳定

两种隔离级别的差别,可以这样看:

RC

RR

同一个事务内多次普通 select

隔离级别

每次 select 生成新的 ReadView

可能看到其他事务新提交的数据

第一次 select 生成 ReadView

后续 select 复用同一个 ReadView

同一事务内读取结果更稳定

这也解释了为什么 RC 下可能出现不可重复读,而 RR 能让普通快照读保持可重复。

一个简单例子

假设事务 5 创建了 ReadView:

m_ids = {3, 4, 5} min_trx_id = 3 max_trx_id = 6 creator_trx_id = 5

现在沿着版本链看到几个版本:

版本 trx_id是否可见原因
5可见当前事务自己修改
2可见小于min_trx_id,早已提交
6不可见不小于max_trx_id,属于更晚事务
4不可见m_ids中,当时未提交

如果某个版本不可见,就继续沿着 undo log 版本链向前找,直到找到可见版本或没有更旧版本。

面试回答模板

可以这样回答:

MVCC 是多版本并发控制,用来降低读写冲突。InnoDB 每行记录有隐藏字段,比如事务 ID 和回滚指针;更新数据时会生成 undo log,多个旧版本通过回滚指针形成版本链。普通 select 是快照读,会基于 ReadView 判断版本是否可见。ReadView 中包含当前活跃事务集合、最小活跃事务 ID、下一个事务 ID 和创建者事务 ID。RC 隔离级别下每次快照读都会生成新的 ReadView,RR 隔离级别下第一次快照读生成后会复用,所以 RR 下多次读取更稳定。

小结

MVCC 的难点不是名词多,而是要把它们串成一条线:隐藏字段记录版本信息,undo log 串起旧版本,ReadView 决定哪个版本可见。理解这条线,MVCC 就从“背概念”变成了“顺着链表找可见数据”。

http://www.jsqmd.com/news/832357/

相关文章:

  • 3分钟快速上手:CELLxGENE单细胞数据交互式探索终极指南
  • 从单体智能到组织智能:AgentOrg多智能体系统架构与实战
  • QMC文件解密终极指南:轻松解锁QQ音乐加密音频
  • EmoLLM:大语言模型的情感增强训练与部署实践
  • RAG知识库实战:LangChain+Chroma搭建本地问答系统,解决幻觉与知识更新
  • 命令行AI助手:自然语言驱动终端操作的技术原理与实践
  • OpenGL拼图游戏开发:从渲染管线到交互逻辑的完整实现
  • 如何让Photoshop图层批量导出速度提升3倍?这个开源脚本做到了!
  • Claude代码库分析工具:突破AI编程助手的上下文限制
  • 30亿条出行记录解密:如何用纽约出租车数据洞察城市脉搏 [特殊字符][特殊字符]
  • MySQL高可用与扩展-主从复制读写分离分库分表
  • Pipeworx官方示例库:从场景化实践到生产级数据管道构建指南
  • 可逆计算与量子电路合成:改进QM算法与全局优化
  • 开源项目管理工具sgrade/plan-manager:从部署到深度集成的工程实践
  • AI新型电力系统智能化核心场景
  • MCP服务器生产级部署:从Docker到Kubernetes的完整工程化实践
  • 法语语音合成选型决策树,深度对比ElevenLabs vs. Amazon Polly vs. Coqui TTS:含MOS评分、时延、版权条款与GDPR兼容性分析
  • Golioth Firmware SDK:物联网设备连接与管理的开源解决方案
  • 042、PCIE BAR空间类型与映射
  • 基于强化学习的机器人抓取:从PPO/SAC算法到仿真部署全解析
  • AI记忆增强系统:突破上下文限制的工程架构与实现
  • 技术人的职业发展:从运维工程师到架构师
  • MCP-Commander:让AI助手操作本地文件与命令行的智能接口
  • PowerInfer:基于稀疏激活的LLM推理引擎,消费级GPU运行百亿大模型
  • QQ截图独立版终极指南:免费高效的屏幕捕获与OCR文字提取工具
  • 5分钟快速上手:Windows虚拟显示器终极指南,轻松实现多屏扩展
  • 3分钟快速安装Android Studio中文语言包:终极免费汉化指南
  • 基于Adafruit Audio FX Mini的智能音效道具制作全流程解析
  • GitHub中文界面3分钟终极汉化指南:告别语言障碍的开发者神器
  • AI智能体记忆系统构建:基于向量检索的agentrove实践指南