当前位置: 首页 > news >正文

数据库三大日志深度解析:Redo Log、Binlog、Undo Log 如何守护你的数据

📌 今日关键词:Redo Log、Binlog、Undo Log、WAL、两阶段提交、crash-safe

大家好,我是数据库小学妹👋

之前我们学过 MVCC,知道 Undo Log 可以实现数据的"时光回溯"。但很多同学问:“MySQL到底有几种日志?它们各自管什么事?为什么要有这么多日志而不是一个搞定?”

说实话,刚开始我也一头雾水——明明都是记录变更,为什么要搞 Redo Log、Binlog、Undo Log 三个概念?直到我真正理解了它们的分工,才发现这是数据库设计中最精妙的部分之一。

今天用一条 UPDATE 语句走一遍流程,把这三个东西的关系理清楚。


一、三种日志分工

日志类型归属作用删除策略
Redo LogInnoDB 引擎崩溃恢复(crash-safe)循环覆盖
Undo LogInnoDB 引擎事务回滚 + MVCC事务结束后可被 purge
BinlogServer 层主从复制 + 数据恢复手动清理或按策略归档

记住一句话:Redo Log 负责"死了能活",Undo Log 负责"错了能悔",Binlog 负责"丢了能找"


二、Redo Log —— 宕机后靠它恢复数据

什么是 Redo Log?

想象一下这个场景:你刚给某个用户充值了 100 元,UPDATE 语句执行到一半,服务器突然断电了。数据会怎样?

如果不做任何处理,这笔账就丢了——因为内存里的修改还没来得及刷到磁盘上。

Redo Log 的作用就是:即使宕机,已提交的事务也不会丢失。

Redo Log 的核心特点

1. 环形文件结构
redo log000001 → redo log000002 → ... → redo log000010 → (回到开头) redo log000001

Redo Log 是固定大小的环形文件组(默认总共 1GB),写到末尾就从头开始覆盖。这种设计保证了日志不会因为长期运行而撑爆磁盘。

2. 物理日志

Redo Log 记录的是"在某个数据页上做了什么修改",比如:

[LSN=100] 在 page_id=100 的 offset=4096 处写入 value=100 元

这种物理级别的记录让恢复速度非常快——直接按日志重放就行,不用重新解析 SQL。

3. WAL 技术(Write-Ahead Logging)

核心原则:任何修改必须先写 Redo Log,才能认为事务成功。

正常流程(有风险): 修改内存 buffer pool → 异步刷盘 → 告诉用户"成功了" ↑ 如果这里宕机,数据就丢了 WAL 流程(安全): 写 Redo Log 并刷盘 → 修改内存 buffer pool → 告诉用户"成功了" ↑ 即使宕机,重启后通过 Redo Log 能恢复

查看 Redo Log 配置

-- 查看 Redo Log 大小和数量SHOWVARIABLESLIKE'innodb_log_file_size';-- 单个文件 256MSHOWVARIABLESLIKE'innodb_log_files_in_group';-- 4 个文件,共 1GB-- 查看 checkpoint 位置(决定了能回收多少 log)SHOWENGINEINNODBSTATUS\G

三、Undo Log —— 回滚和版本链

Undo Log 我们之前学 MVCC 时提过,今天从更底层角度再拆解一遍。

Undo Log 的两个职责

职责 1:事务回滚

你执行了一个错误操作,比如:

BEGIN;UPDATEaccountsSETbalance=0WHEREuser_id=123;-- 哎呀手滑了!ROLLBACK;

数据库怎么知道你原来的余额是多少?靠的就是 Undo Log 里保存的"旧值"。

Undo Log 记录的格式类似这样:

[事务 A] 将 accounts 表中 user_id=123 的 balance 从 500 改为 0 ↓ 反向操作就是 [回滚] 将 accounts 表中 user_id=123 的 balance 从 0 改回 500
职责 2:MVCC 版本链

同一个表的同一行数据,不同事务看到的版本可能不一样:

时间线: T1: 事务 A 把 balance 从 100 改成 200(undo log 指向旧版本) T2: 事务 B 把 balance 从 200 改成 300(undo log 指向 T1 的版本) T3: 事务 C 查询,如果是 RC 级别看到 300,如果是 RR 级别且早于 T1 则看到 100

每一行数据的 undo log 连成一条"版本链",越新的数据在链表头部,越旧的在后面。

Undo Log vs Redo Log

特性Undo LogRedo Log
存储位置表空间内(系统表空间或独立 undo 表空间)独立的 redo log 文件
是否循环使用否,事务结束后被 purge 线程清理是,checkpoint 后可覆盖
记录内容逻辑日志(反向日志)物理日志(数据页修改)
主要用途回滚 + MVCC崩溃恢复

四、Binlog —— Server 层的日志文件

Binlog 是什么?

Binlog(Binary Log)是 MySQL Server 层的日志,所有引擎(InnoDB、MyISAM 等)都会产生。

它记录的是 SQL 语句的逻辑变更,比如:

# At 123456789 #260521 10:30:00 server id 1 end_log_pos 123456789 Query SET timestamp=1684658400; UPDATE accounts SET balance = 100 WHERE id = 1

Binlog 的三种格式

-- 查看当前 binlog 格式SHOWVARIABLESLIKE'binlog_format';
格式记录内容优点缺点
STATEMENT原始 SQL 语句体积小某些函数(如 NOW())主从不一致
ROW每行变更的前后镜像精确可靠DDL 或批量更新时体积大
MIXED混合模式,自动切换平衡两者逻辑复杂

生产环境推荐用 ROW 模式,虽然体积大点,但最安全。

Binlog 的独特价值

1. 数据恢复(Point-in-Time Recovery)

误删了一张表?可以通过 Binlog 恢复到任意时间点:

# 停止 MySQL# 恢复全量备份# 回放 Binlog 到删除前的时间点mysqlbinlog --stop-datetime="2026-05-21 10:29:59"binlog.000001|mysql-uroot-p
2. 主从复制

从库通过读取主库的 Binlog,保持数据同步——这是我们之前学主从复制时的基础。

Binlog 管理命令

-- 查看 Binlog 列表SHOWBINARYLOGS;-- 清空过期 Binlog(谨慎操作!)PURGEBINARYLOGS BEFORE'2026-05-01 00:00:00';-- 强制刷新 Binlog 到新文件FLUSH LOGS;-- 关闭/开启 Binlog(一般不用)SETGLOBALlog_bin=0;

五、一条 UPDATE 语句的执行流程

现在看执行一条 UPDATE 时,三个日志怎么协作:

UPDATEaccountsSETbalance=balance+100WHEREuser_id=1;

执行流程

┌─────────────────────────────────────────────────────────────┐ │ 1. 检查 Buffer Pool,找到对应的数据页 │ │ ↓ │ │ 2. 生成 Undo Log(记录旧值 balance=500) │ │ ↓ │ │ 3. 修改内存中的数据页(balance 变成 600) │ │ ↓ │ │ 4. 写 Redo Log(记录"page X 的 offset Y 修改为 600") │ │ ↓ │ │ 5. 写 Binlog(记录"UPDATE accounts...") │ │ ↓ │ │ 6. 两阶段提交:先准备(prepare),再提交(commit) │ │ ↓ │ │ 7. 返回给客户端:"Query OK, 1 row affected" │ └─────────────────────────────────────────────────────────────┘

关键点:两阶段提交

为什么不写完 Redo Log 和 Binlog 就直接提交,而要分两个阶段?

场景假设

  • 写完 Redo Log 并提交,然后宕机
  • 结果:Redo Log 里有这条记录,但 Binlog 没有
  • 后果:主库恢复了,但从库没有这条变更记录→数据不一致!

两阶段提交的解决方案

阶段 1(Prepare): 写 Redo Log,标记为"prepare"状态 ↓ 阶段 2(Commit): 写 Binlog 并刷盘 写 Redo Log 的 commit 标记 ↓ 事务完成

如果中途宕机,重启后通过检查 Redo Log 的状态来决定是否恢复:

  • 只有 prepare 标记 → 不恢复(说明 Binlog 没写完)
  • 有 commit 标记 → 恢复

六、实战:监控与调优

1. 检查 Redo Log 使用情况

-- 查看 checkpoint 进度SHOWENGINEINNODBSTATUS\G# 搜索 "LOG" 部分,关注:# - Log sequence number(当前 LSN)# - Checkpoint age(距离 checkpoint 还有多远)

Checkpoint age 过大说明刷盘跟不上写入速度,可以考虑:

  • 增大 innodb_log_file_size
  • 优化写入负载

2. Undo Log 膨胀排查

长事务会导致 Undo Log 无法被清理:

-- 查找长事务SELECTtrx.trx_id,trx.trx_state,trx.trx_started,TIMESTAMPDIFF(SECOND,trx.trx_started,NOW())asrunning_secondsFROMinformation_schema.innodb_trx trxWHERETIMESTAMPDIFF(SECOND,trx.trx_started,NOW())>60;

发现有长事务要尽快定位原因,通常是因为业务代码里事务包裹的范围太大。

3. Binlog 大小监控

-- 查看所有 binlog 总大小SELECTFILE_NAMEaslog_name,FILE_LENGTHassize_bytes,ROUND(FILE_LENGTH/1024/1024,2)assize_mbFROMinformation_schema.FILESWHEREFILE_TYPE='REDO LOG'ORFILE_NAMELIKE'%binlog%';-- 或者直接从系统表查SHOWBINARYLOGS;

Binlog 占用太大时可以调整保留策略:

# my.cnf [mysqld] expire_logs_days = 7 # 7 天后自动删除 max_binlog_size = 100M # 单个 binlog 最大 100M

七、常见问题速答

Q1: Redo Log 和 Binlog 的区别?

A: Redo Log 是 InnoDB 引擎层的物理日志,用于崩溃恢复,循环使用;Binlog 是 Server 层的逻辑日志,用于主从复制和数据恢复,不会自动覆盖。

Q2: 为什么要两阶段提交?

A: 保证 Redo Log 和 Binlog 的一致性。如果一个事务在 Redo Log 中提交了但 Binlog 没写完,单阶段提交会导致主从数据不一致。

Q3: Undo Log 什么时候被清除?

A: 当事务不需要再读旧版本时,Purge 线程会在后台清理 Undo Log。具体来说,RR 级别下事务结束后可清理,RC 级别下每条 SELECT 后可清理不再需要的旧版本。

Q4: Redo Log 满了怎么办?

A: Redo Log 是环形文件,满了就从头开始覆盖。但有个前提:_checkpoint_必须已经追赶上来,即对应的脏页已经刷回磁盘。如果写入速度太快导致 checkpoint 追不上,MySQL 会挂起写入直到有空间。


八、今日学习心得

  1. Redo Log 是 InnoDB 的"保险箱",确保宕机后数据不丢失
  2. Undo Log 是事务的"后悔药",同时支撑 MVCC 的版本链
  3. Binlog 是 Server 层的"审计日志",用于主从复制和时间点恢复
  4. 两阶段提交是保证 Redo Log 和 Binlog 一致性的关键
  5. 理解这三种日志,才能真正掌握 MySQL 的事务机制

👋 我是数据库小学妹一个用设计师思维学数据库的转行人。我们一起,把复杂的技术变得简单有趣!💕


本文示例基于MySQL8.0 + InnoDB。

http://www.jsqmd.com/news/857833/

相关文章:

  • 从零到发布:72小时打造爆款蒸汽波专辑封面,含Discord私密训练集+5个未公开--sref参数
  • CircuitJS1 Desktop Mod:基于NW.js的离线电路仿真技术架构解析
  • 如何快速实现无人机合规飞行:基于ESP32的完整远程识别解决方案
  • 惠州采购/质量/项目岗考证避坑:众智商学院6证合报,一站式搞定CPPM/PMP/SCMP/六西格玛/中级经济师/CCAA - 众智商学院课程中心
  • MySQL Binlog 格式对比
  • 从零开始搭建一个基于Taotoken多模型支持的对话应用
  • AICoverGen实战指南:5步掌握AI翻唱制作的核心技术
  • ARM SVE向量减法指令详解与应用优化
  • Camunda流程版本管理避坑指南:从Version Tag查询到迁移验证,这些细节决定成败
  • Qt样式表(QSS)实战:手把手教你解决QRadioButton和QCheckBox布局错位的那些坑
  • 重新定义怀旧体验:揭秘Bilibili-Old项目的架构哲学与实战价值
  • Super IO:Blender批量导入导出的终极解决方案,告别繁琐文件操作!
  • Midjourney洛可可风格提示词工程(2024权威白皮书版):含12组经AIGC艺术展验证的高通过率prompt模板
  • Linux驱动开发实战:为I.MX6ULL编写一个DS18B20的字符设备驱动(从设备树到应用测试)
  • 5分钟掌握DistroAV:告别复杂布线,用网络视频传输重塑你的OBS直播工作流
  • UE5 VSCode头文件跳转失效的根因与解决方案
  • DDrawCompat完整指南:3步实现Windows 11完美运行经典游戏的实用解决方案
  • Steam Economy Enhancer终极指南:如何快速提升Steam市场交易效率
  • 新一代大文件管理系统 网盘系统源码
  • 告别臃肿IDE:用w64devkit在Windows上打造一个极简C/C++开发环境(附OpenCV配置)
  • 5分钟快速激活Adobe全系列软件的终极指南:Adobe-GenP工具详解
  • UE5 VSCode头文件跳转失效的终极解决方案
  • Gophish钓鱼页面制作指南:从克隆腾讯企业邮箱到数据收集
  • 蓝牙5.0广播包PDU字段逐行解读:从ADV_IND到AUX_CHAIN_IND,新手也能看懂的报文拆解
  • 从防御者视角看TCP攻击:SYN Cookie、队列策略与Wireshark抓包分析实战
  • 在STM32上玩转C++:用IAR和类封装重构你的硬件驱动(附工程源码)
  • 2026 苏州科创企业资质办理服务商口碑榜单:高新 / 专精特新 / 绿色工厂申报靠谱机构优选 - 海棠依旧大
  • 办公效率翻倍!OpenClaw AI 数字员工实操教程
  • 终极密码恢复指南:3步轻松找回遗忘的压缩包密码
  • 从‘找不同’到异常检测:拆解RegAD论文里的空间变换网络(STN)与SimSiam