先说结论:真正危险的是“成功提交后悄悄消失”,不是一次普通报错

SQLite 的 WAL 模式先把新页面写入 write-ahead log,再由 checkpoint 把页面合并回主数据库。Tailscale 与 SQLite 团队定位到的竞态发生在 checkpoint 和写事务非常特殊的交错时序:checkpoint 看到 WAL 被另一个线程重置后,错误地把某些页面当作已经复制。写事务可以正常返回成功,后续事务却看不到那次提交;引用这些缺失页面的索引或其他页面继续落盘,最终让数据库结构不一致。

这也是问题多年未被发现的原因。Tailscale 的控制平面按分片使用单个 Go 进程和单写者 SQLite,完整快照每几分钟上传一次,这套架构从 2023 年起长期无事。直到生产规模把极低概率时序重复放大,团队才在六个月内遇到 19 次损坏。它们靠备份监控持续运行 `PRAGMA integrity_check`、遇到损坏立刻停止分片、保存取证信息,并把每个写 SQL 事务另记日志用于重放,才找到“已提交写入在后续事务中消失”的关键线索。

中文开发者最该复制的是验证链,而不是恐慌式迁库

先确认应用真正加载的 SQLite 版本,而不是只看系统命令或包管理器标签;桌面应用、移动端、Python、Node、Go 和容器可能各自捆绑不同运行时。再在数据库副本上检查 WAL 配置、checkpoint 策略、备份是否包含一致状态,并执行完整恢复演练。`integrity_check` 能发现结构问题,却不能证明每笔业务数据都存在,因此还要核对关键表行数、外键、时间序列连续性和应用级不变量。

已经出现异常的库不应在唯一副本上反复“修复”或盲目 checkpoint。先冻结写入、复制数据库及 WAL/SHM、记录版本和文件哈希,再从已验证快照恢复并重放可审计事务。公开内容应给出安全检查表与版本证据,不散布“SQLite 天生会丢数据”的结论。所有复盘框架、标题模板和恢复演练简报都应免费公开;读者也可向搞着玩实验室免费提交自己的备份流程,先共同找出验证缺口,再决定是否需要固定范围的个人诊断或原型服务。