mysql中三大日志文件的写入/刷盘时机

在 MySQL(InnoDB)事务执行过程中,Binlog、Redo Log、Undo Log 的写入与刷盘时机紧密配合,共同保障 ACID 特性主从一致性 。它们的协作核心是 两阶段提交(2PC)

下面从 写入时机、刷盘时机、执行顺序 三个维度详细说明。

一、总体流程:两阶段提交(2PC)

为保证 崩溃恢复一致性主从复制一致性,MySQL 采用如下顺序:

💡 关键点:Redo Log 先 Prepare,Binlog 后写,最后 Redo Log Commit

二、各日志的写入与刷盘时机详解

|--------------|--------------------------------------------------------|----------------------------------------------------------------------------------------------------|----------------------------|
| 日志类型 | 写入时机 | 刷盘时机 | 是否强制落盘? |
| Undo Log | DML 执行时 (修改数据前) → 写入 Undo Page(在 Buffer Pool 中) | 异步刷盘 → 随 Undo Page 脏页由后台线程刷入磁盘 | ❌ (持久性由 Redo Log 保证) |
| Redo Log | DML 执行时 → 写入 Redo Log Buffer(内存) | 在事务 Prepare/Commit 阶段 → 由 innodb_flush_log_at_trx_commit 控制: • =1:每次 COMMIT 强制刷盘 • =0/2:异步刷盘 | ✅ 是(默认) (WAL 机制要求) |
| Binlog | 事务 COMMIT 时 → 先写入 Binlog Cache,再写入 Binlog File(内存) | 在事务 COMMIT 阶段 → 由 sync_binlog 控制: • =1:每次事务刷盘 • =0:由 OS 决定 • =N:每 N 个事务刷一次 | ⚠️ 可配置 (生产建议 =1) |


三、详细步骤分解(以 UPDATE + COMMIT 为例)

步骤 1:执行 DML(如 UPDATE t SET x=1 WHERE id=1

  • InnoDB:
    • 生成 Undo Log(记录旧值),存入 Undo Page(Buffer Pool)
    • 修改聚簇索引页(标记为脏页)
    • 生成 Redo Log (物理修改),写入 Redo Log Buffer

此时:Undo 和 Redo 都在内存,未刷盘


步骤 2:执行 COMMIT → 触发两阶段提交

▶ 阶段 1:Prepare 阶段(InnoDB)
  • InnoDB 将 Redo Log Buffer 中的日志 刷盘(含事务状态 = PREPARE)
  • 返回成功给 Server 层

此时 Redo Log 已持久化(若 innodb_flush_log_at_trx_commit=1**)**

▶ 阶段 2:Commit 阶段(Server 层)
  • Server 层将事务的 Binlog 写入 Binlog File(内存)
  • 根据 sync_binlog 决定是否 刷 Binlog 到磁盘
    • sync_binlog=1 → 立即 fsync() 刷盘
  • 然后通知 InnoDB 提交
▶ 阶段 3:InnoDB 最终提交
  • InnoDB 写一条 Redo Log(状态 = COMMIT)
  • 根据配置决定是否立即刷盘(通常可延迟)

至此,事务完成


四、崩溃恢复如何保证一致性?

MySQL 通过 Redo Log + Binlog 对账 实现:

|------------------------------------|--------------------|
| 场景 | 恢复动作 |
| 只有 Redo Log(PREPARE),无 Binlog | → 事务未完整提交 → 回滚 |
| Redo Log(PREPARE) + Binlog 都存在 | → 事务已完整提交 → 提交 |
| Redo Log(COMMIT)存在 | → 直接提交 |

💡 这确保了:Binlog 记录的事务 = InnoDB 实际提交的事务,主从不会数据不一致。


五、三者的角色总结

|--------------|--------|-------------|--------------|------------------|
| 日志 | 层级 | 作用 | 刷盘要求 | 生命周期 |
| Undo Log | InnoDB | 回滚 + MVCC | ❌ 异步 | 被 Purge 线程清理 |
| Redo Log | InnoDB | 崩溃恢复 + WAL | ✅ 默认强制 | Checkpoint 后循环覆盖 |
| Binlog | Server | 主从复制 + PITR | ⚠️ 可配置(建议强制) | 手动或自动过期删除 |


六、关键参数配置建议(生产环境)

复制代码
# Redo Log(安全第一)
innodb_flush_log_at_trx_commit = 1

# Binlog(保证主从一致)
sync_binlog = 1
binlog_format = ROW

# 自动清理
binlog_expire_logs_seconds = 604800  # 7天

⚠️ 如果 innodb_flush_log_at_trx_commit=1sync_binlog=0
可能主从不一致(主库崩溃时 Binlog 丢失,但从库可能已收到部分日志)。


七、常见误区澄清

|-----------------------------|----------------------------------------------|
| 误区 | 正确理解 |
| "Binlog 在 DML 时就写" | ❌ 只在 COMMIT 时 写(保证原子性) |
| "Undo Log 需要刷盘才能 COMMIT" | ❌ 不需要,靠 Redo Log 保证其可恢复 |
| "Redo Log 和 Binlog 谁先谁后无所谓" | ❌ 必须 Redo Prepare → Binlog → Redo Commit |
| "关闭 Binlog 能提升性能" | ✅ 能,但失去主从和 PITR 能力 |


总结:三者的写入与刷盘顺序

|---------------------|------------------------|------------------------------------------------|
| 阶段 | 操作 | 日志行为 |
| 1. DML 执行 | UPDATE/INSERT/DELETE | • Undo Log 写入内存 • Redo Log 写入内存(Redo Buffer) |
| 2. COMMIT 开始 | 两阶段提交启动 | --- |
| 3. Prepare | InnoDB 准备提交 | • Redo Log 刷盘(PREPARE) |
| 4. Write Binlog | Server 层记录 | • Binlog 写入文件(内存) • 按 sync_binlog 决定是否刷盘 |
| 5. Commit | InnoDB 最终提交 | • Redo Log 写 COMMIT(可延迟刷盘) |

💡 记住口诀
"改数据 → 记 undo → 生 redo → prepare redo → 写 binlog → commit redo"

这种精密协作,使得 MySQL 既能 高性能写入 ,又能 强一致、高可用、可恢复

相关推荐
luoluoal16 小时前
基于python大数据的电影市场预测分析(源码+文档)
python·mysql·django·毕业设计·源码
conca16 小时前
Java+MySQL时区难题-Date自动转换String差8小时
数据库·mysql
壹米饭16 小时前
MYSQL进阶:删除视图时视图被lock解决方案
后端·mysql
oMcLin17 小时前
如何在Ubuntu 22.04 LTS上配置并优化MySQL 8.0分区表,提高大规模数据集查询的效率与性能?
android·mysql·ubuntu
一路向北⁢18 小时前
MySQL 5.7 表分区使用说明(视频系统实战)
mysql·分区·分表·表分区
齐鲁大虾19 小时前
SQL Server 和 MySQL的区别
数据库·mysql
东方巴黎~Sunsiny20 小时前
mysql大表空间整理注意点
数据库·mysql
AllData公司负责人21 小时前
AllData数据中台-数据同步平台集成开源项目Seatunnel-Web,完成Mysql到Doris同步流程
数据库·mysql·开源
萧曵 丶1 天前
MySQL InnoDB 实现 MVCC 原理
数据库·mysql·mvcc
万粉变现经纪人1 天前
如何解决 pip install mysqlclient 报错 ‘mysql_config’ not found 问题
数据库·python·mysql·pycharm·bug·pandas·pip