今年稍早,SQLite 發布了 3.51.3 版本,修復了其 Write-Ahead Logging (WAL) 子系統中一個名為 WAL-Reset 的長期存在的錯誤。這個錯誤自 2010 年就已存在,但 SQLite 團隊直到今年稍早才意識到它的存在(更多細節如下)。正如他們當時所寫:

「這個錯誤是一個具有嚴格時序限制的資料競爭。它在常見使用情況下不太可能發生。開發人員從未能夠有機地重現這個錯誤,不得不為 SQLite 添加特殊的測試邏輯,故意觸發錯誤的條件,以驗證問題是否已修復。」

我當時正和女友在公路旅行,但身為一個超級資料庫宅,我立刻就被這個問題吸引住了。畢竟,SQLite 的錯誤是傳奇般地罕見。而且,這聽起來就像一個完美的「棕色 M&M 症候群」:一個已知且具挑戰性的錯誤,我們可以用 Antithesis 來追蹤(我們在概念驗證中做過很多次)。更重要的是,我最近剛完成了我們為 Claude 設計的技能。

於是,我坐在陽光海岸的山坡上,拿出手機,讓 Claude 開始工作。我讓它在 Antithesis 中設定好仍有錯誤的 SQLite 3.51.2 版本,然後用大量的 Antithesis 斷言來檢測程式碼。你可以在這裡看到檢測後的版本。

接著,我讓它編寫一個簡單的工作負載,該工作負載會執行 WAL 的插入和檢查點程式碼。值得注意的是,這是一個完全通用的工作負載。它只是同時執行寫入和檢查點——這些是在生產環境中隨時可能發生的事情。這些斷言對這個錯誤來說也是通用的,它們都是你通常會添加到任何資料庫中的標準斷言,例如「沒有遺失已提交的寫入」和「資料庫沒有損壞」(在 SQLite 中稱為完整性檢查)。

我們實際上發現,最簡單的工作負載往往能找到最難的錯誤。

在我第一次執行時,Antithesis 在 15 分鐘內就捕捉到了這個錯誤。這是報告。你要找的部分是:

然後,我用 3.51.3 版本重複了這個練習,使用相同的工作負載和 Antithesis 檢測。果然,執行結果是綠燈通過。

我今天想到這件事,是因為 Tailscale 最近寫了一篇很棒的部落格文章,講述了他們如何解決 2025 年遇到的正常運行時間問題。這些問題正是 SQLite 團隊發現 WAL-Reset 錯誤的契機。Tailscale 經歷了 6 個月的運行時間不穩定,然後他們和 SQLite 團隊花了數週時間追蹤這個錯誤,推出並回滾了一個修復,結果卻破壞了其他東西,然後不得不再等兩個月,看看「真正的」修復(3.51.3)是否有效。

為了找出問題的根本原因,他們不得不為 Tailscale 編寫一個新的交易日誌管道,然後為 SQLite 的虛擬檔案系統層插入一個新的偵錯工具。在 Antithesis 中,這個過程雖然不是一鍵完成,但一鍵操作就能提供因果關係分析,將問題精確到毫秒級,並提供確定性的時間旅行偵錯功能,讓你能夠進行假設分析和破壞性分析。

正如 Tailscale 團隊所寫:「沒有人希望我們花六個月的時間去尋找 SQLite 中的錯誤。這對我們的客戶和員工來說都是一次極其令人沮喪的經歷。」

找出像 WAL-Reset 這樣的錯誤是極其困難的(也許就像在碎玻璃上爬行一樣)——但對於罕見且困難的錯誤,真正的折磨可能來自於等待,看你的修復是否真的有效。我在足夠多的資料庫上工作過,並且親身經歷過很多次。

因此,意識到這個錯誤在實際應用中造成了多麼痛苦的經歷,既令人警醒又令人振奮。透過賦予代理人使用 Antithesis 的技能,我僅僅花了一小時,就從手機上,在陽光下的雲杉樹下,找到了並驗證了它。我知道我們的代理技能有效,但我沒想到它們會如此有效。如果你有棘手的資料庫問題,請聯繫我。