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

【Mysql】MySQL的MVCC及实现原理,核心目标与全流程图解

MySQL的MVCC及实现原理,核心目标与全流程图解

  • 一、MVCC核心
    • 解决两大问题:
    • MVCC 全流程图解
  • 二、MVCC核心实现组件
    • 1. 隐藏字段(InnoDB表必有)
    • 2. Undo Log(版本链)
    • 3. ReadView(可见性判断核心)
  • 三、可见性判断算法(RR隔离示例)
    • 代码级判断逻辑:
  • 四、不同隔离级别的实现差异
  • 五、实战案例演示(RC vs RR)
    • 结果对比:
  • 六、关键参数优化
  • 七、MVCC的限制

一、MVCC核心

MySQL MVCC(多版本并发控制)是 ​InnoDB 引擎实现高并发的核心技术,其本质是 ​通过数据多版本实现读写操作的并行执行。

解决两大问题:

  1. 读写冲突:读操作不阻塞写操作
  2. 事务隔离:实现RC(读已提交)、RR(可重复读)隔离级别

📌 关键设计:通过数据多版本+版本可见性判断实现

MVCC 全流程图解

不可见
事务开始
分配trx_id
数据修改
写Undo Log
更新行DB_TRX_ID/DB_ROLL_PTR
读操作
创建ReadView
检查当前行可见性
沿Undo链回溯
找到可见版本
Purge线程
清理过期Undo Log

二、MVCC核心实现组件

1. 隐藏字段(InnoDB表必有)

字段名长度作用
DB_TRX_ID6字节最新修改该行的事务ID
DB_ROLL_PTR7字节指向Undo Log的回滚指针
DB_ROW_ID6字节行隐藏ID(无主键时自增)
-- 查看行隐藏字段(虚拟列)
SELECT `DB_TRX_ID`,   -- 最后更新事务ID`DB_ROLL_PTR`, -- 指向历史版本链`DB_ROW_ID`    -- 行唯一标识
FROM information_schema.INNODB_SYS_TABLES 
WHERE name = 'test/t1';

2. Undo Log(版本链)

当前行数据
Undo Log v1
Undo Log v2
Undo Log v3
  • 更新流程:每次修改前拷贝旧数据到Undo Log
  • 版本链:通过DB_ROLL_PTR串联历史版本

3. ReadView(可见性判断核心)

// 源码位置:storage/innobase/include/read0types.h
class ReadView {trx_id_t m_low_limit_id;    // 高水位ID(>此值的事务不可见)trx_id_t m_up_limit_id;     // 低水位ID(<此值的事务可见)ids_t    m_ids;             // 活跃事务ID列表trx_id_t m_creator_trx_id;  // 创建该ReadView的事务ID
};

三、可见性判断算法(RR隔离示例)

等于当前事务ID
小于m_up_limit_id
大于m_low_limit_id
在m_ids中
其他情况
读取数据行
检查DB_TRX_ID
可见
可见
不可见
不可见
可见

代码级判断逻辑:

// storage/innobase/include/read0types.h
bool changes_visible(trx_id_t id, const table_name_t& name) const {// 1. 自己修改的数据总是可见if (id == m_creator_trx_id) return true; // 2. 事务ID < 活跃事务最小ID(已提交)if (id < m_up_limit_id) return true;// 3. 事务ID >= 高水位(属于未来事务)if (id >= m_low_limit_id) return false;// 4. 事务活跃状态检查return (m_ids.find(id) == m_ids.end()); // 不在活跃列表中则可见
}

四、不同隔离级别的实现差异

隔离级别ReadView创建时机版本链访问逻辑
RC(读已提交)每次SELECT创建新ReadView总是读取最新已提交版本
RR(可重复读)首次SELECT创建ReadView复用同一视图,保持版本一致性
Serializable加锁读(不使用MVCC)无版本链

⚠️ RR防幻读机制:基于Next-Key Locking + MVCC版本快照


五、实战案例演示(RC vs RR)

-- 初始化数据
CREATE TABLE t(id INT PRIMARY KEY, v INT);
INSERT INTO t VALUES(1, 10);-- 事务1(更新数据)
START TRANSACTION;
UPDATE t SET v = 20 WHERE id = 1;-- 事务2(两次查询)
START TRANSACTION;
SELECT v FROM t WHERE id = 1; -- RC看到20|RR看到10(旧值)
COMMIT;-- 事务1提交
COMMIT;-- 事务2再次查询
SELECT v FROM t WHERE id = 1; -- RC/RR均看到20

结果对比:

步骤RC隔离级别结果RR隔离级别结果
事务2首次查询20(脏读)10(快照读)
事务2二次查询20(读已提交)10(可重复读)

六、关键参数优化

# my.cnf配置项
innodb_undo_log_truncate = ON      # 启用undo log清理
innodb_max_undo_log_size = 1G      # 控制版本链长度
innodb_purge_threads = 4           # 后台清理线程数

七、MVCC的限制

  1. 大事务风险:长事务导致Undo Log暴涨(可能触发OOM)
  2. 历史版本清理:purge线程滞后可能引发性能问题
  3. 二级索引更新:仅主键存储版本链,二级索引通过主键回表判断可见性

📊 监控建议:定期检查SHOW ENGINE INNODB STATUS中的History list length


通过【隐藏字段+Undo版本链+ReadView】三元组配合,MySQL实现在不锁定读的情况下保证事务隔离。核心在于多版本数据存储+事务快照判断,此设计也是InnoDB高并发能力的基石。

http://www.xdnf.cn/news/1057429.html

相关文章:

  • 获取ip地址安全吗?如何获取静态ip地址隔离ip
  • 常见航空数码相机
  • 基于SpringBoot的民宿管理平台-037
  • 【Linux指南】文件内容查看与文本处理
  • 操作系统引导和虚拟机(包含os结构,选择题0~1题无大题)
  • 编译链接实战(27)动态库实现变了,可执行程序需要重新编译吗
  • 互联网思维概念和落地
  • 如何写一个简单的python类class
  • 影视剧学经典系列-梁祝-《闲情赋》
  • 如何让DeepSeek-R1-Distill-Qwen-32B支持Function calling
  • 学习昇腾开发的第三天--将服务器连接网络
  • 【锂电池剩余寿命预测】XGBoost锂电池剩余寿命预测(Pytorch完整源码和数据)
  • 外观模式Facade Pattern
  • 02- 六自由度串联机械臂(ABB)运动学分析
  • C++面向对象编程:简洁入门
  • RPG29:制作ui基础
  • YoloV12改进策略:Block改进|MKP,多尺度卷积核级联结构,增强感受野适应性|即插即用|AAAI 2025
  • 命令模式Command Pattern
  • 多线程并发编程硬核指南:从互斥锁到生产者模型的全场景实战与原理揭秘
  • C++(初阶)(二十一)——unordered_set和unordered_map
  • Addressable-引用计数
  • DDD领域驱动设计学习路线
  • VS202静态库制作和使用指南
  • 【Android】输入路由
  • 将CVAT点云格式标注格式由datumaro转换为kitti格式
  • 软件测试用例(一)
  • Java锁机制:ReentrantLock深度解析与锁粒度优化实践(时序图详解)
  • 交互式编程:编程范式的静默革命
  • 在windows10上安装nvm以及配置环境
  • 【推荐】城市灾害应急管理系统【面试模拟题目——字节跳动面试原题】