Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

SQLite 顯示 database is locked?先找出寫入者與交易再調 busy_timeout

把 SQLITE_BUSY 當成鎖定時間線問題:先確認寫入者、連線、交易階段與日誌模式,再決定逾時、WAL 或重試。

原创示意圖:一個 SQLite 寫入者持鎖,另一個連線在有界计時器旁等待。
原创示意:先找出寫入者和鎖区間,再提高超時。 Watch at Ease

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 状態;啟用後继續监控检查点和寫交易時長。

應用最小修複并複驗

確定性關閉语句與連線,保证每条退出路徑提交或回滚,缩短寫交易并串行化不可避免的寫入者。

用連線標識和计時重放原失败操作,確认没有重複寫入且超出预算会明確失败;持續高并發寫入可能需要客户机/服務器資料庫。

原创概念插画:讀交易面對单寫入者門槛,并分出 WAL 與有限等待路徑。
原创概念插画:分類鎖路徑後再選择 IMMEDIATE、WAL 或有限等待。 Watch at Ease