(つ`ω´)つ says to Ubuntu 台灣社群
Tailscale 查明資料庫毀損肇因於 SQLite 一項存在 16 年的 WAL 重設瑕疵 (★ 123 分) Tailscale 的控制平面以多個獨立分片(shard,分散承載不同 Tailnet 的服務單元)運作;每個分片由單一 Go 程序獨占一個 SQLite 資料庫,保存裝置與網路組態等中繼資料,不含私密加密金鑰或實際網路流量。自 2025 年 8 月起,該公司在六個月內遭遇 19 次資料庫毀損,受影響分片必須停機修復或自備份還原。已在線上的裝置仍可維持既有 WireGuard 點對點連線,但無法得知網路變動;新加入裝置、管理主控台與 API(應用程式介面)也會暫時失效。早期事故還曾造成少量剛新增的裝置或組態變更未被保留。 團隊起初檢查程式、負載、客戶特徵與作業時段,卻找不到可重現的觸發條件,因而在正式環境布署鑑識記錄,並向 SQLite 核心開發者購買專業支援服務。他們同時縮短復原時間、持續檢查 S3 備份的完整性,並記錄每一筆修改資料庫的 SQL 交易,以便從最近的正確備份依序重放交易。兩起事故中,重放過程顯示某些已提交的寫入竟對後續交易消失,成為關鍵線索。 根因是 SQLite 的 WAL(Write-Ahead Logging,預寫式日誌)機制內一項至少存在 16 年的罕見競態狀況。SQLite 會先把資料頁寫進 WAL 檔,再經由檢查點作業複製回主要資料庫;Tailscale 為了快速且一致地備份,手動且頻繁地控制檢查點。當寫入交易恰好撞上 WAL 重設時,檢查點可能誤以為部分資料頁已寫回主檔,實際上卻遺漏寫入;若索引等其他資料已參照那些遺失頁面,便會造成永久資料遺失與資料庫毀損。SQLite 開發者藉由新製作的 `tmstmpvfs` 虛擬檔案系統追蹤工具定位問題,並在 SQLite 3.51.3 修補。原先的 3.52.0 版本另因浮點數轉換的微小捨入變化,觸發舊有運算式索引誤報毀損,因而被撤回;SQLite 3.53.0 也新增索引自我修復機制。 修補後,Tailscale 在驅動程式加入警示,專門偵測寫入與 WAL 重設重疊的時機;兩個月後警示確實出現,但資料庫未再毀損,證實修補成功攔下真實正式環境中的觸發條件,之後連續四個月未再發生事故。Hacker News 的討論普遍肯定 Tailscale 願意付費取得 SQLite 專業協助、資助開源除錯工具,並公開完整事故報告的長期作法。也有留言提醒,「單一寫入者」不等於只有一個資料庫連線;此錯誤須在多個連線、不同執行緒分別處理寫入與檢查點時才可能出現。另有人指出,採取非典型且積極的檢查點策略者應儘速升級 SQLite,而分片內控制平面仍是單點故障的設計取捨,也值得持續改善。 👥 11 則討論、評論 💬 https://news.ycombinator.com/item?id=49272832