SQLite (with WAL) doesn't do fsync on each commit under default settings | Hacker News
https://www.sqlite.org/pragma.html#pragma_synchronous
📌 Summary:
本文主要探討 SQLite 在啟用 Write-Ahead Logging(WAL)模式時,
PRAGMA synchronous 設定與 fsync 行為之間的關係,以及不同作業系統和編譯環境下的預設差異。SQLite 的 WAL 模式能提升寫入效能,但在預設的 synchronous=NORMAL 狀態下,交易提交並不會在每次操作時都呼叫 fsync,導致系統崩潰或斷電時可能回滾部分已提交交易。相對地,設定為 FULL 會增加交易耐久性,確保每次提交後都執行同步操作,降低資料遺失風險。文中以 macOS 內建 sqlite 與 Homebrew 版本為例,指出兩者在此設定上的不同,且編譯階段的宏定義(SQLITE_DEFAULT_SYNCHRONOUS 與 SQLITE_DEFAULT_WAL_SYNCHRONOUS)通常預設為 FULL,但發行版或包裝方式可能改變預設,產生行為差異。文章並輔以 Hacker News 社羣討論,引伸對於資料庫耐久性預設的安全性疑慮、不同檔案系統、fsync 性能影響以及應用場景需求的範例分析,提醒使用者必須理解底層配置與預設差異,並根據實務需求調整參數,而非盲目依賴默認設定。 🎯 Key Points:
→ 🔧 SQLite WAL 模式與同步機制:
★ WAL 模式預設 journal mode 為 WAL,優化寫入效能;
★
PRAGMA synchronous 控制 fsync 行為,影響資料耐久性與系統穩定性; ★
synchronous=NORMAL(數值1)表示不對每次提交呼叫 fsync,僅於檢查點前後同步,可能導致部分交易因斷電丟失; ★
synchronous=FULL(數值2)確保每次交易提交後同步 WAL 檔案,提升耐久性; → 💻 系統與編譯差異:
★ macOS 內建 sqlite3 版本默認為 WAL 模式下同步為
NORMAL; ★ Homebrew 版本默認為
FULL,顯示編譯宏設定差異; ★ 編譯預設宏
SQLITE_DEFAULT_SYNCHRONOUS 和 SQLITE_DEFAULT_WAL_SYNCHRONOUS 皆預設值為 FULL,但發行包裝可能自行調整; ★ 不同 Linux 發行版 Docker 映像大多維持
FULL 為預設; → 🗣 社羣討論與應用影響:
★ 斷電後資料持久性及交易一致性成為關鍵,尤其金融或加密貨幣等重要場景;
★ 許多應用為提升效能採用
NORMAL,但犧牲了部分交易的耐久保障; ★ fsync 操作較耗費資源且影響性能,故預設採折衷策略;
★ 使用者應明確檢視並調整關鍵設定以符合應用需求,避免默認帶來資料遺失風險;
★ 針對 Apple 平臺 fsync 行為存在特殊處理,如使用 F_FULLFSYNC 或 F_BARRIERFSYNC ;
★ SQLite 不同默認設置的不透明性亦可能導致開發者誤解資料庫的安全保證;
🔖 Keywords:
#SQLite #WAL模式 #PRAGMA_synchronous #fsync #資料耐久性
