什么是版本链?

在 MySQL InnoDB 的 MVCC 机制中,版本链 是一行数据的所有历史版本通过回滚指针串联起来的单向链表,它是实现快照读的核心数据结构。

一、版本链的构成要素

版本链的每一个节点,都是一行数据的一个历史版本,而串联这些节点的关键,就是 InnoDB 为每行数据隐式添加的两个字段:

  1. **DB_TRX_ID**标记创建这个版本的事务 ID,相当于给这个版本贴了一个 "身份标签"。
  2. DB_ROLL_PTR (回滚指针)这是版本链的 "链条",它指向当前版本的上一个历史版本 (这个历史版本存储在 undo log 中)。

除此之外,每行数据的最新版本 会直接存储在数据页中,而历史版本则全部保存在 undo log 里。

二、版本链的生成过程(一步一步拆解)

我们用一个具体的例子,看一行数据的版本链是如何随着事务操作逐步变长的。假设表 user 有一行初始数据:id=1, name="张三",此时它的隐藏字段状态:

  • DB_TRX_ID = 0(表示这是初始化版本,无事务修改)
  • DB_ROLL_PTR = null(无历史版本,链表头)
步骤 1:事务 101 执行 UPDATE(第一次修改)
sql 复制代码
BEGIN;
UPDATE user SET name = "李四" WHERE id = 1;
COMMIT;

InnoDB 的处理逻辑:

  1. 先把当前行的原始版本 (name=张三, DB_TRX_ID=0, DB_ROLL_PTR=null)拷贝到 undo log 中;

  2. 修改数据页中的当前行:name=李四,更新隐藏字段:

    • DB_TRX_ID = 101(标记是事务 101 修改的)
    • DB_ROLL_PTR = 指向 undo log 中的原始版本
  3. 此时版本链结构:

    复制代码
    数据页当前版本(101: 李四) → undo log 历史版本(0: 张三)
步骤 2:事务 102 执行 UPDATE(第二次修改)
sql 复制代码
BEGIN;
UPDATE user SET name = "王五" WHERE id = 1;
COMMIT;

InnoDB 的处理逻辑:

  1. 把数据页中的当前版本 (name=李四, DB_TRX_ID=101, DB_ROLL_PTR=指向旧版本)拷贝到 undo log;

  2. 修改当前行:name=王五,更新隐藏字段:

    • DB_TRX_ID = 102
    • DB_ROLL_PTR = 指向 undo log 中的 101 版本
  3. 此时版本链变长:

    复制代码
    数据页当前版本(102: 王五) → undo log 版本1(101: 李四) → undo log 版本2(0: 张三)
核心规律
  • 每次 UPDATE/DELETE 操作,都会生成一个新的历史版本,并追加到版本链尾部;
  • INSERT 操作不会生成历史版本(因为插入前该行不存在),所以不会影响版本链;
  • 版本链的遍历方向是从当前版本到最旧版本。

三、版本链的核心作用

版本链的唯一作用,就是为快照读提供历史版本数据 ,配合 Read View 实现 "读不阻塞写"。

具体流程是:

  1. 事务执行快照读(普通 SELECT)时,会生成一个 Read View(版本可见性规则);
  2. 先读取数据页中的当前版本 ,用 Read View 判断这个版本是否可见:
    • 如果可见,直接返回;
    • 如果不可见,就通过 DB_ROLL_PTR 遍历版本链,去 undo log 中找下一个历史版本;
  3. 重复步骤 2,直到找到第一个符合 Read View 规则的可见版本,返回该版本数据。

四、版本链的清理机制

版本链不会无限变长,否则 undo log 会越来越大,占用大量磁盘空间。InnoDB 的 purge 线程 会定期清理版本链中不再需要的历史版本------ 判断标准是:

没有任何活跃事务的 Read View 会用到这个历史版本。

比如,所有事务的快照读都不需要访问 undo log 中的 0 版本了,purge 线程就会把这个版本从 undo log 中删除,版本链也会相应缩短。

相关推荐
2401_891409261 小时前
量化数据13:港股分钟K线、Level2逐笔Tick、十档盘口和港股通历史数据的批量提取
数据库
w-w0w-w7 小时前
SQL注入
网络·数据库·sql
tianyuanwo8 小时前
NetBox 数据库详解:当“关系型数据库”被装进一个网络运维的领域模型里
运维·数据库·netbox
一条泥憨鱼8 小时前
【计算机网络】短连接、长连接与连接池:从 TCP 握手到池化复用的完整链路
网络·数据库·网络协议·tcp/ip·计算机网络
IvorySQL8 小时前
深入 PostgreSQL WAL:从崩溃恢复到逻辑复制
数据库·postgresql
幽灵诶9 小时前
Mysql(基于测试的学习)
数据库·mysql
砚底藏山河9 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
宇宙无敌暴龙战士66610 小时前
MySQL 8 库表操作学习笔记:SQL 基础、库表管理、约束与用户授权全流程
数据库·sql·mysql·学习笔记·后端开发
猿究院_夏燊10 小时前
MySQL 的四种隔离级别
java·数据库·mysql
say_fall10 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++