MySQL redo log、undo log、binlog之间的区别及联系
ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花
要理解 MySQL 中 redo log、undo log、binlog 的区别与联系,首先要明确它们的设计目标完全不同——redo log 保障崩溃恢复,undo log 保障事务回滚,binlog 保障数据备份与主从同步。三者协同工作,共同支撑 MySQL 的事务一致性、数据可靠性和高可用性,下面从定义、作用、核心特性、区别及联系五个维度,由浅入深详细讲解。
一、三者核心概念与区别(核心重点)
三者的核心差异集中在「所属存储引擎」「设计目标」「数据范围」「写入时机」等方面,先通过分点详细拆解,再用表格总结。
1. Redo Log(重做日志)
定位:InnoDB 存储引擎独有的日志,属于「物理日志」,记录的是「数据页的物理修改」(比如某数据页的某个偏移量的值修改为多少),与具体的 SQL 语句无关。
核心作用:保障 MySQL 崩溃恢复(Crash Recovery),解决「事务已提交但数据未写入磁盘」的问题,避免数据丢失。
举个例子:执行 update user set age=20 where id=1,redo log 不会记录这条 SQL,而是记录「id=1 所在的数据页,偏移量 X 的值从 18 改为 20」。即使 MySQL 崩溃,重启后会读取 redo log,将未写入磁盘的物理修改重新执行,确保已提交的事务不会丢失——这就是 InnoDB 「事务持久性」的核心保障。
核心特性:
- 循环写入:redo log 有固定大小(如 4 个文件,每个 1GB),写满后会覆盖旧日志(前提是旧日志对应的物理修改已写入磁盘);
- 写入时机:事务执行过程中,会先将修改写入 redo log buffer(内存),事务提交时,通过 fsync 刷到磁盘(可通过innodb_flush_log_at_trx_commit 配置刷盘策略);
- 仅 InnoDB 独有:MyISAM 存储引擎没有 redo log,因此不支持崩溃恢复和事务。
2. Undo Log(回滚日志)
定位:同样是 InnoDB 独有的日志,属于「逻辑日志」,记录的是「事务执行前的原始数据」(或原始操作的逆操作),与 SQL 语句的逻辑对应。
核心作用:保障事务的「原子性」,支持事务回滚(ROLLBACK),同时配合 MVCC(多版本并发控制)实现读取已提交(RC)、可重复读(RR)等隔离级别。
举个例子:执行 update user set age=20 where id=1(原 age=18),undo log 会记录「id=1 的 age 从 20 改回 18」的逆操作;如果事务执行失败或主动回滚,MySQL 会通过 undo log 执行逆操作,将数据恢复到事务开始前的状态。
核心特性:
- 可回滚性:每个事务都会生成对应的 undo log,事务回滚时,依次执行 undo log 中的逆操作;
- 支持 MVCC:undo log 会保留数据的历史版本,当其他事务读取数据时,若数据被当前事务修改,可通过 undo log 读取历史版本,避免脏读、不可重复读;
- 回收机制:undo log 会在事务提交后,由 InnoDB 的 purge 线程异步回收(前提是没有其他事务需要读取该历史版本)。
3. Binlog(二进制日志)
定位:MySQL 服务器层(不是存储引擎层)的日志,属于「逻辑日志」,记录的是「所有修改数据的 SQL 语句(或其逻辑等价形式)」,与存储引擎无关。
核心作用:用于数据备份、主从复制,解决「数据备份恢复」和「集群数据同步」的问题。
举个例子:执行 update user set age=20 where id=1,binlog 会记录这条 SQL 语句(或其逻辑编码);主库将 binlog 发送给从库,从库执行相同的 SQL,实现主从数据一致;备份时,可通过 binlog 恢复指定时间点的数据。
核心特性:
- 追加写入:binlog 是按时间顺序追加写入的,不会覆盖旧日志,可通过日志轮转(如按大小、按时间)管理;
- 与存储引擎无关:无论使用 InnoDB、MyISAM 还是其他存储引擎,只要执行修改数据的操作,都会记录 binlog;
- 三种格式:STATEMENT(记录 SQL 语句)、ROW(记录行的修改前后状态,推荐)、MIXED(混合前两种格式);
- 写入时机:事务提交时,将事务中的所有修改操作一次性写入 binlog(可通过 sync_binlog 配置刷盘策略)。
4. 三者核心区别总结表
所属层级 | InnoDB 存储引擎层 | InnoDB 存储引擎层 | MySQL 服务器层 |
日志类型 | 物理日志(数据页修改) | 逻辑日志(逆操作/历史数据) | 逻辑日志(SQL/行修改) |
核心作用 | 崩溃恢复,保障持久性 | 事务回滚,支撑 MVCC | 备份恢复、主从复制 |
写入方式 | 循环写入(固定大小) | 追加写入,异步回收 | 追加写入(可轮转) |
存储引擎支持 | 仅 InnoDB | 仅 InnoDB | 所有存储引擎 |
与事务的关系 | 事务提交时刷盘,保障提交后不丢失 | 事务执行时生成,回滚时使用 | 事务提交时写入,记录已提交的修改 |
二、三者的内在联系(协同工作机制)
redo log、undo log、binlog 并非独立工作,而是协同支撑 MySQL 的事务和高可用,核心协同场景有 3 个:事务执行与提交、崩溃恢复、主从复制。
1. 事务执行与提交的协同流程(核心)
以一个更新事务为例,三者的协同步骤如下(简化版):
- 事务开始,执行 update 语句,InnoDB 先读取数据页到内存,修改内存中的数据;
- 同时,InnoDB 生成 undo log(记录逆操作,用于回滚)和 redo log(记录物理修改,用于崩溃恢复),写入各自的内存缓冲区;同时,MySQL 服务器层会将该修改操作写入 binlog cache(binlog 的内存缓冲区);
- 事务提交时,执行「两阶段提交」(保障 redo log 和 binlog 一致性):第一阶段:将 redo log 标记为「准备状态」,并刷盘(确保 redo log 已持久化);第二阶段:将 binlog 写入并刷盘,然后将 redo log 标记为「提交状态」,完成事务提交;
- 事务提交后,undo log 由 purge 线程异步回收,redo log 后续会被覆盖(当对应数据页已写入磁盘)。
关键说明:两阶段提交的目的是避免「redo log 提交但 binlog 未写入」或「binlog 写入但 redo log 未提交」的情况,确保主从复制时数据一致(从库依赖 binlog,主库崩溃恢复依赖 redo log)。
2. 崩溃恢复时的协同
当 MySQL 崩溃后,重启时会执行崩溃恢复,此时 redo log 和 undo log 协同工作:
- 第一步:读取 redo log,将所有已标记「准备状态」或「提交状态」的物理修改,重新应用到数据页(恢复已提交的事务,保障持久性);
- 第二步:读取 undo log,将未提交的事务(redo log 中未标记提交的)执行回滚操作(保障原子性);
- 此时 binlog 不参与崩溃恢复(binlog 仅用于备份和主从,崩溃恢复依赖 InnoDB 自身的 redo/undo log)。
3. 主从复制时的协同
主从复制的核心是 binlog,但 redo log 间接保障了 binlog 的可靠性:
- 主库:事务提交时,通过两阶段提交确保 redo log 和 binlog 同步(binlog 只记录已提交的事务);
- 从库:通过 IO 线程读取主库的 binlog,写入自身的 relay log(中继日志);
- 从库 SQL 线程:读取 relay log,执行其中的 SQL 语句,实现数据同步;
- 若主库崩溃,重启后通过 redo log 恢复数据,确保 binlog 中的内容都是已提交的有效数据,避免从库同步错误数据。
三、总结
三者的核心定位可概括为:
- undo log:负责事务回滚和 MVCC,保障原子性;
- redo log:负责崩溃恢复,保障持久性;
- binlog:负责数据备份和主从复制,保障高可用。
三者协同,既保障了单实例 MySQL 的事务一致性(ACID),又支撑了集群的高可用(主从复制)和数据可靠性(备份恢复),是 MySQL 核心架构中不可或缺的组成部分。
ps:如果这篇帖子对于还在找工作和找实习的你有所帮助,可以关注我,给本贴点赞、评论、收藏并订阅专栏;同时不要吝啬您的花花
MySQL 日志专栏:带你慢览数据库运行轨迹,解析错误日志、查询日志、二进制日志核心价值,排查死锁、定位执行瓶颈,掌握日志备份恢复实操,轻松保障数据安全稳定运行。
查看7道真题和解析