MySQL三大日志 binglog(历史档案) redolog(草稿本/记账本) undolog(后悔药)

MySQL 中的三大日志(binlogredo logundo log )是数据库能够实现 ACID 特性 (特别是原子性、持久性)以及主从复制数据恢复的关键。

为了让你条理清晰地理解,我们可以从作用、所属层级、记录内容这几个维度来拆解。

我们可以把它们比作:

  • binlog"历史档案"(记录所有发生过的事,用于归档和传给别人)。
  • redo log"草稿本/记账板"(防止突然断电,用于崩溃恢复)。
  • undo log"后悔药"(事务失败了要回滚,或者看过去的数据)。

一、 redo log(重做日志)------ 保证"持久性" (Durability)

1. 核心作用:Crash-safe(崩溃恢复)

MySQL 为了性能,更新数据时是先更新内存(Buffer Pool),然后异步刷到磁盘。如果内存更新了但还没刷盘时数据库宕机,数据就丢了。
redo log 的作用就是:只要事务提交成功,即使数据库立刻宕机,重启后也能通过 redo log 找回数据。 这就是 WAL 技术(Write-Ahead Logging,先写日志,再写磁盘)。

2. 所属层级

  • 特属于 InnoDB 存储引擎

3. 记录内容(物理日志)

  • 它记录的是物理修改。比如:"在第 X 号表空间的第 Y 号数据页上,偏移量 Z 处做了什么修改"。

4. 写入方式(循环写)

  • redo log 的文件大小是固定的(例如一组 4 个文件,每个 1GB)。
  • 它像一个圆环,写满了一个就回到开头覆盖写。
  • write pos:当前记录的位置。
  • checkpoint:当前已经擦除(同步到磁盘)的位置。
  • 如果 write pos 追上了 checkpoint,说明空间满了,必须停下来把脏页刷到磁盘,腾出空间。

二、 undo log(回滚日志)------ 保证"原子性" (Atomicity)

1. 核心作用:事务回滚 & MVCC

  • 事务回滚 :如果一个事务执行到一半出了错,或者用户执行了 ROLLBACK,MySQL 需要把数据恢复到事务开始前的样子。
  • MVCC(多版本并发控制):当读取记录时,若该记录被其他事务占用,可以通过 undo log 读取之前的版本(快照读),实现非阻塞读。

2. 所属层级

  • 特属于 InnoDB 存储引擎

3. 记录内容(逻辑日志)

  • 它记录的是逻辑相反操作
    • 你执行 INSERT,它记录一条 DELETE
    • 你执行 DELETE,它记录一条 INSERT
    • 你执行 UPDATE,它记录一条反向的 UPDATE

4. 生命周期

  • 事务开始前产生,事务提交后并不会立刻删除(因为 MVCC 可能还需要用),而是放入待删除列表,由 Purge 线程清理。

三、 binlog(归档日志)------ 用于"复制"和"恢复"

1. 核心作用:主从复制 & 数据恢复

  • 主从复制:Master 端把 binlog 发送给 Slave 端,Slave 重放这些日志,从而保证主从数据一致。
  • 数据恢复:如果你误删库了,可以通过 binlog 把数据库恢复到某个时间点(PITR - Point In Time Recovery)。

2. 所属层级

  • 属于 MySQL Server 层(所有存储引擎共用,MyISAM 也有)。

3. 记录内容(逻辑日志)

  • 记录的是 SQL 语句的原始逻辑
  • 格式有三种:
    • Statement:记录 SQL 语句原文(可能导致主从不一致,如使用了 now() 函数)。
    • Row:记录每一行具体被修改成什么样(最安全,但日志量大)。
    • Mixed:混合模式。

4. 写入方式(追加写)

  • 追加写(Append-only)。文件写到一定大小后会切换到下一个文件,不会覆盖以前的日志。

四、 重点对比:redo log vs binlog

这是面试中最常问的区别,必须清晰区分:

|----------|-----------------------|-----------------------|
| 特性 | redo log (重做日志) | binlog (归档日志) |
| 归属 | InnoDB 引擎特有 | MySQL Server 层 (引擎通用) |
| 内容类型 | 物理日志 (数据页改了啥) | 逻辑日志 (SQL语句/行变化) |
| 主要作用 | 崩溃恢复 (Crash-safe) | 主从复制历史恢复 |
| 写入方式 | 循环写 (空间固定,会覆盖) | 追加写 (文件切换,不覆盖) |
| 持久性 | 事务提交必须写 (保证不丢) | 事务提交必须写 (保证同步) |


五、 进阶:它们是如何配合的?(两阶段提交)

当我们要更新一条数据时,redo log 和 binlog 是如何保证一致性的?这就涉及到了两阶段提交 (Two-Phase Commit, 2PC)

假设执行 UPDATE user SET name='A' WHERE id=1;

  1. 执行阶段:InnoDB 将内存中的数据更新。
  2. redo log prepare(预提交) :InnoDB 写 redo log,标记状态为 prepare
  3. 写 binlog:Server 层写入 binlog 并持久化到磁盘。
  4. redo log commit(提交) :InnoDB 将 redo log 标记为 commit

为什么要这么麻烦?

是为了防止由宕机引发的 "日志不一致"

  • 如果先写 redo log,再写 binlog
    • redo log 写完,机器断电,binlog 没写。
    • 重启后,redo log 恢复了数据(主库有数据),但 binlog 没记录(从库没数据)。主从不一致
  • 如果先写 binlog,再写 redo log
    • binlog 写完,机器断电,redo log 没写。
    • 重启后,主库数据丢了(redo log 没刷盘),但从库通过 binlog 同步了该数据。主从不一致

两阶段提交保证了:要么两个日志都成功,要么都失败,确保主库数据和从库(以及历史归档)的一致性。

总结

  • undo log:原子性。如果我要反悔(回滚),或者想看旧数据(MVCC),找它。
  • redo log:持久性。如果服务器挂了,重启时要恢复内存里没来得及刷盘的数据,找它。
  • binlog:归档与复制。如果我要把数据同步给从库,或者恢复到上个月的状态,找它。
相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
l1t8 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划8 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿9 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar1239 小时前
C++使用format
开发语言·c++·算法
探路者继续奋斗9 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd
码说AI9 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化
星空下的月光影子10 小时前
易语言开发从入门到精通:补充篇·网络爬虫与自动化采集分析系统深度实战·HTTP/HTTPS请求·HTML/JSON解析·反爬策略·电商价格监控·新闻资讯采集
开发语言
老约家的可汗10 小时前
初识C++
开发语言·c++