MySQL InnoDB 三大日志详解:redo、binlog 与 undo log

七月
七月
发布时间:2026-10-15| 6人浏览过
原创

MySQL InnoDB 存储引擎依赖 redo log、binlog 和 undo log 三种日志机制来确保数据的持久性、原子性及集群一致性。其中 redo log 负责崩溃恢复,binlog 支持主备同步,两者结合两阶段提交协议保证数据一致;undo log 则用于事务回滚和多版本并发控制(MVCC)。

1. redo log

概述与工作原理

redo log(重做日志)是 InnoDB 存储引擎独有的物理日志,记录了“在某个数据页上做了什么修改”。它赋予 MySQL 崩溃恢复(Crash-Safe)能力,确保数据持久性。

在执行更新操作时,InnoDB 会将数据页从磁盘加载到内存缓冲池(Buffer Pool)中进行修改,同时将被修改的操作记录到 redo log buffer,随后刷盘至 redo log 文件。这一机制旨在减少随机磁盘 I/O,提升性能。

刷新策略

redo log 的刷盘时机由参数 innodb_flush_log_at_trx_commit 控制,直接影响数据安全性与性能:

  • 0:每秒一次将 redo log buffer 刷盘。数据库宕机可能丢失最近一秒的数据。
  • 1:(默认值)每次事务提交时强制执行 fsync 刷盘,确保无数据丢失,但性能开销最大。
  • 2:每次提交仅将内容写入系统页缓存(page cache),不强制刷盘。重启或断电可能导致部分数据丢失。

此外,后台线程会周期性监控,当 redo log buffer 使用量达到 innodb_log_buffer_size 一半时,也会主动触发刷盘。

不同配置的影响

当设置为 0 时,如果系统在两次刷盘间隔内发生宕机,可能导致最多一秒的写操作丢失。

设置为 1 是最安全的方式,只要事务返回成功,日志必定落盘。若在执行中异常,因未提交不会造成数据损失。

设置为 2 时,MySQL 进程崩溃无数据丢失(因为 OS 已接收),但如果服务器遭遇意外断电导致 page cache 丢失,可能会有数据损毁风险。

环形数组结构

硬盘上的 redo log 由一组固定大小的文件组成(默认为两个),采用环形数组(Ring Buffer)形式循环书写。当头写到末尾时,会回到开头继续覆盖旧日志,以此保证日志文件大小有限且连续高效。

2. binlog

概述

binlog 是 MySQL Server 层级的逻辑日志。相比于 redo log 的物理页修改,它记录的是语句的逻辑原始信息(例如:给 ID=2 的记录字段 c 加 1)。任何存储引擎发生的表数据更新都会产生 binlog。

它是数据备份、主从复制及高可用架构的核心依据,依靠 binlog 实现节点间的数据同步。

记录格式

通过 binlog_format 参数可以指定以下三种格式:

  • Statement:记录原始 SQL 语句。优点是空间占用小,缺点是某些包含不确定性函数(如 now())的语句在主从库执行时会导致结果不一致。
  • Row:记录每一行数据的具体变更细节。能完全保证数据的一致性,是目前推荐的生产环境格式,但会产生大量日志并消耗较多 IO。
  • Mixed:混合模式。MySQL 自动判断,对于普通语句采用 Statement,对于可能引起不一致的语句自动切换为 Row。

写入与刷盘流程

事务执行过程中,日志先被写入线程专属的 binlog cache。由于一个事务的日志不可分割,若缓存超过 binlog_cache_size 设定值,则会被临时存入磁盘 Swap 中。

刷盘行为由 sync_binlog 参数决定:

  • 0:事务提交只 write 进系统缓存,操作系统自由决定何时 fsync。性能最高,但机器故障易丢日志。
  • 1:每次事务提交立即 fsync 刷盘。安全性等同于 redo log = 1,IO 压力最大。
  • N (>1):累积 N 个事务后一次性 fsync。适用于存在 IO 瓶颈的场景,作为性能与安全的折中。

3. 两阶段提交 (Two-Phase Commit)

为何需要两阶段提交?

redo log 与 binlog 的写入时序不同:前者贯穿事务执行全程,后者仅在事务提交时写入。这种差异会导致两份日志逻辑不一致的风险。以一条更新语句为例,若写完 redo log 但未写完 binlog 就发生宕机:

  • 重启时,凭借 redo log 恢复会导致该次更新生效。
  • 利用 binlog 进行主从复制时,由于缺少记录,从库不会执行该更新。
  • 最终导致主库与从库数据不一致。

    解决方案原理

    InnoDB 采用两阶段提交方案解决上述矛盾。它将 redo log 的写入分为 prepare 和 commit 两个状态:

    1. Prepare 阶段:事务的所有修改写入 redo log,标记为 prepare 状态,此时尚未写入 binlog。
    2. Commit 阶段:将日志刷入 binlog,然后再次修改 redo log 标记为 commit 并完成刷盘。

    通过这种机制,即使中途发生异常,MySQL 启动恢复时也具备明确的判断逻辑:

    • 发现 prepare 且无 binlog:说明写入 binlog 前中断,判定为不完整事务,直接回滚。
    • 发现 prepare 但有 binlog:说明 binlog 已成功保存,判定为完整事务,直接提交。

    4. undo log

    功能与作用

    undo log(回滚日志)主要用于保证事务的原子性。

    • 事务回滚:当事务执行出错或需要手动回滚时,InnoDB 利用 undo log 中的历史信息撤销已经完成的修改。
    • 数据一致性(MVCC):在 Read View 的作用下,undo log 保存了多份历史数据版本,配合隐藏字段,让不同事务能看到各自隔离范围内的数据,从而实现非锁定读。

    5. 总结

    MySQL 的三大日志各司其职又紧密协作:redo log 确保崩溃后能恢复,保障了持久性;undo log 协助完成错误处理与多版本读取,保障了原子性与隔离性;binlog 则是集群同步的核心,保障一致性。了解这些日志的运行原理,有助于在数据库调优与故障排查时做出正确决策。

    以上就是关于 MySQL 三大日志(redo log、binlog 和 undo log)运行原理及两阶段提交的详细内容,更多关于 MySQL 数据库底层机制的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。