Skip to content

第7章:日志、检查点与崩溃恢复

为什么要日志

事务修改多页,崩溃可能发生在任意两次写入之间。日志记录足以重做或撤销的变化,使恢复不依赖所有数据页恰好同时落盘。

WAL 有两个关键顺序:数据页落盘前,相应更新日志先持久化;向客户端确认提交前,提交所需日志必须达到协议要求的持久边界。

steal 与 no-force

steal 允许未提交修改所在页被写出,因此恢复可能需要撤销。no-force 允许提交时不立即写出所有修改页,因此恢复可能需要重做。这两个选择分别影响 undo 与 redo,不能混为“是否使用日志”。

假设事务把 A 从 100 改为 90、B 从 100 改为 110。若 A 页写出后崩溃且事务未提交,恢复应使扣款不单独保留;若已提交日志落盘、两数据页尚未写出,恢复要重做两次更新。

LSN 与重复恢复

日志序列号 LSN 标记更新顺序,页上可记录已包含到哪个更新。恢复时比较页状态与日志,避免不加判断地重复施加非幂等变化。

ARIES 风格恢复分分析、重做、撤销:分析识别事务和脏页状态,重做恢复历史效果,撤销未完成事务。补偿日志记录 CLR 让撤销本身可被再次恢复,处理“恢复中又崩溃”的情况。

这一流程是特定恢复体系,不要求所有数据库都采用同一实现。影子分页、不同版本存储和日志格式会有别的恢复方式。

检查点与备份

检查点保存恢复可用的状态,缩短重启需要扫描或重做的范围。模糊检查点可以在事务继续运行时建立,不一定把所有脏页立刻写干净。

备份用于恢复更广泛的损坏,例如设备丢失或误操作。日志和检查点若与数据一起丢失,单机崩溃恢复协议无法凭空还原。副本也可能同步执行误删除,因此复制不等于独立备份。

练习

  1. 对 steal/no-steal 与 force/no-force 的四种组合,判断是否需要 undo 和 redo。
  2. 为什么必须先持久化更新日志再写数据页?
  3. 恢复过程中再次崩溃,会对日志设计提出什么要求?

上次更新: