目录
正在加载目录…
专栏文章
专栏文章
MySQL 系列
1. MySQL:核心概念、架构与使用场景 2. MySQL 数据类型与 Java 类型映射 3. MySQL 基础架构与执行流程 4. MySQL InnoDB 日志系统 5. MySQL 事务与 MVCC 6. MySQL 索引原理与优化 7. MySQL 锁机制 8. MySQL 性能问题排查 9. MySQL 主备复制与高可用 10. MySQL 实战技巧与常见陷阱 11. MySQL 数据库设计规范 12. MySQL SQL 函数与查询技巧 13. MySQL InnoDB Buffer Pool 原理 14. MySQL 排序与聚合原理

MySQL InnoDB 日志系统

发布于 2026-05-26 10:33 · 最后编辑于 2026-07-31 15:52 · 字数 2,555 👁 82 次阅读

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

目录

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

WAL 机制

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

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

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

为什么能提升性能?

  • 直接更新磁盘:随机 I/O,需要先找到记录位置再修改
  • WAL 写日志:顺序 I/O,直接追加写,速度快 10 倍以上

redo log

是什么

  • InnoDB 引擎专属的物理日志,记录"在某个数据页上做了什么修改"
  • 固定大小、循环写(不是追加写)
  • 保障 crash-safe:即使数据库异常重启,已提交的事务不会丢失

环形结构

redo log ring

  • write pos:当前写入位置,一直往后推进,到末尾回到开头
  • checkpoint:已经刷到磁盘的位置,往后推进代表擦除可复用空间
  • write pos 追上 checkpoint → redo log 写满 → 必须先刷脏页,才能继续写

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_sizeinnodb_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

是什么

  • MySQL Server 层实现的逻辑日志,所有存储引擎都可以使用
  • 记录"这个语句的原始逻辑",比如"给 ID=2 这一行的 c 字段加 1"
  • 追加写,不会覆盖历史日志,文件写满后切换到下一个文件

两种格式

格式内容特点
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,中间 crashredo log 有记录,数据恢复后 c=1;但 binlog 没有,用 binlog 恢复的临时库 c=0,主从不一致
先写 binlog,再写 redo log,中间 crashbinlog 有记录,用它恢复的库 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_commit1(推荐)每次事务提交都将 redo log 持久化到磁盘
innodb_flush_log_at_trx_commit2每秒一次刷盘,性能更好但可能丢 1 秒数据
sync_binlog1(推荐)每次事务提交都将 binlog 持久化到磁盘
sync_binlog0由 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)

暂无评论,来留下第一条吧。
登录注册 后才能发表评论