題干與適用場景
一個桌面同步服務在多個程序中開啟同一個 SQLite 檔案,資料庫使用 WAL 模式。團隊發現歷史版本可能存在 WAL-reset bug,擔心升級過程誤判資料安全、觸發並發寫入或把損壞副本繼續同步。請設計從版本盤點、風險判定、升級、完整性驗證、備份復原到回滾的方案,並說明如何治理多程序存取。
面試官考察點
- 能否區分「受影響版本」與「實際觸發條件」,避免把理論風險誇大成已損壞事實。
- 能否根據官方修復版本和回移版本制定升級矩陣。
- 能否設計一致的備份、校驗、隔離和復原順序。
- 能否解釋
PRAGMA integrity_check的邊界,而不是把它當成所有業務正確性的證明。 - 能否處理多程序寫入、checkpoint、檔案複製和同步下游的副作用。
回答前需要釐清的問題
- 目前 SQLite 精確版本、編譯選項、作業系統和資料庫是否持續使用 WAL?
- 是否存在兩個以上程序或執行緒同時對同一檔案寫入或 checkpoint?
- 資料庫是否有可驗證的備份、同步副本和最後一次成功校驗時間?
- 升級是否允許短暫停寫,客戶端是否能強制退出舊程序?
- 資料損壞的容忍度是什麼:可丟失最近交易、可從服務端重建,還是必須原樣復原?
30 秒回答
我會先做版本與執行模式盤點,不把「版本落在受影響範圍」直接等同於已經損壞。SQLite 官方說明 WAL-reset bug 影響 3.7.0 到 3.51.2 的部分 WAL 場景,3.51.3 及之後修復,另有少數回移版本。升級前凍結寫入,複製原檔案和 WAL/SHM 相關材料,記錄校驗基線;在隔離副本上升級並執行完整性檢查、業務抽樣和同步一致性校驗。通過後再切換生產檔案,保留可回滾副本。長期治理上限制同檔案多程序寫入,監控 checkpoint、鎖衝突和校驗失敗,並把復原演練納入發布門禁。
分步驟深入解答
1. 建立影響矩陣
官方資料指出,WAL-reset bug 可能存在於 3.7.0 至 3.51.2,修復版為 3.51.3 及以後,部分舊分支有 3.44.6 和 3.50.7 回移修復。風險還需要同時滿足 WAL 模式、同一檔案的多個連線,以及寫入或 checkpoint 在緊密時間窗交錯。先記錄每個客戶端的 SQLite 版本、WAL 狀態、連線數、程序模型和檔案位置,再按「受影響版本 + 觸發條件是否存在」分層。
版本與模式 -> 是否使用 WAL -> 是否多連線/多程序 -> 是否存在並發寫入與 checkpoint
| | | |
+-- 升級門禁 ----+--------------------+----------> 隔離驗證與復原演練2. 凍結與取證
發布窗口先停止新寫入,讓應用優雅關閉連線;無法確認舊程序已退出時,不複製或替換資料庫。保存原資料庫、同目錄的 WAL/SHM 檔案、版本資訊、最近備份和校驗日誌。任何複製都應在穩定狀態下進行,避免把正在變化的 WAL 當成靜態快照。
3. 隔離升級與校驗
在副本上使用修復版本開啟資料庫,先做 SQLite 層完整性檢查,再做應用層抽樣:行數、關鍵索引、外鍵關係、同步游標和最近交易。integrity_check 能發現部分結構問題,但不能證明業務語義、遠端副本或未提交交易都正確。校驗結果必須關聯資料庫副本雜湊和工具版本。
4. 切換、回滾與復原
通過門禁後原子切換檔案路徑或版本目錄,舊副本只讀保留。若啟動後出現校驗失敗、同步衝突或業務資料缺口,立即停止新寫入,切回舊副本或從可信備份重建,再進行增量同步。不要在疑似損壞檔案上繼續執行 VACUUM、批量修復或覆蓋式複製,以免丟失取證材料。
5. 多程序與 checkpoint 治理
優先把同一檔案的寫入集中到單一程序,透過請求佇列串行化寫交易;其他程序使用受控讀連線。明確 checkpoint 的觸發方、逾時和失敗告警,避免多個元件同時主動 checkpoint。若必須多程序協作,記錄連線生命週期、鎖等待、checkpoint 結果和程序版本,並用壓力測試重現寫入與 checkpoint 交錯。
6. 監控與復原演練
發布後監控 SQLite 版本覆蓋率、WAL 檔案增長、checkpoint 延遲、鎖衝突、完整性檢查失敗、同步重試和復原耗時。定期用脫敏副本演練「凍結—備份—校驗—切換—回滾」,驗證舊客戶端不會重新寫入舊版本資料庫。復原目標應以業務 RPO/RTO 表示,不能只寫「有備份」。
高品質示範回答
我會先建立影響矩陣:SQLite 版本是否在 3.7.0–3.51.2、是否使用 WAL、同一檔案是否有多個連線,以及是否可能同時寫入和 checkpoint。版本落入範圍只說明需要升級和驗證,不說明檔案已經損壞。生產窗口凍結寫入並確認舊程序退出,保存資料庫、WAL/SHM、備份、版本和雜湊;在隔離副本上升級到 3.51.3 或可接受的回移修復版。
驗證分三層:PRAGMA integrity_check 檢查結構,應用抽樣檢查關鍵資料和索引,同步校驗檢查本地與遠端游標。通過門禁後原子切換,保留舊副本只讀。如果出現校驗或業務缺口,停止寫入、回滾到可信副本並重建增量同步。長期上把寫入集中到單一程序,限制主動 checkpoint,監控鎖衝突與校驗失敗,並定期演練復原。
常見錯誤
- 只看到舊版本就斷言「資料庫已經損壞」。
- 只升級二進位檔,沒有凍結寫入、保留 WAL/SHM 和可回滾副本。
- 把一次
integrity_check通過當成業務資料完全正確。 - 在疑似損壞檔案上直接 VACUUM 或覆蓋複製,破壞取證證據。
- 允許多個程序各自 checkpoint,卻沒有衝突和逾時監控。
- 只說「定期備份」,沒有定義備份一致性、RPO、RTO 和復原演練。
追問及應對
如果版本受影響但沒有發現異常,是否可以跳過升級?
不應跳過。應結合觸發條件評估短期風險,同時安排修復版本升級;「未觀察到異常」不能證明極窄時間窗的競態不存在。
PRAGMA integrity_check 通過後,為什麼還要做業務校驗?
它主要檢查資料庫結構和部分約束,不能驗證同步游標、領域不變量、遠端一致性或最近交易是否完整,所以需要應用層抽樣和副本比對。
多程序無法立即改造,臨時措施是什麼?
先統一 SQLite 版本和啟動參數,禁止不受控的主動 checkpoint,串行化寫交易並提高鎖衝突觀測;同時縮短灰度批次,保留可快速切換的唯讀備份,直到單一寫入者方案落地。