[Critical] 预创建 segment 可破坏尾部截断逻辑 #7

Closed
opened 2026-06-09 13:07:40 +08:00 by dailz · 1 comment
Owner

来源

Oracle 审核 docs/design.md Section 3.2 WAL

位置

Section 3.2 "WAL 元数据持久化协议"(~line 173)与 "Physical Record 解析规则"(~line 491)

问题描述

新 segment 创建协议(步骤 1-8)允许 segment-N+1.wal 在文件系统上可见(已完成 rename + directory fsync),即使它尚未承载任何 batch。如果此时进程崩溃,segment-N.wal 可能有 crash-torn tail。

Recovery 扫描时,因为 segment-N+1.wal 存在且 header 合法,segment-N 不再被视为"最后一个需要恢复的 segment"。按照当前的尾部/中间损坏分类规则,segment-N 的尾部损坏会被升级为"WAL 中间损坏"→ 报错而非截断。

影响

一个本应可截断恢复的尾部 partial write 场景被错误升级为不可恢复的中间损坏,导致整个 DB 无法启动。

建议修复

方案 A(推荐):禁止预创建未来 segment,直到当前 segment 在完整 batch 边界 sealed:

新 segment 只在当前 active segment 写完一个完整 WAL Batch 后才创建。
确保 segment-N 永远在完整 batch 边界结束,segment-N+1 的创建不先于该 sealing。

方案 B:Recovery 能识别并忽略空 segment:

如果 segment header 合法但不含任何 complete batch,且 startSequence == expectedSequence,视为空 segment,跳过或删除,继续扫描下一个 segment。

## 来源 Oracle 审核 `docs/design.md` Section 3.2 WAL ## 位置 Section 3.2 "WAL 元数据持久化协议"(~line 173)与 "Physical Record 解析规则"(~line 491) ## 问题描述 新 segment 创建协议(步骤 1-8)允许 `segment-N+1.wal` 在文件系统上可见(已完成 rename + directory fsync),即使它尚未承载任何 batch。如果此时进程崩溃,`segment-N.wal` 可能有 crash-torn tail。 Recovery 扫描时,因为 `segment-N+1.wal` 存在且 header 合法,`segment-N` 不再被视为"最后一个需要恢复的 segment"。按照当前的尾部/中间损坏分类规则,`segment-N` 的尾部损坏会被升级为"WAL 中间损坏"→ 报错而非截断。 ## 影响 一个本应可截断恢复的尾部 partial write 场景被错误升级为不可恢复的中间损坏,导致整个 DB 无法启动。 ## 建议修复 **方案 A(推荐)**:禁止预创建未来 segment,直到当前 segment 在完整 batch 边界 sealed: > 新 segment 只在当前 active segment 写完一个完整 WAL Batch 后才创建。 > 确保 segment-N 永远在完整 batch 边界结束,segment-N+1 的创建不先于该 sealing。 **方案 B**:Recovery 能识别并忽略空 segment: > 如果 segment header 合法但不含任何 complete batch,且 `startSequence == expectedSequence`,视为空 segment,跳过或删除,继续扫描下一个 segment。
dailz closed this issue 2026-06-11 17:52:35 +08:00
Author
Owner

已在设计文档中修复:f6a2cd9 update WAL segment boundary design 补充了 segment rotation 约束,明确新 segment 的 durable-ready 协议只能在当前 active segment 已结束于完整 WAL Batch 边界后启动,并禁止预创建未来 segment / 让 segment-N+1 在 segment-N 仍可能存在未完成 Batch 尾部时对 recovery 可见。对应位置:docs/design.md:213、docs/design.md:328-332。

已在设计文档中修复:f6a2cd9 `update WAL segment boundary design` 补充了 segment rotation 约束,明确新 segment 的 durable-ready 协议只能在当前 active segment 已结束于完整 WAL Batch 边界后启动,并禁止预创建未来 segment / 让 segment-N+1 在 segment-N 仍可能存在未完成 Batch 尾部时对 recovery 可见。对应位置:docs/design.md:213、docs/design.md:328-332。
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dailz/go-kv#7