专栏文章
专栏文章
MySQL 系列
1. MySQL 系列 #01:MySQL 简介 2. MySQL 系列 #02:MySQL 数据类型与 Java 类型映射 3. MySQL 系列 #03:MySQL 基础架构与执行流程 4. MySQL 系列 #04:MySQL InnoDB 日志系统 5. MySQL 系列 #05:MySQL 事务与 MVCC 6. MySQL 系列 #06:MySQL 索引原理与优化 7. MySQL 系列 #07:MySQL 锁机制 8. MySQL 系列 #08:MySQL 性能问题排查 9. MySQL 系列 #09:MySQL 主备复制与高可用 10. MySQL 系列 #10:MySQL 实战技巧与常见陷阱 11. MySQL 系列 #11:MySQL 数据库设计规范 12. MySQL 系列 #12:MySQL SQL 函数与查询技巧 13. MySQL 系列 #13:MySQL InnoDB Buffer Pool 原理 14. MySQL 系列 #14:MySQL 排序与聚合原理

MySQL 系列 #04:MySQL InnoDB 日志系统

发布于 2026-05-26 10:33 👁 11 次阅读
#mysql#innodb#redo-log#binlog#wal#crash-safe

InnoDB 用 WAL(Write-Ahead Logging)机制实现高性能写入和 crash-safe 能力,核心是 redo log(物理日志)和 binlog(逻辑日志)的协作,两者通过两阶段提交保持一致。


目录

章节 说明
WAL 机制 先写日志再写磁盘,为什么能提升性能
redo log InnoDB 专属,保障 crash-safe
binlog Server 层归档日志,用于复制和恢复
redo log vs binlog 三个关键区别
两阶段提交 为什么必须两阶段
关键参数 生产环境推荐配置
数据恢复流程 利用 binlog 恢复到任意时间点

WAL 机制

WAL = Write-Ahead Logging:先写日志,再写磁盘。

掌柜的粉板(内存 + redo log) vs 账本(磁盘数据文件)

写粉板(快)→ 等空闲时再更新账本(慢但不阻塞业务)

为什么能提升性能?


redo log

是什么

环形结构

redo log ring

redo log 满了会怎样

redo log 写满时,系统停止所有更新操作,强制把 checkpoint 往前推(将对应脏页刷盘),腾出空间。这就是 MySQL 偶尔"抖一下"的原因之一。

MySQL 8.0.30+ 的新文件架构

8.0.30 起 redo log 文件机制做了重大改变:

8.0.30 以前 8.0.30+
文件位置 数据目录根下(ib_logfile0ib_logfile1 #innodb_redo/ 子目录
文件数量 默认 2 个 32 个(16 活跃 + 16 spare _tmp
容量配置 innodb_log_files_in_group × innodb_log_file_size innodb_redo_log_capacity(默认 100MB)
在线调整 ❌ 需重启 SET GLOBAL innodb_redo_log_capacity=...

为什么用 32 个小文件而不是 2 个大文件?

官方原文(Frederic Descamps,MySQL 官方博客,2022-12-24,经 InnoDB 团队 Kuba Lopuszanski 审阅):

"InnoDB tries to maintain approximately 32 files here, so that it doesn't need to wait long before one of them becomes no longer needed as it would if you had just 2 big files. This way it can reclaim them one by one when you want to resize them."

核心动机是回收粒度更细:2 个大文件必须等整个文件都不再需要才能释放,32 个小文件可以逐个回收,resize 时等待时间大幅缩短。

_tmp 文件是预备(spare)文件,等待被激活使用;活跃文件用完后直接从 spare 中补充,无需临时分配磁盘空间。

⚠️ undersized redo log 会导致性能问题(write_pos 频繁追上 checkpoint);oversized 则增加 crash recovery 和 shutdown 耗时。建议在业务高峰期实测后设置合适容量。


binlog

是什么

两种格式

格式 内容 特点
statement 原始 SQL 语句 日志小,但某些语句(含函数)可能主从不一致
row 每行数据的变化 日志大,但主从一致性最好,推荐生产使用
mixed 自动切换 折中方案

redo log vs binlog

mysql innodb logs

为什么 InnoDB 要有自己的 redo log? MySQL 最早只有 MyISAM,没有 crash-safe 能力。InnoDB 作为插件引入后,无法依赖 binlog(binlog 不支持 crash-safe),因此自己实现了 redo log。


两阶段提交

mysql write flow

为什么必须两阶段

如果不用两阶段提交,会出现数据不一致:

场景 问题
先写 redo log,再写 binlog,中间 crash redo log 有记录,数据恢复后 c=1;但 binlog 没有,用 binlog 恢复的临时库 c=0,主从不一致
先写 binlog,再写 redo log,中间 crash binlog 有记录,用它恢复的库 c=1;但 redo log 没有,crash 恢复后 c=0,主从不一致

本质:两阶段提交让 redo log 和 binlog 形成逻辑上的原子操作,要么都有要么都没有。


关键参数

-- 查看 redo log 刷盘策略(建议设为 1)
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';

-- 查看 binlog 刷盘策略(建议设为 1)
SHOW VARIABLES LIKE 'sync_binlog';
参数 含义
innodb_flush_log_at_trx_commit 1(推荐) 每次事务提交都将 redo log 持久化到磁盘
innodb_flush_log_at_trx_commit 2 每秒一次刷盘,性能更好但可能丢 1 秒数据
sync_binlog 1(推荐) 每次事务提交都将 binlog 持久化到磁盘
sync_binlog 0 由 OS 决定刷盘时机,性能好但可能丢数据

生产环境强烈建议两个参数都设为 1,保证 MySQL 异常重启后数据不丢失。


数据恢复流程

恢复到任意时间点

前提:

  1. 定期全量备份(如每天凌晨)
  2. 保留全量备份时间点之后的所有 binlog

恢复步骤:

  1. 找到最近的全量备份,恢复到临时库
  2. 从备份时间点开始,依次重放 binlog
  3. 重放到目标时刻(如误删前 1 秒)
  4. 将数据从临时库导回线上库

全量备份周期的选择

备份周期 优点 缺点
每天备份 RTO 短(最多应用 1 天 binlog) 存储成本高
每周备份 存储成本低 RTO 长(最坏需应用 1 周 binlog)

RTO(Recovery Time Objective):数据恢复所需的最长时间,是衡量备份策略的核心指标。


参考资料

  • 《MySQL 实战 45 讲》— 第 02 讲:日志系统:一条 SQL 更新语句是如何执行的?
  • 《MySQL 实战 45 讲》— 第 23 讲:MySQL 是怎么保证数据不丢的?
  • InnoDB Redo Log
← 返回列表

评论 (0)

暂无评论,来留下第一条吧。

发表评论