From 40b6791fea0749a3bd57ae20e1430e0b62f80486 Mon Sep 17 00:00:00 2001 From: dailz Date: Fri, 12 Jun 2026 08:52:34 +0800 Subject: [PATCH] update WAL recovery segment continuity design Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- docs/design.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/design.md b/docs/design.md index fb44508..48de4c3 100644 --- a/docs/design.md +++ b/docs/design.md @@ -529,6 +529,8 @@ MANIFEST 是 recovery 起点和 checkpoint 状态的权威源,记录最老仍 5. 如果 MANIFEST 指定的 recovery segment 缺失,或后续需要恢复的 segment 不连续,报错 ``` +目录扫描得到的 WAL segment 集合必须先按 `MANIFEST.recoverySegmentID` 过滤:`segmentID < recoverySegmentID` 的旧 segment 已被 MANIFEST 覆盖,不属于 recovery candidate set。Recovery 不校验这些旧 segment 的连续性、header 或 `startSequence`;它们即使仍残留在目录中,也只交由文件生命周期清理流程处理。 + 该规则保证即使 CURRENT 更新在崩溃前未持久化,恢复仍不会依赖不可靠的 active segment 指针;只要已确认写入所在 segment 已按 WAL 元数据持久化协议进入 durable-ready 状态,恢复就能通过目录扫描发现它。 ###### Recovery 扫描流程 @@ -554,10 +556,14 @@ MANIFEST 是 recovery 起点和 checkpoint 状态的权威源,记录最老仍 从 MANIFEST 指定的 recovery 起点开始,多 segment 恢复必须同时校验 `segmentID` 和 `startSequence` 的连续性: ```text +segments = scan WAL directory +recoverySegments = segments where segmentID >= manifest.recoverySegmentID +sort recoverySegments by segmentID ascending + expectedSegmentID = manifest.recoverySegmentID expectedSequence = recoveryStartSegment.startSequence -for segment in segmentID ascending order: +for segment in recoverySegments: require segment.segmentID == expectedSegmentID require segment.startSequence == expectedSequence @@ -571,6 +577,10 @@ for segment in segmentID ascending order: 已被 MANIFEST 证明不再需要的旧 WAL segment 可以删除,不参与连续性校验;连续性要求只适用于 recovery 起点之后仍需恢复的 WAL segment。 +如果目录中仍存在 `segmentID < recoverySegmentID` 的旧 segment,recovery 必须忽略它们,不得因旧 segment 的缺失、不连续、header 损坏或 `startSequence` 不匹配而报错。是否删除这些旧文件属于 checkpoint 后的文件生命周期管理,不是 recovery 正确性的前置条件。 + +首次创建数据库时,`MANIFEST.recoverySegmentID` 通常初始化为 0;但该值不是全局固定起点。随着 checkpoint 推进,`recoverySegmentID` 可以推进到任意后续 `segmentID`,后续 recovery 只从该起点开始要求连续。 + ###### Physical Record 解析规则 解析器在 Block 内顺序读取 Physical Record: