深度解析Mysql中MVCC的工作机制

MVCC,多版本并发控制

  • 定义:维护一个数据的多个版本 ,使读写操作没有冲突,依赖于:隐藏字段,undo log日志,readView

  • MVCC会为每条版本记录保存三个隐藏字段

    1. DB_TRX_ID : 记录最近插入或修改该记录的事务ID
    2. DB_ROLL_PTR :回滚指针,指向这条记录的上个版本,配合undo log
    3. DB_ROW_ID隐藏主键,如果没有指定主键,将会生成该隐藏主键

    流程(重点):在修改数据前,innodb引擎会在undo log 日志拷贝一份原记录 ,并将其DB_ROLL_PTR指向上一个版本 ,形成版本链 。然后修改数据值 ,并把DB_TRX_ID 改为当前执行的事务ID

  • readView

    1. 定义:确定事务在快照读时 能够看到数据库中的哪些数据版本

    2. 区分:

      当前读 :读取的是记录的最新版本 ,对读取的记录加锁 ,保证读取时其他并发事务不能修改当前记录,解决幻读

      快照读 :select查询,不加锁,读取记录数据的可见版本 (通过事务ID递增性判断是否可见)

      1. Read Commited每次select都生成一个readView,读取可见记录中的最新版本,会造成不可重复读的问题
      2. Repetable Read :事务首次 select时生成 readView,后续复用该readView**
  1. 定义:确定事务在快照读时 能够看到数据库中的哪些数据版本

  2. 区分:

    当前读 :读取的是记录的最新版本 ,对读取的记录加锁 ,保证读取时其他并发事务不能修改当前记录,解决幻读

    快照读 :select查询,不加锁,读取记录数据的可见版本 (通过事务ID递增性判断是否可见)

    1. Read Commited每次select都生成一个readView,读取可见记录中的最新版本,会造成不可重复读的问题
    2. Repetable Read :事务首次 select时生成 readView,后续复用该readView
  3. 流程:基于快照读 生成的readview ,跟要查询的行数据的mvcc版本DB_TRX_ID 做比较,基于事务ID的递增性 判断mvcc版本 是否对当前readview可见 ,如果可见则返回当前mvcc版本的行数据,如果不可见 ,则通过mvcc的回滚指针回退到上一个版本。

  4. 判断MVCC版本是否对当前readView可见:mvcc版本的DB_TRX_ID字段readView的字段比较,满足以下任意条件:

    • DB_TRX_ID < min_trx_id(最小事务ID):该版本的事务比所有活跃事务(正在运行)更早创建且已提交,因此可见
    • DB_TRX_ID = creator_trx_id(创建该readview的事务ID):当前事务自己生成的版本(即使未提交),对自己总是可见
    • DB_TRX_ID < max_trx_id (预分配事务ID)&& DB_TRX_ID not in m_ids(活跃的事务ID列表中): 该版本的事务不在创建 read view 时的活跃事务列表中,说明已提交
相关推荐
用户2986985301421 分钟前
.NET 文档自动化:Spire.Doc 设置奇偶页页眉/页脚的最佳实践
后端·c#·.net
随风飘的云43 分钟前
mysql的innodb引擎对可重复读做了那些优化,可以避免幻读
mysql
码路飞1 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
序安InToo1 小时前
第6课|注释与代码风格
后端·操作系统·嵌入式
xyy1231 小时前
C#: Newtonsoft.Json 到 System.Text.Json 迁移避坑指南
后端
洋洋技术笔记1 小时前
Spring Boot Web MVC配置详解
spring boot·后端
JxWang051 小时前
VS Code 配置 Markdown 环境
后端
navms1 小时前
搞懂线程池,先把 Worker 机制啃明白
后端
JxWang051 小时前
离线数仓的优化及重构
后端
Nyarlathotep01131 小时前
gin01:初探gin的启动
后端·go