知识全景图/ 软件工程与系统/ 如何设计一个数据库/ WAL 和崩溃恢复

如何设计 WAL 和崩溃恢复

WAL 解决持久解释问题:崩溃后保留已提交,撤销未提交。

边界:事务运行时的锁、隔离和普通回滚在 事务系统。这一页只讲断电、kill、重启后的恢复证据。
一、第一版失败:commit 返回后数据丢了
失败原因需要什么
commit 返回后 kill,重启看不到修改。数据页还在 Buffer Pool,没落盘。Redo。
未提交事务的脏页被刷盘。Buffer Pool 为了腾空间刷了 dirty page。Undo。
表页和索引页只落了一半。跨页修改没有持久证据。WAL 记录修改顺序。
二、WAL 的核心规则
1. append UPDATE log 2. change page in Buffer Pool 3. append COMMIT log 4. flush WAL through commit LSN 5. return success
规则为什么
数据页刷盘前,对应日志必须先刷盘。否则崩溃后没有证据解释这个页。
commit 返回前,commit log 必须刷盘。否则用户看到成功,数据库却没有持久承诺。
每个页记录 pageLSN。恢复时判断这个页是否已经包含某条日志。
三、最小日志模型
wal_record: lsn tx_id type -- BEGIN / UPDATE / COMMIT / ABORT / CLR page_id before_image after_image prev_lsn
四、恢复三步
阶段回答什么问题
Analysis崩溃时哪些事务已提交,哪些事务没提交。
Redo已提交修改是否有些还没落到数据页。
Undo未提交修改是否已经污染了数据页。
winners = tx with COMMIT losers = tx with BEGIN but no COMMIT redo needed winner updates undo losers in reverse LSN order
五、checkpoint 为什么需要
没有 checkpoint有 checkpoint
每次恢复都从第一条日志扫起。从最近恢复点附近开始。
数据库运行越久,恢复越慢。恢复时间和最近日志量相关。
无法快速知道脏页和活跃事务。checkpoint 保存 dirty page table 和 tx table。
六、验收实验
实验通过标准
commit 前 kill。重启后修改被撤销。
commit 后、数据页刷盘前 kill。重启后修改被 Redo。
未提交脏页强制刷盘后 kill。重启后修改被 Undo。
表页落盘、索引页未落盘。恢复后访问路径一致。
大量日志后 checkpoint。恢复不从历史第一条日志开始。
一句话:WAL 不是“写日志”四个字,而是一套顺序承诺:先有日志证据,再让数据页落盘;先有 commit 证据,再告诉用户成功。