liuziyi

liuziyi

ORACLE 和MYSQL redo 和 undo 的含义

一、概念定义

redo 和 undo 是“先写日志再写数据”这套机制(WAL,Write-Ahead Logging)的两个组成部分:

  • redo(重做日志):记录“数据页被改成了什么”,按顺序追加写入,用于崩溃后前滚重放,把已经落盘的日志变更重新应用到数据上。
  • undo(回滚日志):记录“改动之前的旧值”,用于事务回滚和一致性读(构造修改前的版本)。
  • 日志回放:数据库启动或恢复时,把日志中的变更按顺序重新应用,使数据库从崩溃后的不一致状态恢复到一个事务一致的状态。

两家产品的定位差异:

维度 Oracle MySQL(InnoDB)
redo 归属 数据库内核层的联机重做日志 + 归档日志 InnoDB 存储引擎层的物理日志
undo 归属 undo 表空间 / undo 段(回滚段) undo 表空间 / 回滚段(rollback segment)
额外日志 归档日志用于介质恢复 服务器层 binlog,与 redo 通过两阶段提交协调
回放典型场景 实例恢复、介质恢复 崩溃恢复、备份恢复

二、作用与适用场景

Oracle

  • 实例恢复(Instance Recovery):实例异常终止后,确保 buffer cache 中已提交的变更不丢失,并回滚未提交事务,使数据库达到一致状态。
  • 介质恢复(Media Recovery):数据文件损坏或丢失时,用备份 + 归档日志 + 联机日志前滚到目标时间点。
  • 事务回滚与一致性读:ROLLBACK 按 undo 链逆向撤销;查询用 undo 构造读一致性版本。

MySQL

  • 崩溃恢复:异常宕机后,用 redo 把已提交但未刷盘的数据页变更恢复到数据文件。
  • 事务回滚与 MVCC:undo 用于回滚,也为一致性读提供旧版本;提交后由 purge 线程清理不再需要的 undo。
  • 主从复制与备份:binlog 负责逻辑变更传播;redo 负责引擎层持久化,两者靠两阶段提交保持一致。

共同点:提交只保证日志落盘,不要求数据页已经落盘,所以崩溃后必须回放。

三、工作机制

1. Oracle 的回放机制

正常运行阶段

  1. 会话修改数据块,改动先在 buffer cache 中完成;
  2. 同时生成 redo 记录写入 log buffer,生成 undo 记录写入 undo 段;
  3. 提交时 LGWR 把 redo 从 log buffer 写入联机重做日志文件(提交等待即 log file sync);
  4. 脏数据块由 DBWn 延迟写出,检查点控制推进节奏。

实例恢复阶段

  1. 确定起点:从控制文件中记录的检查点位置(RBA/SCN)开始;
  2. 前滚(roll forward):顺序应用 redo,把日志中记录的块变更重新做一遍。这一步包括未提交事务的变更,先把数据恢复成崩溃瞬间的样子;
  3. 回滚(roll back):用 undo 逆向撤销未提交事务,按 undo 链逐条回退;
  4. 完成 open:回滚完成后实例恢复才算真正结束。因此 redo 或 undo 任一丢失、损坏,都可能导致实例恢复失败;
  5. 介质恢复则在此基础上还需要归档日志补齐日志链。

要点:undo 本身的修改也会产生 redo,否则恢复时无法重建 undo。

2. MySQL(InnoDB)的回放机制

正常运行阶段

  1. 修改先发生在 buffer pool 的数据页上;
  2. 生成 redo 写入 redo log buffer,事务提交时按 innodb_flush_log_at_trx_commit 的策略刷入 redo log file;
  3. 同时生成 undo(分 insert undo 与 update undo 两类),写入 undo 表空间;
  4. 若开启 binlog,则执行两阶段提交:
    • Prepare:redo 进入 prepare 状态;
    • 写 binlog 并 fsync;
    • Commit:redo 进入 commit 状态。

崩溃恢复阶段

  1. 确定起点:从最近一次 checkpoint 对应的 LSN 开始扫描 redo;
  2. 前滚:把 redo 重放到日志末尾的最新 LSN,恢复已提交但未刷盘的数据页变更;
  3. 处理 prepare 事务:对处于 prepare 状态的事务,用 XID 与 binlog 比对——binlog 中存在则提交,不存在则回滚,从而保证 redo 与 binlog 一致;
  4. 回滚未提交事务:用 undo 撤销;
  5. purge:后续由 purge 线程清理不再需要的 undo 版本。

要点:

  • 恢复时间与 checkpoint LSN 到当前 LSN 的差距直接相关,差距越大需要重放越多;
  • redo 日志文件较大能减少检查点频率、降低日常 I/O,但会拉长崩溃恢复时间;
  • redo 归档文件(无论哪种归档方式)不参与崩溃恢复,崩溃恢复只读 #innodb_redo 目录下的 redo 文件。

四、相关对象与观察入口

Oracle

视图/入口 用途 与本概念的关联
V$LOG 联机重做日志组状态 观察当前日志、切换与归档状态
V$LOG_HISTORY 控制文件中的日志历史 判断日志链与恢复起点
V$INSTANCE_RECOVERY 恢复 I/O 限制机制 结合 FAST_START_MTTR_TARGET 估算恢复量
V$TRANSACTION 活动事务 观察事务的 undo 占用
V$ROLLSTAT 回滚段统计 观察回滚段使用与回滚活动
V$UNDOSTAT undo 使用直方图(10 分钟一档) 观察 undo 空间消耗与事务并发

其他入口:告警日志中的 “Instance Recovery”“Media Recovery” 记录;等待事件 log file sync、log file parallel write、log buffer space;统计项 redo size、redo entries 等。

MySQL

视图/入口 用途 与本概念的关联
SHOW ENGINE INNODB STATUS 引擎运行状态 LOG 段可见 Log sequence number、Last checkpoint at,直接反映待重放量
information_schema.INNODB_TRX 当前事务 观察事务状态与 undo 相关活动
information_schema.INNODB_METRICS InnoDB 计数器 观察 redo/undo 相关统计
performance_schema 细粒度等待与统计 分析日志写入与恢复相关等待

其他入口:#innodb_redo 目录下的 redo 文件;undo 表空间文件;参数 innodb_redo_log_capacity、innodb_log_file_size、innodb_flush_log_at_trx_commit、innodb_fast_shutdown、innodb_force_recovery;innodb_fast_shutdown=2 相当于冷关闭,下次启动会走崩溃恢复流程。

五、常见误区与边界

  • redo 与 undo 不能互相替代:redo 负责前滚,undo 负责回退。redo 重放时也会重放未提交事务,最终一致性靠 undo 收尾。
  • “回放”不等于“把日志应用到最新”:实例/崩溃恢复只回到崩溃点;时间点恢复受恢复目标限制。
  • redo 不是 SQL 日志:Oracle redo 是块级变更记录,MySQL redo 是数据页级物理日志;MySQL 的语句/行级逻辑记录在 binlog 里,两者不要混为一谈。
  • MySQL 的 binlog 与 redo 是两层日志:binlog 在服务器层,redo 在 InnoDB 层,靠两阶段提交保证一致;Oracle 没有同名的 binlog 机制,对应场景是归档日志与备库日志传输。
  • 提交只保证日志落盘,不保证数据页落盘,所以崩溃后必须回放。
  • undo 也会产生 redo:不能认为“写 undo 就没有日志开销”。
  • PostgreSQL 等产品没有同名 undo 段,其 MVCC 由旧版本元组 + WAL 实现,不能直接套用本文术语。
  • 日志损坏或缺链才会需要介质恢复;普通断电一般只走实例恢复/崩溃恢复,不需要备份介入。

六、延伸知识

  • 检查点与恢复量的权衡:Oracle 用 FAST_START_MTTR_TARGET 控制恢复时间;MySQL 用 checkpoint LSN 差距衡量,redo 文件越大恢复越慢。
  • 日志序列定位:Oracle 用 SCN/RBA,MySQL 用 LSN,都是判断“从哪里开始重放”的基础。
  • MVCC 与一致性读:Oracle 靠 undo 构造读一致性;MySQL 靠 undo + Read View。
  • 清理机制:Oracle 由 SMON 管理 undo 段与 undo_retention;MySQL 由 purge 线程清理 undo,长事务会拖住 purge。
  • 高可用延伸:Oracle Data Guard 的日志应用、MySQL 主从复制与 MGR 的日志传输,本质都是“日志回放”的跨实例延伸。

posted on 2026-10-26 18:19  刘子毅  阅读(4)  评论(0)    收藏  举报

导航