题目重点:用提交日志和数据页的时间顺序解释持久性,区分恢复与复制。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 明确问WAL/redo在恢复中的作用。练习通用日志先行模型,具体undo/redo记录格式和引擎策略未给,不能跨数据库套一个恢复算法。
- 同步持久提交模型要求满足日志持久条件再对客户端确认;异步提交合同不同,必须单独说明可能丢失窗口。
解题路线
- WAL核心是数据页持久化前,对应变更日志先持久。这样崩溃后页尚未包含的更新可以由日志恢复,而不必每个小事务都立即flush全部数据页。
- redo重做已记录的页变化;重复恢复需要页位点/LSN等判断已应用记录,避免重复应用非幂等的“余额+10”。不是简单从头把业务请求再执行一遍。
- checkpoint缩短恢复需要检查的范围,但不是可随意删除全部旧日志的时刻;未刷脏页、备份和复制消费者仍可能需要旧记录。日志回收由最小安全位点决定。
- group commit让多事务共享日志flush,提升吞吐但增加批等待。崩溃时区分已经持久确认的commit、未确认但可能持久的记录及未写完整尾段;客户端超时需查结果/幂等重试。
手动走一遍
更新页P、日志LSN42已持久并确认,页仍旧内容时断电:重放42恢复新页。若页先写而日志没落盘,恢复无依据。页已经应用42后再恢复,不重复给账户再加一次金额。
规模与取舍
恢复耗时由检查日志量与页IO决定,约日志字节/解析带宽加读写页成本;checkpoint频率与写放大/恢复目标权衡。提交吞吐不能只看单次fsync延迟,还看批大小、日志大小和CPU。
易错点与追问
容易失分的边界
- 把WAL当完整业务请求日志再执行外部副作用。
- 所有checkpoint前日志都立刻删除。
- 把日志flush成功等同于reader已经可见。
继续深挖
- 日志最后一条只写了一半如何识别?
- 怎样同时满足备份PITR与日志磁盘容量上限?
技术参考
- PostgreSQL WAL与恢复:技术语义参考,具体题目按本文约定。
