MySQL每次 DML 操作生成 Redo 记录的庖丁解牛
2026/5/15 1:37:07 网站建设 项目流程

MySQL 每次 DML(INSERT/UPDATE/DELETE)操作生成 Redo 记录,是InnoDB 实现 WAL(Write-Ahead Logging)和崩溃恢复的核心机制


一、Redo 记录的本质

  • 不是逻辑日志(如 “UPDATE users SET name=‘John’ WHERE id=100”)
  • 而是物理日志
    “在数据页 X 的偏移 Y 处,写入 Z 字节的数据”
  • 目的
    崩溃恢复时,能精确重放内存中的修改,无论原始 SQL 是什么。

关键特性
Redo 记录与 SQL 无关,只与物理存储变更相关


二、DML 操作如何触发 Redo 生成

1.通用流程
RedoLogBufferBufferPoolInnoDBINSERT/UPDATE/DELETERedoLogBufferBufferPoolInnoDBINSERT/UPDATE/DELETE执行修改定位/加载目标数据页修改内存中的页生成 Redo 记录
2.各 DML 类型的 Redo 内容
操作Redo 记录内容
INSERT- 聚簇索引页插入记录
- 所有二级索引页插入记录
- Undo Log 页插入回滚段
UPDATE- 聚簇索引页原记录标记删除 + 新记录插入
- 二级索引页若键值变更:删除旧 + 插入新
- Undo Log 更新
DELETE- 聚簇索引页记录标记删除
- 二级索引页记录标记删除
- Undo Log 插入

⚠️注意
即使 UPDATE 未改变索引列,仍会生成聚簇索引的 Redo(因行数据变更)。


三、Redo 记录的内部结构

InnoDB Redo 记录采用类型化日志格式,核心字段:

// 伪代码:Redo 记录头structredo_header{uint16_ttype;// 日志类型(MLOG_1BYTE, MLOG_4BYTES...)uint16_tspace_id;// 表空间IDuint32_tpage_no;// 页号uint16_toffset;// 页内偏移uint16_tlength;// 数据长度byte data[];// 变更数据};
典型日志类型:
类型说明示例
MLOG_WRITE_STRING写入字符串插入 VARCHAR 列
MLOG_4BYTES写入 4 字节整数更新 INT 列
MLOG_REC_INSERT插入完整记录INSERT 新行
MLOG_REC_DELETE_MARK标记删除DELETE 操作

💡为什么分类型
减少日志体积:仅记录变更部分,而非整个页。


四、生成 Redo 的详细步骤(以 UPDATE 为例)

假设执行:

UPDATEproductsSETprice=100WHEREid=1000;
步骤 1:定位数据页
  • 通过聚簇索引(主键 id)找到页 P1
  • 若有二级索引(如idx_price),找到页 P2
步骤 2:修改 Buffer Pool
  • P1 页
    • 原记录标记为“已删除”
    • 插入新记录(price=100)
  • P2 页(若 price 变更):
    • 删除旧索引项(price=50)
    • 插入新索引项(price=100)
步骤 3:生成 Redo 记录
  1. 聚簇索引 Redo
    • MLOG_REC_DELETE_MARK:标记原记录删除
    • MLOG_REC_INSERT:插入新记录
  2. 二级索引 Redo(若 price 变更):
    • MLOG_REC_DELETE:删除旧索引项
    • MLOG_REC_INSERT:插入新索引项
  3. Undo Log Redo
    • MLOG_WRITE_STRING:写入旧值(price=50)到 Undo 页
步骤 4:写入 Redo Log Buffer
  • 所有 Redo 记录追加到内存缓冲区
  • 不立即刷盘(除非 COMMIT 或缓冲区满)

五、Redo 生成的性能影响

1.CPU 开销
  • 序列化 Redo 记录:需构造二进制日志
  • 校验和计算:每条记录含 CRC32 校验
2.I/O 开销
  • Redo Log 写入
    • 顺序 I/O(高效)
    • fsync是昂贵操作(尤其 HDD)
  • Double Write
    脏页刷盘时额外写双写区 → 2x I/O
3.内存开销
  • Redo Log Buffer
    大事务可能填满缓冲区 → 触发提前刷盘
  • Undo Log
    长事务积累大量 Undo → 占用 Buffer Pool

📊实测数据

  • 纯内存操作(Buffer Pool 命中):Redo 生成占 CPU 10–20%
  • 磁盘 I/O 密集:Redofsync成为主要瓶颈

六、优化 Redo 生成的策略

1.减少 Redo 量
  • 删除无用索引:每个索引 = 额外 Redo
  • 避免大字段更新:TEXT/BLOB 更新生成大量 Redo
  • 批量操作
    -- 优于 1000 条单条 UPDATEUPDATEproductsSETprice=price*1.1WHEREcategory='A';
2.调整 Redo 配置
# 增大日志文件(减少 checkpoint) innodb_log_file_size = 2G # 增大缓冲区(减少提前刷盘) innodb_log_buffer_size = 64M # 组提交优化(MySQL 5.7+) innodb_flush_log_at_trx_commit = 1 # 安全 # innodb_flush_log_at_timeout = 1 # 后台刷盘间隔
3.硬件加速
  • NVMe SSD:降低fsync延迟
  • Battery-Backed Write Cache (BBWC)
    RAID 卡缓存fsync,提升吞吐

七、监控 Redo 生成

1.关键指标
-- Redo 日志生成速率SHOWGLOBALSTATUSLIKE'Innodb_os_log_written';-- 日志等待次数(缓冲区不足)SHOWGLOBALSTATUSLIKE'Innodb_log_waits';
2.解析 Redo 内容(高级)
  • 使用 mysqlbinlog(仅限 binlog,非 Redo)
  • InnoDB Recovery 工具
    innodb_ruby可解析.ibd和 Redo 文件(需停机)

八、总结:Redo 生成心法

  • Redo 是物理变更的精确录像,与 SQL 语义无关。
  • 每次 DML = 多条 Redo 记录(聚簇索引 + 二级索引 + Undo)。
  • 性能瓶颈常在fsync,而非 Redo 生成本身。
  • 优化核心
    减少索引数量 + 批量操作 + 高速存储

💡终极原则
“Redo 不是开销,而是可靠性的保险费——
付多少,取决于你对数据安全的重视程度。”

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询