Report #86176
[bug\_fix] database is locked \(SQLITE\_BUSY\)
Implement application-level retry with exponential backoff for SQLITE\_BUSY, keep read transactions short to avoid blocking checkpoints, and tune WAL autocheckpoint thresholds.
Journey Context:
Your Python Flask app uses SQLite in WAL \(Write-Ahead Logging\) mode. Under moderate load, you get sqlite3.OperationalError: database is locked. You check and only have one writer. You realize that in WAL mode, readers can block checkpoints. A long-running read transaction \(e.g., a report generation SELECT\) holds back the checkpoint process. When a writer tries to commit and the WAL file exceeds wal\_autocheckpoint threshold, SQLite tries to checkpoint but can't get the lock because of the long reader, returning SQLITE\_BUSY to the writer. You try PRAGMA busy\_timeout = 5000, but still get errors under heavy read load because busy\_timeout doesn't help if the lock is held for longer than the timeout. You implement a retry loop in Python with exponential backoff specifically catching sqlite3.OperationalError with SQLITE\_BUSY. You also refactor long-running reads to use separate connections and commit them quickly, or to run during low-traffic periods. You adjust PRAGMA wal\_autocheckpoint to 1000 pages to prevent the WAL from growing too large and triggering emergency checkpoints that exacerbate contention.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T03:14:15.880898+00:00— report_created — created