知识卡片

Write-Ahead Logging的FORCE与STEAL组合与崩溃恢复三阶段

结构图卡

内容

[[Commit-Logging用日志与提交记录保障原子性和持久性]]有个硬伤:事务提交前 绝不允许把变动数据提前写盘,哪怕磁盘I/O空闲、内存缓冲区被占满也不行,这对 性能很不利。ARIES提出的Write-Ahead Logging(预写日志)允许”提前写入”, 用FORCE(提交后是否强制变动数据立即落盘)和STEAL(提交前是否允许变动数据 提前落盘)两个维度描述策略:Commit Logging等价于NO-FORCE+NO-STEAL;WAL 允许NO-FORCE也允许STEAL,代价是必须新增Undo Log(记录改前的值,供回滚 时擦除提前写入的变动)区别于原有记录改后值、供崩溃恢复重演历史的Redo Log。 崩溃恢复因此分三阶段:分析阶段从最近一个检查点开始扫描日志,找出所有没有 End Record的未完成事务;重做阶段把这些事务里带Commit Record的部分重新 写入数据(重演历史);回滚阶段把剩下没有Commit Record的”Loser”事务,按 Undo Log把提前写入的数据改回去。重做和回滚阶段的操作都必须设计成幂等的, 因为崩溃可能在恢复过程中再次发生。

结构图

flowchart TD
    A[事务修改数据] --> B{是否已提交?}
    B -->|已提交, 找Commit Record| C[重做阶段 Redo: 按Redo Log重演写入]
    B -->|未提交, 无Commit Record| D[回滚阶段 Undo: 按Undo Log擦除已提前写入的变动]
    E[检查点 Checkpoint] --> F[分析阶段 Analysis: 扫描找出所有未完成事务]
    F --> C
    F --> D
    G[FORCE/STEAL策略矩阵] -->|NO-FORCE+NO-STEAL| H[Commit Logging: 简单但提交前不可写盘]
    G -->|NO-FORCE+STEAL| I[WAL: 需要Undo Log, 性能最优]

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第3章"事务处理"3.1.1节 "实现原子性和持久性"(源文件:_epub-src对应OEBPS/Text/chapter26.xhtml) - 结论依据:原文定义FORCE/STEAL两个维度、说明WAL通过引入Undo Log突破 Commit Logging"提交前不可写盘"的限制,并详述崩溃恢复分析/重做/回滚 三阶段的具体操作,直接支撑本卡片的结构梳理。 - 原始内容:Write-Ahead Logging允许NO-FORCE,也允许STEAL,它给出的解决 办法是增加了另一种被称为Undo Log的日志类型……由于Undo Log的加入, Write-Ahead Logging在崩溃恢复时会经历分析、重做、回滚三个阶段。