[Critical] WAL write failure 语义过于简化:write() 失败后 bytes 可能已落盘 #5

Closed
opened 2026-06-09 13:07:11 +08:00 by dailz · 0 comments
Owner

来源

Oracle 审核 docs/design.md Section 3.2 WAL

位置

Section 3.2 "写入流程" 步骤 ⑤ 及后续错误处理段落(~line 117)

问题描述

当前设计将 WAL encode/write 失败统一当作 "definitely failed" 返回普通错误。但实际上存在两种不同情况:

  1. Encode 失败(未触及 syscall):确实是 definitely failed,可以安全返回普通错误
  2. write() 失败(bytes 可能已进入 OS page cache 或部分写入文件):不是 definitely failed。Recovery 后可能发现该 batch CRC 合法并被重放,导致语义矛盾——调用方收到错误认为写入失败,但数据实际被恢复

影响

调用方可能基于"写入失败"做非幂等业务决策(如放弃、走替代路径),但数据实际持久化了。

建议修复

拆分 WAL write failure 处理:

  • encode 失败(未调用 write()):普通错误 + write-stopped
  • write() 失败(bytes 可能已交给 OS):ErrCommitUnknown + write-stopped,除非实现能证明零 bytes 到达文件(例如 write 返回 0 且无副作用)
## 来源 Oracle 审核 `docs/design.md` Section 3.2 WAL ## 位置 Section 3.2 "写入流程" 步骤 ⑤ 及后续错误处理段落(~line 117) ## 问题描述 当前设计将 WAL encode/write 失败统一当作 "definitely failed" 返回普通错误。但实际上存在两种不同情况: 1. **Encode 失败**(未触及 syscall):确实是 definitely failed,可以安全返回普通错误 2. **`write()` 失败**(bytes 可能已进入 OS page cache 或部分写入文件):不是 definitely failed。Recovery 后可能发现该 batch CRC 合法并被重放,导致语义矛盾——调用方收到错误认为写入失败,但数据实际被恢复 ## 影响 调用方可能基于"写入失败"做非幂等业务决策(如放弃、走替代路径),但数据实际持久化了。 ## 建议修复 拆分 WAL write failure 处理: - encode 失败(未调用 `write()`):普通错误 + write-stopped - `write()` 失败(bytes 可能已交给 OS):`ErrCommitUnknown` + write-stopped,除非实现能证明零 bytes 到达文件(例如 `write` 返回 0 且无副作用)
dailz closed this issue 2026-06-09 13:38:17 +08:00
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#5