MySQL Undo Log 深度解析:表空间、MVCC、回滚机制与版本演进全解

引言

作为 InnoDB 存储引擎的核心组件之一,Undo Log(撤销日志) 是事务执行、回滚、多版本并发控制(MVCC)的基石。它与 Redo Log、Binlog 一起构成 MySQL 事务的三大日志体系,分别负责不同方向的保障:Undo 回滚、Redo 崩溃恢复、Binlog 主从复制与归档

本篇文章从存储结构到工作原理,从事务执行到版本演进,为你彻底讲清 Undo Log 完整机制。

一、InnoDB 表空间:Undo Log 的家在哪里

什么是表空间(Tablespace)

InnoDB 把所有数据、索引、Undo Log 等都放在"表空间"里。表空间本质是一个逻辑存储结构,用于将物理文件组织成可管理的存储单元。

InnoDB 中常用的表空间类型:

类型 说明
System Tablespace(共享表空间) 默认在 ibdata1 中,早期版本 Undo Log 全在这里
File-Per-Table Tablespace(独立表空间) 每个表一个 .ibd 文件
Undo Tablespace(独立 Undo 表空间) 5.6+,将 Undo Log 从共享空间中分离出来
Temporary Tablespace 存储临时数据

共享表空间(System Tablespace)

结构特点:

  • 默认文件:ibdata1

  • 存储内容:

  • Undo Log(旧版)

  • Data Dictionary

  • Doublewrite Buffer

  • Change Buffer

  • 部分索引数据

优点

  • 统一管理,结构简单
  • Undo Log 可以复用,节省管理成本

缺点

  • 文件永不缩小(历史性痛点)
  • 所有表数据混在一个大文件里,迁移不便
  • Undo Log 导致空间膨胀难清理

独立表空间(File-Per-Table)

每个表一个 .ibd 文件,结构更清晰。

优点

  • 删除表时空间可回收
  • 表迁移、备份更灵活
  • 更利于 SSD 的顺序写和扩展

缺点

  • Undo Log 仍可能在共享表空间中(5.6 之前)
  • 文件数量多,维护成本提升

独立 Undo 表空间(Undo Tablespace) ------ 事务写入的全新归宿

MySQL 5.6 后,Undo Log 移到独立的 undo_001undo_002 等文件中。

优势:

  • Undo 页可以独立回收
  • 降低共享表空间膨胀
  • Undo 存储更高效

二、Undo Log 的作用:回滚与 MVCC 的基础

Undo Log 是一类 逻辑日志,记录的是数据修改之前的"旧值"。

Undo Log 两大核心能力:

① 事务回滚

示例:

sql 复制代码
UPDATE account SET balance = balance - 100 WHERE id = 1;

假设原 balance = 500。

Undo Log 会记录:

sql 复制代码
(undo record)
table: account
id=1
balance = 500

如果事务回滚,用该记录恢复数据即可。

② MVCC(多版本并发控制)实现的关键

MVCC 依赖 Undo Log 与隐藏列:

隐藏列 含义
trx_id 本行被哪个事务修改
roll_pointer 指向 Undo Log 的指针

查询时根据版本链判断行的可见性。

假设对一个行进行了三次修改:

sql 复制代码
最新版本(data3)
    ↑ roll_pointer
data2
    ↑ roll_pointer
data1(最旧)

每个版本存储在 Undo Log 中,每个查询根据事务级别读取不同版本。

三、Undo Log vs Redo Log vs Binlog:三者区别一文看懂

Undo Log 与 Redo Log 区别

对比项 Undo Log Redo Log
作用 回滚行记录、MVCC 数据页崩溃恢复
记录内容 数据修改前的旧值 数据修改后的物理变化
格式 逻辑日志 物理日志
写入时机 数据修改时生成 Buffer Pool 脏页产生时生成

一句话总结:

Undo 负责撤销,Redo 负责重做。

Redo+Binlog 能否替代 Undo Log?

不能。

原因如下:

① Binlog 只用于主从复制与归档

  • Binlog 是逻辑日志
  • 不记录行版本
  • 无法支持 MVCC
  • 无法撤销未提交事务

② Redo Log 不记录旧值

  • Redo 记录页物理变化
  • 不能回滚数据
  • 只能确保数据不丢(崩溃恢复)

因此 Undo Log 是不可替代的。

Binlog 三种格式区别

格式 优点 缺点
STATEMENT 体积小 难以重现执行环境
ROW 精确记录每行变化 文件巨大
MIXED 折中模式 实现复杂

Binlog 主要用于:

  • 主从复制
  • PITR 时间点恢复
  • 审计与数据归档

四、Undo Log 的物理结构与写入过程

Undo Log 属于 Undo Space 中的段(Segment),包含两类记录:

类型 说明
Insert Undo Log Insert 事务提交后即可清除
Update Undo Log 删除或更新记录的旧版本,用于 MVCC

Undo Log 写入流程(配合 MVCC)

假设执行:

sql 复制代码
UPDATE user SET age = 20 WHERE id=1;

流程如下:

  • 生成 Undo 记录(旧值)

  • 将 Undo 记录写入 Undo Page

  • Data Page 写入新值(Buffer Pool)

  • Redo Log 记录物理变化

  • 提交事务后

  • Insert Undo 可立即清理

  • Update Undo 在无事务使用后由 Purge Thread 清除

五、事务回滚机制:如何恢复旧值

回滚操作过程如下:

  • 事务遇到 ROLLBACK 或发生异常
  • 获取 Undo Log 版本链
  • 按链表顺序倒序恢复每条记录
  • Redo Log 会记录 Undo 操作(保证 crash-safe)
  • 事务失败结束

Undo 与 Redo 是双向联动保证一致性的。

六、Undo Log 堆积问题:为什么空间越来越大?

Undo Log 堆积主要源于:

① 长事务

某个事务长时间未提交,旧版本无法被清理。

② Purge Thread 太慢

磁盘 IO 高、系统繁忙导致清理不及时。

③ 大量读取历史版本

MVCC 查询导致版本被引用无法删除。

解决方案

  • 关闭长事务
  • 确保自动提交
  • 优化 Purge
  • MySQL 8.0 后 Undo 表空间支持 truncate 回收空间

七、MySQL 各版本 Undo Log 演进

MySQL 5.5 及以前

  • Undo 全部在共享表空间
  • 无法回收空间
  • 容易膨胀

MySQL 5.6

  • 引入独立 Undo 表空间
  • 支持回收 Undo

MySQL 5.7

  • 多 Undo Tablespace
  • Undo 自动 purge 更智能

MySQL 8.0

  • Undo 支持 truncate
  • Undo 重做机制优化
  • 根本改善长事务导致空间膨胀的问题

总结

Undo Log 的关键作用:

作用 说明
回滚能力 让事务具有"撤销"功能
MVCC 实现 快照读必须依赖 Undo
事务隔离级别保证 Repeatable Read 离不开版本链
逻辑日志 记录的是"旧值"

Undo 在整个 MySQL 体系中不可替代。

Redo 负责让数据不丢,

Binlog 负责让数据能复制,
Undo 负责让事务可回滚、多版本可读取

三者共同组成了 MySQL 事务引擎的铁三角。

相关推荐
fenglllle19 小时前
MySQL explain format的差异
数据库·mysql
哈哈不让取名字20 小时前
用Pygame开发你的第一个小游戏
jvm·数据库·python
程序员敲代码吗20 小时前
Python异步编程入门:Asyncio库的使用
jvm·数据库·python
liux352820 小时前
MySQL主从复制技术全面解析:从基础原理到高级架构实践(八)
mysql
a程序小傲20 小时前
听说前端又死了?
开发语言·前端·mysql·算法·postgresql·深度优先
志凌海纳SmartX20 小时前
榫卯企业云平台:让企业自建云更简单
数据库
老邓计算机毕设20 小时前
SSM学生信息管理系统ow05a(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学生信息管理系统·ssm 框架·高校教育管理
小Mie不吃饭20 小时前
MySQL慢查询日志全解析:从配置到优化实践
mysql
Access开发易登软件21 小时前
数据处理中的两大基石:何时选择Excel,何时考虑Access
数据库·信息可视化·excel·vba·access