UndoLog实现事务原子性与多版本并发控制,RedoLog通过循环写入保证崩溃恢复,Binlog以二进制形式记录变更用于主从复制和数据恢复。RedoLog为InnoDB物理日志,Binlog为Server层逻辑日志,两者写入方式与用途不同。
首先来看 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 正是为实现事务原子性而设计的。在事务处理过程中,如果发生错误,或用户主动执行 ROLLBACK,MySQL 可借助 Undo Log 中的备份数据,将数据库恢复到事务开始前的状态。
实现多版本并发控制(MVCC)
在 MySQL InnoDB 引擎中,Undo Log 也是实现多版本并发控制(MVCC)的关键。当事务尚未提交时,Undo Log 保存了数据未提交前的旧版本。这些数据可作为旧版本的快照,供其他并发事务进行快照读操作。
来看一个具体示例:

图中展示了如下场景:事务 A 手动开启事务,执行更新操作。它先将待更新的数据备份到 Undo Buffer 中。此时,事务 B 也手动开启事务,执行查询操作。事务 B 会读取 Undo Buffer 中的日志数据并返回,这就是一次典型的快照读操作。
Redo Log 与 Binlog 是 MySQL 日志体系中两个至关重要的组成部分,但它们的职责和特性差异十分显著。
从名称可知,它用于“重做”,主要作用是在数据库意外崩溃时恢复数据。
Redo Log 随着事务操作的执行而实时生成。在事务提交时,产生的 Redo Log 会先写入一个名为 Log Buffer 的内存区域,而非立即刷到磁盘文件。直到事务的脏页真正写入磁盘后,Redo Log 的使命才算完成,其占用的空间即可被重用(覆盖写入)。

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

观察下图可以更清晰地理解:
Write Pos 与 Check Point 之间的空白区域,就是可供记录新操作的空间。如果 Write Pos 追上了 Check Point,说明空间已写满,此时不能再继续执行新的更新操作,需要停止并擦除一些旧记录,将 Check Point 向前推进。
每个 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:
Innodb_flush_log_at_trx_commit =1:
Innodb_flush_log_at_trx_commit =2:
通常建议取值 2。这样 MySQL 进程崩溃不会丢失数据,只有整个操作系统崩溃时,才会损失 1 秒的事务提交数据。
流程如图所示:

Redo Log 是 InnoDB 引擎特有的日志,而 MySQL Server 自身也有一套日志,即 Binary Log(二进制日志),通常称为 Binlog。
Binlog 以事件形式记录所有数据库表结构的变更和表数据的修改操作,同时包含语句执行所消耗的时间。但需注意,它不会记录 Select 和 Show 这类操作。开启 Binlog 主要服务于两个场景:
Binlog 的文件名默认格式为“主机名_binlog-序列号”,例如 oak_binlog-000001,也可在配置文件中自定义。其记录模式有三种:STATEMENT、ROW 和 MIXED。具体含义如下:
ROW(row-based replication,简称 RBR):日志中记录每一行数据被修改的具体情况,从库针对相同数据执行修改。
STATEMENT(statement-based replication,简称 SBR):每条修改数据的 SQL 语句都被记录到主库的 Binlog 中。从库复制时,SQL 进程解析这些 SQL,并在从库上重新执行。本质上是 SQL 语句的复制。
MIXED(mixed-based replication,简称 MBR):混合模式。通常使用 STATEMENT 模式保存 Binlog,但对于 STATEMENT 模式无法正确复制的情况,自动切换为 ROW 模式。MySQL 会根据执行的 SQL 语句智能选择相应的写入模式。
MySQL 的 Binlog 文件中记录了数据库的各种修改操作,表示这些修改操作的数据结构称为 Log Event。不同的修改操作对应不同的 Log Event,常见的有 Query Event、Row Event、Xid Event 等。可以理解为,Binlog 文件的内容就是各种 Log Event 的集合。
以下为 Binlog 文件中 Log Event 的结构图:

事务在提交阶段,会将产生的 Log Event 写入外部 Binlog 文件。不同事务以串行方式写入,因此一个事务包含的 Log Event 信息在 Binlog 文件中连续存储,中间不会插入其他事务的 Log Event。
查看 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 能力。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述