科技 · 實用指南
SQLite 顯示 database is locked?先找出寫入者與交易再調 busy_timeout
把 SQLITE_BUSY 當成鎖定時間線問題:先確認寫入者、連線、交易階段與日誌模式,再決定逾時、WAL 或重試。

SQLite 的“database is locked”只說明所需鎖不可用,并不会告诉你哪個程序、連線或交易造成衝突。先提高 busy_timeout,可能只是把長交易藏起來。
建立連線時間线,区分可等待的短暫争用與 DEFERRED 讀轉寫升級,再用带上限的重试驗证最小修複。
先冻结失败現场
保存完整異常、数字错误码、SQL 操作、程序、執行緒、連線標識和時間;同時記录失败發生在 BEGIN、首次寫入、COMMIT、检查点、恢複還是關閉阶段。
不要刪除 -wal 或 -shm 文件,也不要只複制主資料庫;列出所有可能打開该路徑的應用、終端、迁移、後台任務和编辑器。
建立逐連線交易時間线
記录每個連線的打開、BEGIN、首次讀取、首次寫入、提交或回滚、语句结束和連線關閉,并附上 journal_mode、timeout 和交易模式。
如果寫交易内包含網络、文件或人工等待,把這些慢操作移出交易,再考慮重试参数。
区分等待與交易升級失败
SQLite 可同時有多個讀交易,但只能有一個寫交易。DEFERRED 交易先讀後寫時需要升級;另一個寫入者存在時,首次寫入可能直接返回 SQLITE_BUSY。
只有在工作单元確定会寫且應在開始時取得寫入槽時才用 BEGIN IMMEDIATE;它仍可能因已有寫入者而失败。
只把 busy_timeout 用于短暫争用
超時只规定等待多久,不会替你提交別的連線、關閉泄漏游標或缩短交易。每個連線都應量測等待時長、重试次数和鎖持有者。
仅重试幂等操作或副作用受控的完整交易;加入抖動和硬上限,并在最終失败時保留原時間线。
把 WAL 当并發模式,不是万能解鎖
WAL 通常允许讀者與寫入者并行,但仍只有一個寫入者;獨占模式、清理或恢複期間仍可能出現 SQLITE_BUSY。
啟用前確认所有程序和文件系统兼容,并安全處理資料庫與 WAL 状態;啟用後继續监控检查点和寫交易時長。
應用最小修複并複驗
確定性關閉语句與連線,保证每条退出路徑提交或回滚,缩短寫交易并串行化不可避免的寫入者。
用連線標識和计時重放原失败操作,確认没有重複寫入且超出预算会明確失败;持續高并發寫入可能需要客户机/服務器資料庫。
