update WAL tail truncation recovery design

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
dailz
2026-06-11 20:17:29 +08:00
co-authored by Sisyphus
parent c02bbc57e3
commit 7557c38e6c
+19
View File
@@ -606,6 +606,25 @@ lastCompleteBatchEnd = 当前 WAL offset
如果 Batch Header 或 Entry 解析错误发生在 WAL 尾部,可以丢弃该 incomplete batch;如果发生在 WAL 中间,默认报错。
###### 尾部截断持久化
当 recovery 在最后一个需要恢复的 segment 发现可截断的 WAL 尾部损坏时,截断本身是 recovery repair 的一部分,必须在恢复完成并接受新写入前持久化。截断目标始终是最后一个完整 WAL Batch 的结束位置 `lastCompleteBatchEnd`;非最后恢复 segment 中的异常仍按 WAL 中间损坏处理,不得通过截断 repair 静默跳过。
尾部截断持久化步骤:
```text
1. ftruncate 当前 active segment 到 lastCompleteBatchEnd
2. fsync 被截断的 segment
3. 删除 startSequence == expectedSequence 且不含任何 complete batch 的后续空 segment
4. fsync WAL directory
5. 更新 MANIFEST 或等价 recovery metadata,记录本次 recovery repair 后的恢复终点
6. fsync metadata directory
```
以上步骤全部成功后,recovery 才能进入恢复完成状态并允许 WAL writer 接受新写入。若任一步失败,recovery 必须报错,DB 不得进入可写状态;否则再次崩溃后可能重新暴露未持久化的截断尾部,导致重复 repair 或 recovery 边界不一致。
这里的 MANIFEST 更新只记录 recovery repair 后的安全边界,不等同于普通 checkpoint 推进,也不意味着旧 WAL segment 已经可以删除。旧 WAL 文件生命周期仍由 MemTable flush、SSTable 与 checkpoint 元数据持久化后的规则决定。
###### 恢复完成状态
恢复完成后: