大家好我是小耶写功课只是为了我踩过的坑你们别再踩了之前写过事务隔离级别——脏读、不可重复读、幻读。但那是表象。隔离级别是怎么实现的为什么InnoDB能做到“读不阻塞写、写不阻塞读”为什么RR级别下幻读没有被完全解决答案都在MVCC多版本并发控制里。今天把MVCC的底层机制彻底拆开讲清楚。一、什么是MVCCMVCCMulti-Version Concurrency Control多版本并发控制。它的核心思想是同一行数据在数据库中保留多个版本不同事务读取时看到的是符合自己隔离级别的那个版本。InnoDB为每一行数据维护了三个隐藏字段DB_TRX_ID6字节最后一次修改该行的事务IDDB_ROLL_PTR7字节指向Undo Log中该行的上一个版本DB_ROW_ID6字节如果没有显式主键InnoDB用它生成聚簇索引DB_ROLL_PTR是版本链的关键——通过它当前行可以一路回溯到所有历史版本。二、版本链是怎么构建的每次对数据进行修改UPDATE或DELETEInnoDB都会在Undo Log中记录修改前的旧值。修改后当前行的DB_ROLL_PTR指向Undo Log中的旧版本。举个例子一个事务把id1的name从张三改成李四再把age从25改成26。版本链会变成当前行: name李四, age26, trx_id100, roll_ptr - Undo Log ↑ Undo Log: name李四, age25, trx_id100, roll_ptr - Undo Log ↑ Undo Log: name张三, age25, trx_id90, roll_ptr - NULL版本链的每一个版本都记录了修改它的事务ID。这个ID是Read View判断“哪个版本可见”的核心依据。三、Read View决定哪个版本可见Read View是事务在快照读时生成的一个“可见性判断规则”。它包含四个核心字段字段含义m_ids当前活跃事务ID列表已启动但未提交的事务min_trx_id活跃事务中最小的事务IDmax_trx_id下一个将要分配的事务IDcreator_trx_id创建这个Read View的事务ID当一个事务要读取某行数据时沿着版本链从头开始找如果版本的trx_id小于min_trx_id说明这个版本在Read View创建之前就已提交——可见如果版本的trx_id大于等于max_trx_id说明这个版本在Read View创建之后才启动——不可见如果trx_id在min_trx_id和max_trx_id之间如果trx_id在m_ids列表中说明事务还活跃——不可见如果不在说明已提交——可见沿着版本链一直找到第一个可见的版本就是当前事务能读到的数据。四、RC和RR的Read View差异这是MVCC最核心的差异点。隔离级别Read View生成时机效果READ COMMITTED每次SELECT都生成新的Read View能读到其他事务最新提交的数据REPEATABLE READ只在事务第一次SELECT时生成之后复用整个事务期间看到的是同一份快照RC下事务A第一次SELECT时看到的是当时的数据快照。事务B提交后事务A再次SELECT会生成新的Read View看到事务B提交的数据。这就是“读已提交”。RR下事务A第一次SELECT生成Read View后后续所有SELECT都复用这个Read View。即使事务B提交了事务A也看不到——因为它仍然用旧Read View判断可见性。这就是“可重复读”。这也解释了为什么RR级别下幻读没有被完全解决。快照读普通SELECT下RR确实避免了幻读——因为Read View不变新插入的行对当前事务不可见。但当前读SELECT ... FOR UPDATE、SELECT ... LOCK IN SHARE MODE会读取最新数据如果另一个事务插入了新行当前读会看到它——这就是幻读。五、快照读与当前读InnoDB的读操作分两种快照读Snapshot Read普通的SELECT语句。读取的是Read View决定的历史版本不加锁不阻塞写。当前读Current ReadSELECT ... FOR UPDATE、SELECT ... LOCK IN SHARE MODE、INSERT、UPDATE、DELETE。读取的是最新版本需要加锁。读类型语句是否加锁读取版本快照读普通SELECT不加锁Read View决定的版本当前读FOR UPDATE / 写操作加锁最新版本MVCC的核心价值就在于快照读——读操作不需要加锁写操作不会被读阻塞。这是InnoDB高并发性能的基石。六、长事务与Undo Log膨胀MVCC有一个代价历史版本必须保留到不再被任何Read View需要为止。如果一个事务长时间不提交它持有的Read View会一直阻止InnoDB清理旧版本。Undo Log不断膨胀占用大量表空间。监控长事务SELECT trx_id, trx_state, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS duration_sec FROM information_schema.innodb_trx WHERE TIMESTAMPDIFF(SECOND, trx_started, NOW()) 60;如果发现长事务需要评估是否可以提交或回滚。监控指标Innodb_history_list_length持续增长说明Undo Log清理不及时版本链过长。七、小结MVCC是InnoDB并发控制的内核。版本链记录历史Read View决定可见性快照读利用MVCC实现无锁读当前读读取最新版本并加锁。RC和RR的核心差异在于Read View的生成时机——每次SELECT vs 首次SELECT。理解MVCC才能理解InnoDB为什么能做到高并发下的读写不互相阻塞。小耶在手SQL 不愁还有什么想了解的欢迎留言小耶一定知无不言言无不尽……我们下次见~
企业数字化 ERP 产品动态
相关推荐
疾风之刃千月姬转职面试必问的5个代码坑 疾风之刃千月姬转职面试必问的5个代码坑 复制来的代码跑不通不知道怎么调,这是很多后端开发者在接手“疾风之刃千月姬转职”这类高并发游戏业务逻辑时的噩梦。尤其是当面试官抛出这个看似简单实则暗藏玄机的场景时,你能否在3分钟内定位到事务一致性的死穴… · 2026/9/23 9:34:39
Kepler.gl 热力图(Heatmap)图层详解:强度聚合、GPU 密度渲染与参数配置 数据可视化数据分析 【免费下载链接】kepler.gl Kepler.gl is a powerful open source geospatial analysis tool for large-scale data sets. 项目地址: https://gitcode.com/gh_mirrors/ke/kepler.gl 点击查看 免费下载 kepler.gl 的热力图(Heatmap&a… · 2026/9/23 9:34:39
小木屋免费手机影院新手避坑指南:3个致命错误让你少走弯路 小木屋免费手机影院新手避坑指南:3个致命错误让你少走弯路 别再看那几百页的官方文档了,真的,直接看这篇。 刚入行或者转行做开发的朋友,是不是经常被官方文档劝退?密密麻麻的文字,术语满天飞,看完还是不知道代码该往哪写。这就是典型的“新手避坑”… · 2026/9/23 9:34:26
weh 浏览器扩展开发实战:跨浏览器兼容与消息通信避坑指南 1. weh 项目到底在解决什么问题第一次接触 weh 这个开源项目的人,大概率是被"WebExtensions Helper"这个名字吸引过来的。浏览器扩展开发这件事,说简单也简单,写个 manifest.json 加几行 JavaScript 就能跑起来;说复杂也… · 2026/9/23 10:23:27
校准分位数与报童模型的等价性 import numpy as np
from scipy.stats import norm# 定义成本结构
p_s 10 # 缺货成本
w 5 # 积压成本# 计算最优订货量对应的分位数
tau p_s / (p_s w)# 假设需求分布为正态分布
mu 100 # 均值
sigma 20 # 标准差# 计算最优订货量Q
Q norm.ppf(tau, locmu, scale… · 2026/9/23 10:23:14
5分钟搞懂dnf阿拉德大陆毁灭逻辑,搞定高频面试题 5分钟搞懂dnf阿拉德大陆毁灭逻辑,搞定高频面试题 官方文档往往厚达数百页,新手打开后直接劝退,抓不住重点。 很多开发者在准备 高频面试题 时,面对《dnf阿拉德大陆毁灭》这类大型项目的底层逻辑一头雾水。 其实核心就三点:… · 2026/9/23 10:23:07
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29