首页 > 数据库 >MySQL InnoDB 三大日志文件实现详解

MySQL InnoDB 三大日志文件实现详解

来源:互联网 2026-07-10 08:38:12

UndoLog实现事务原子性与多版本并发控制,RedoLog通过循环写入保证崩溃恢复,Binlog以二进制形式记录变更用于主从复制和数据恢复。RedoLog为InnoDB物理日志,Binlog为Server层逻辑日志,两者写入方式与用途不同。

Undo Log

首先来看 Undo Log。从名称可知,它主要用于“撤销”或“取消”操作,目标是将数据回滚到某个指定状态。这是一种逻辑日志,记录的是数据变化的过程。在 InnoDB 存储引擎中,Undo Log 采用段(segment)的方式进行管理和记录。具体而言,InnoDB 的数据文件中包含一个名为回滚段(rollback segment)的结构,其内部拥有 1024 个 Undo Log 段。通过参数 innodb_undo 可以控制其行为。

show variables like '%innodb_undo%';

Undo Log 在事务开始之前就已生成。值得注意的是,当事务提交时,它并不会被立即删除。InnoDB 会将此事务对应的 Undo Log 先放入一个删除列表,随后由后台的 purge thread 线程逐步回收处理。例如,执行 delete 操作时,Undo Log 会记录一个 insert 操作;执行 update 时,则会记录一个相反的 update 操作。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

Undo Log 的作用

实现事务的原子性

可以说,Undo Log 正是为实现事务原子性而设计的。在事务处理过程中,如果发生错误,或用户主动执行 ROLLBACK,MySQL 可借助 Undo Log 中的备份数据,将数据库恢复到事务开始前的状态。

实现多版本并发控制(MVCC)

在 MySQL InnoDB 引擎中,Undo Log 也是实现多版本并发控制(MVCC)的关键。当事务尚未提交时,Undo Log 保存了数据未提交前的旧版本。这些数据可作为旧版本的快照,供其他并发事务进行快照读操作。

来看一个具体示例:

MySQL InnoDB 三大日志文件实现详解

图中展示了如下场景:事务 A 手动开启事务,执行更新操作。它先将待更新的数据备份到 Undo Buffer 中。此时,事务 B 也手动开启事务,执行查询操作。事务 B 会读取 Undo Buffer 中的日志数据并返回,这就是一次典型的快照读操作。

Redo Log 和 Binlog

Redo Log 与 Binlog 是 MySQL 日志体系中两个至关重要的组成部分,但它们的职责和特性差异十分显著。

Redo Log

从名称可知,它用于“重做”,主要作用是在数据库意外崩溃时恢复数据。

Redo Log 随着事务操作的执行而实时生成。在事务提交时,产生的 Redo Log 会先写入一个名为 Log Buffer 的内存区域,而非立即刷到磁盘文件。直到事务的脏页真正写入磁盘后,Redo Log 的使命才算完成,其占用的空间即可被重用(覆盖写入)。

Redo Log 的工作原理图

MySQL InnoDB 三大日志文件实现详解

Redo Log 写入机制

Redo Log 的文件采用循环写入方式。即写满最后一个文件后,回溯到第一个文件,从头开始覆盖写入。

MySQL InnoDB 三大日志文件实现详解

观察下图可以更清晰地理解:

  • Write Pos 表示当前记录的写入位置,它会一边写入一边向后移动,当写到最后一个文件的末尾后,回到 0 号文件的开头。
  • Check Point 表示当前要擦除的位置,同样向后移动并循环。在擦除记录前,必须先将该记录更新到数据文件中。

Write Pos 与 Check Point 之间的空白区域,就是可供记录新操作的空间。如果 Write Pos 追上了 Check Point,说明空间已写满,此时不能再继续执行新的更新操作,需要停止并擦除一些旧记录,将 Check Point 向前推进。

Redo Log 的相关配置

每个 InnoDB 引擎至少拥有一个重做日志文件组(Redo Log Group),每个文件组至少包含 2 个重做日志文件(Redo Log),默认为 ib_logfile0 和 ib_logfile1。关于 Redo Buffer 持久化到 Redo Log 的策略,可通过参数 Innodb_flush_log_at_trx_commit 进行设置:

Innodb_flush_log_at_trx_commit =0:

  • 表示每秒执行一次 Redo Buffer → OS Cache → flush cache to disk 的完整操作。该方式可能丢失 1 秒内的事务数据,因为后台的 Master 线程每隔 1 秒才执行一次。

Innodb_flush_log_at_trx_commit =1:

  • 每次事务提交时,立即执行 Redo Buffer → OS Cache → flush cache to disk。这是最安全的方式,但性能也最差。

Innodb_flush_log_at_trx_commit =2:

  • 每次事务提交时,仅执行 Redo Buffer → OS Cache。随后由后台的 Master 线程每隔 1 秒执行 OS Cache → flush cache to disk 的操作。

通常建议取值 2。这样 MySQL 进程崩溃不会丢失数据,只有整个操作系统崩溃时,才会损失 1 秒的事务提交数据。

流程如图所示:

MySQL InnoDB 三大日志文件实现详解

Binlog 日志

Binlog 记录模式

Redo Log 是 InnoDB 引擎特有的日志,而 MySQL Server 自身也有一套日志,即 Binary Log(二进制日志),通常称为 Binlog。

Binlog 以事件形式记录所有数据库表结构的变更和表数据的修改操作,同时包含语句执行所消耗的时间。但需注意,它不会记录 Select 和 Show 这类操作。开启 Binlog 主要服务于两个场景:

  • 主从复制:在主库上开启 Binlog,主库可将 Binlog 内容传给从库,从库接收后重放,从而保证主从数据一致。
  • 数据恢复:通过 mysqlbinlog 工具进行数据恢复。

Binlog 的文件名默认格式为“主机名_binlog-序列号”,例如 oak_binlog-000001,也可在配置文件中自定义。其记录模式有三种:STATEMENT、ROW 和 MIXED。具体含义如下:

ROW(row-based replication,简称 RBR):日志中记录每一行数据被修改的具体情况,从库针对相同数据执行修改。

  • 优点:清晰记录每个行数据的修改细节,能完全实现主从数据同步和数据恢复。
  • 缺点:批量操作时会产生大量日志,尤其 alter table 等操作容易导致日志暴涨。

STATEMENT(statement-based replication,简称 SBR):每条修改数据的 SQL 语句都被记录到主库的 Binlog 中。从库复制时,SQL 进程解析这些 SQL,并在从库上重新执行。本质上是 SQL 语句的复制。

  • 优点:日志量小,减少磁盘 IO,提升存储和恢复速度。
  • 缺点:某些情况下会导致主从数据不一致,例如使用了 last_insert_id()、now() 等函数。

MIXED(mixed-based replication,简称 MBR):混合模式。通常使用 STATEMENT 模式保存 Binlog,但对于 STATEMENT 模式无法正确复制的情况,自动切换为 ROW 模式。MySQL 会根据执行的 SQL 语句智能选择相应的写入模式。

Binlog 文件结构

MySQL 的 Binlog 文件中记录了数据库的各种修改操作,表示这些修改操作的数据结构称为 Log Event。不同的修改操作对应不同的 Log Event,常见的有 Query Event、Row Event、Xid Event 等。可以理解为,Binlog 文件的内容就是各种 Log Event 的集合。

以下为 Binlog 文件中 Log Event 的结构图:

MySQL InnoDB 三大日志文件实现详解

Binlog 写入机制

  • 首先,根据记录模式和操作类型触发 event 事件,生成相应的 Log Event(即事件触发执行机制)。
  • 然后,事务执行过程中产生的 Log Event 先写入缓冲区,每个事务线程拥有自己的缓冲区。Log Event 保存在一个名为 binlog_cache_mngr 的数据结构中,该结构包含两个缓冲区:stmt_cache 用于存放不支持事务的消息,trx_cache 用于存放支持事务的消息。

事务在提交阶段,会将产生的 Log Event 写入外部 Binlog 文件。不同事务以串行方式写入,因此一个事务包含的 Log Event 信息在 Binlog 文件中连续存储,中间不会插入其他事务的 Log Event。

Binlog 文件操作相关命令

查看 Binlog 状态

show variables like 'log_bin';

开启 Binlog 功能

set global log_bin=mysqllogbin;(注意:此处可能报错:ERROR 1238 (HY000): Variable 'log_bin' is a read only variable,此时需修改 my.cnf 或 my.ini 配置文件,在 [mysqld] 下增加 log_bin=mysql_bin_log,然后重启 MySQL 服务。)

#log-bin=ON
#log-bin-basename=mysqlbinlog
binlog-format=ROW
log-bin=mysqlbinlog

使用 show binlog events 命令

show binary logs;// 等价于 show master logs;
show master status;
show binlog events;
show binlog events in 'mysqlbinlog.000001';

使用 mysqlbinlog 命令

mysqlbinlog "文件名"
mysqlbinlog "文件名" > "test.sql"

使用 binlog 恢复数据

-- 指定时间恢复
mysqlbinlog --start-datetime="2020-0425 18:00:00" --stop-datetime="2020-04-26 00:00:00" mysqlbinlog.000002 | mysql -uroot -p1234
-- 按事件位置号恢复
mysqlbinlog --start-position=154 --stop-position=957 mysqlbinlog.000002 | mysql -uroot -p1234

通常,mysqldump 用于定期全量备份数据库,而 mysqlbinlog 用于增量备份和恢复操作。

删除 Binlog 文件

-- 删除指定文件
purge binary logs to 'mysqlbinlog.000001';
-- 删除指定时间之前的文件
purge binary logs before '2020-0428 00:00:00';
-- 清除所有文件
reset master;

也可以通过设置 expire_logs_days 参数自动清理。默认值为 0,表示未启用。若设置为 1,则表示 Binlog 文件超过 1 天自动删除。

最后,总结 Redo Log 和 Binlog 的区别:

Redo Log 是 InnoDB 引擎独有的,而 Binlog 是 MySQL Server 自带的,以二进制文件形式记录。

Redo Log 属于物理日志,记录的是数据页更新后的状态;Binlog 是逻辑日志,记录的是更新的过程。

Redo Log 采用循环写方式,日志空间大小固定;Binlog 是追加写入,写完一个文件继续写下一个,不会覆盖。

最关键的是,Redo Log 用于服务器异常宕机后事务数据的自动恢复;Binlog 主要用于主从复制和数据恢复。坦率地说,Binlog 本身不具备自动的 crash-safe 能力。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备2026025700号-3 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。