news 2026/10/16 6:38:03

数据库如何通过 MVCC 实现隔离性

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据库如何通过 MVCC 实现隔离性

一、MVCC 是什么

MVCC 是一种"多版本 + 快照读"的并发控制机制,用来实现隔离性,并通过不同的 ReadView 策略支撑不同隔离级别,同时保证读写不阻塞。

二、MVCC的实现

1、隐藏字段(每行记录的“身份证”)

InnoDB 在每行记录上,除了你定义的字段,还偷偷加了几个隐藏字段:

而与 MVCC 相关的字段只有前2项

隐藏字段含义作用
DB_TRX_ID最后一次修改该行的事务 ID判断版本可见性
DB_ROLL_PTR回滚指针,指向 undo log 中的上一个版本串联版本链

2、Undo Log版本链(历史版本仓库)

每次修改数据,旧值都会被写进 undo log,并通过DB_ROLL_PTR(回滚指针)串成一条版本链。

特点:

  • 链首是最新版本。

  • 越往后越旧。

  • 每个版本都带trx_id,用于可见性判断。

3、ReadView(可见性判断容器)

这里先说一下快照读和当前读:

快照读是什么? = 读历史版本(快照),不是读最新 = 普通 SELECT = 不加锁 = 靠 MVCC 实现(ReadView + undo log 版本链) 对比: 快照读 → 读历史、不加锁、并发高 当前读 → 读最新、加锁、保证强一致

ReadView(读视图)是事务在执行快照读时生成的一个对象,里面记录了"生成这一刻"数据库的活跃事务信息,用来判断版本链上的哪个版本对当前事务可见。

ReadView 的四个字段

字段含义
m_ids生成 ReadView 时,当前活跃(未提交)的事务 ID 列表
min_trx_idm_ids 中的最小值
max_trx_id下一个将要分配的事务 ID(当前最大 +1)
creator_trx_id创建该 ReadView 的事务 ID

4、可见性判断算法

规则①:自己改的,可见

事务 A 改了数据,虽然还没提交
但 A 自己当然要能看到自己的修改
→ creator_trx_id == trx_id → 可见

规则②:早于 ReadView 生成时刻的,可见

如果 trx_id < min_trx_id
说明这个事务在 ReadView 生成之前就已经"不在活跃列表"了
→ 意味着它早就提交了 → 可见

规则③:晚于 ReadView 生成时刻的,不可见

如果 trx_id >= max_trx_id
说明这个事务是在 ReadView 生成之后才开启的
→ 快照不该看到未来的事务 → 不可见

规则④:介于两者之间的,看是否活跃

在 min 和 max 之间的,可能是:
- 已提交的
- 还活跃的
怎么区分?看它是否在 m_ids 里:
在 m_ids → 当时还活跃 → 不可见
不在 m_ids → 当时已提交 → 可见

不可见怎么办

当前版本不可见
↓
沿 DB_ROLL_PTR(回滚指针) 找上一个版本
↓
再判断,直到找到可见版本
↓
若都不可见,说明该行对当前事务"不存在"

三、隔离级别与MVCC的关系

隔离级别实现方式用 MVCC 吗
READ UNCOMMITTED(读未提交)直接读最新,不加过滤❌
READ COMMITTED(读已提交)MVCC(每次新建 ReadView)✅
REPEATABLE READ(不可重复读)MVCC(复用 ReadView)✅
SERIALIZABLE(串行化)加锁,串行执行❌

四、MVCC 如何实现 RC(读未提交)和 RR(不可重复读)

快照读时,会沿着版本链逐个判断,一旦某个版本满足当前 ReadView 的可见性规则,就读这个版本并返回。

MVCC 靠"同一个版本链 + 不同的 ReadView 生成时机",实现了 RC 和 RR 的差异。

维度RC(读已提交)RR(可重复读)
ReadView 生成时机每次 SELECT 都新建事务首次 SELECT 生成,之后复用
快照范围每次读都是"最新快照"全程一个"固定快照"
能否读到别人提交✅ 能(提交后下次读就能看到)❌ 不能(快照固定)
解决的问题脏读脏读 + 不可重复读

五、事务中的隔离性是如何保证的

事务的隔离性是由锁和 MVCC实现的。

其中MVCC的意思是多版本并发控制,指维护一个数据的多个版本,使得读写操作没有冲突。它的底层实现主要分为三个部分:隐藏字段、undo log 日志、ReadView 读视图。

隐藏字段:在 MySQL 中给每个表都设置了隐藏字段,一个是trx_id(事务 id),记录每一次操作的事务 id,是自增的;另一个是roll_pointer(回滚指针),指向上一个版本的事务版本记录地址。

undo log:主要作用是记录回滚日志,存储老版本数据。在内部会形成一个版本链,在多个事务并行操作某一行记录时,记录不同事务修改数据的版本,通过roll_pointer指针形成一个链表。

ReadView:解决的是一个事务查询选择版本的问题,在内部定义了一些匹配规则和当前的一些事务 id,判断该访问哪个版本的数据。不同的隔离级别快照读是不一样的,最终的访问结果也不一样:

  • RC 隔离级别:每一次执行快照读时生成 ReadView。

  • RR 隔离级别:仅在事务中第一次执行快照读时生成 ReadView,后续复用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 6:38:00

Haar特征描述算子详解:从积分图到级联分类器的人脸检测实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/16 6:37:20

osg模型缩放平移实战:PAT、MatrixTransform与漫游器方案详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/16 6:36:19

Yolo26介绍

Ultralytics YOLO26 是一个支持多种计算机视觉任务的多功能 AI 框架。该框架可用于执行目标检测、分割、语义分割、深度估计、分类、姿态估计以及 OBB&#xff08;带方向边界框&#xff09;检测。这些任务各有不同的目标与应用场景&#xff0c;让您能够利用单一框架应对各种计算…

作者头像 李华
网站建设 2026/10/16 6:34:57

ServerPackCreator Webservice REST API 参考与自动化实战指南

后端前端桌面应用CLI游戏开发 【免费下载链接】ServerPackCreator Create a server pack from a Minecraft Forge, NeoForge, Fabric, LegacyFabric or Quilt modpack! 项目地址&#xff1a; https://gitcode.com/gh_mirrors/se/ServerPackCreator 点击查看 免费下载 ServerPa…

作者头像 李华