跨區 Mac mini M4 並聯叢集若把 SQLite WAL 放在共享卷,檢查點與併發建置常先於 CPU 造成 IO 尾延遲抖動;再疊建置鎖與重試,磁碟水位易快速衝紅。
為何共享卷上的 WAL 特別「咬」IO
給多臺專用 Mac CI/快取團隊:儲存拓樸 × SQLite邊界、可貼 PRAGMA/journal_mode、佇列並發上限與 1TB/2TB 水位驗收。延伸:Nomad 建置鎖、rsync 矩陣、watchman 水位、Mosh/flock。
- WAL 寫入放大:
-wal/-shm與主庫同路徑;網路卷上單次提交易變多 round-trip。 - 檢查點共振:checkpoint 落頁時若同卷還有大檔建置,尾延遲拉長。
- 鎖與排程:多程序同庫時
busy_timeout與重試未對齊會堆佇列。
決策矩陣:儲存拓樸 × SQLite 使用方式
| 拓樸/模式 | 最適場景 | 取捨與風險 |
|---|---|---|
| 每節點本機 APFS + WAL | CI 狀態庫、Bazel/Gradle 遠端快取元資料、單機工具鏈索引。 | 延遲最穩;需另設同步或集中報表匯流。 |
| 單寫者網路卷 + WAL | 過渡期集中快取(僅一個寫入服務);其餘節點唯讀或拉取。 | 必須搭配建置鎖或單一服務 PID;檢查點仍會與大檔 IO 互搶。 |
| 多寫者共享卷 + 同一 .db | 不建議作為設計目標。 | 鎖競態、損毀風險與不可預測尾延遲;應遷回單寫或改用伺服器型資料庫。 |
| 本機 WAL + rsync/製品樹 | 並聯池各自寫本機庫,再以單一 promote 扇出產物(與既有 runbook 一致)。 | 與 製品庫/DNS 矩陣 同一敘事。 |
預設策略:庫放本機;非共享卷不可則單寫入者並遵守下方併發區間。
可執行 PRAGMA 與 journal_mode 建議
本機 SSD上一次性設好日誌模式與同步;網路卷先確認鎖語意與風險再套用。
可存成 init_ci_cache_db.sh,以 CI_SQLITE_PATH 帶入庫路徑:
#!/usr/bin/env bash
set -euo pipefail
DB="${CI_SQLITE_PATH:?}"
sqlite3 "$DB" <<'SQL'
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL; -- 需要更嚴格持久化時改 FULL
PRAGMA wal_autocheckpoint=1000;
PRAGMA busy_timeout=8000;
PRAGMA foreign_keys=ON;
PRAGMA cache_size=-64000; -- 約 64MiB page cache,視記憶體調整
SELECT sqlite_compile_option_used('THREADSAFE');
PRAGMA journal_mode; -- 應回 wal
PRAGMA user_version;
SQL
若 journal_mode=WAL 退回 delete 或失敗,應遷移庫而非加併發。維護窗、無其他寫入時可做 wal_checkpoint(TRUNCATE),避免 WAL 撐爆水位。
佇列並發上限與 IO 抖動
以 iostat、尾延遲與 busy 校準下列起點值:
- 共享卷同一寫入樹:活躍寫入建置 1~2(1TB 偏 1、2TB 試 2);先降佇列勿先鬆
synchronous。 - promote/golden:
max_parallel = 1與 flock 擇一為權威。 - 本機每庫:「同檔多寫」設硬上限,避免單檔熱點。
P99 升、WAL 久大:先減併發與寫放大,再談升配。
建置鎖與 WAL 生命週期
遷移、checkpoint、大量 vacuum 前用 flock;鎖檔放本機。排程已串列則腳本鎖短逾時、快失敗。
LOCK_FILE="/var/tmp/ci-sqlite-maint.lock" flock -w 30 "$LOCK_FILE" sqlite3 "/Volumes/shared/ci_meta.db" \ "PRAGMA wal_checkpoint(PASSIVE);"
1TB/2TB 磁碟水位驗收清單(併入 SQLite)
| 卷宗使用率區間 | 1TB 節點(並聯工作機) | 2TB 節點(並聯工作機) | SQLite/佇列動作 |
|---|---|---|---|
| < 70% | 維持預設併發;每週抽樣 PRAGMA wal_checkpoint(PASSIVE) 與 WAL 檔大小趨勢。 |
可保留較長 WAL 窗;仍監控 -wal 與快照空間。 |
正常 dispatch;記錄 busy 與尾延遲基線。 |
| 70%–80% | 黃燈:共享卷寫入併發降到 1;排程延後非關鍵 job。 | 黃燈:收斂快取輪替週期;預約維護窗做 TRUNCATE checkpoint。 | 調低自動檢查點間隔或改由離峰手動 checkpoint。 |
| > 90% | 紅燈:暫停新寫入建置與大型同步;先釋放 APFS 快照、WAL 殘留與製品暫存。 | 硬停寫庫與 promote,直至利用率低於 85% 並完成驗收項勾選。 | |
1~2
共享卷建議同時寫入建置上限(起點值)
80%
黃燈:佇列與 WAL 趨勢併入值班儀表板
90%
紅燈:硬停線,先清庫與卷再恢復
與排程、製品扇出的銜接
製品樹仍依單一 promote 與 rsync profile;把本文水位併入 rsync 矩陣、Nomad 建置鎖 同份 runbook。
FAQ
SMB 上多台 CLI 共寫 WAL? 不建議;改一機一庫或單寫服務。
synchronous=OFF? 可降延遲但損毀面大;僅可重建快取庫並留風險紀錄。
checkpoint 頻率? 依 WAL 增速;共享卷少 TRUNCATE,離峰 PASSIVE+降併發。
本文為工程實務建議。 SQLite 版本與建置鏈請以官方文件與你方合規為準;對共享卷執行刪除或
checkpoint(TRUNCATE) 前務必確認無其他寫入連線。