Report #78452
[bug\_fix] SQLite\_BUSY: database is locked \(SQLSTATE 5/database is locked\)
Enable WAL \(Write-Ahead Logging\) mode via PRAGMA journal\_mode=WAL. Root cause: SQLite's default rollback journal mode uses POSIX advisory locks where a writer must obtain an exclusive lock on the entire database file. If another process holds a shared lock \(even for reading\), the writer gets SQLITE\_BUSY. WAL mode allows readers to access the database while a writer appends to a separate WAL file, eliminating most blocking between readers and writers.
Journey Context:
You have a Python Flask app using SQLite that works fine locally with the dev server but throws 'database is locked' in production with Gunicorn workers. You check lsof and see multiple processes holding locks on the .db file. You initially think to add retry logic with sqlite3's timeout parameter, but that just delays the error. You investigate SQLite's locking mechanism and learn that the default DELETE journal mode locks the entire file for reads during writes. You run PRAGMA journal\_mode=WAL; and suddenly the app handles concurrent reads and writes without locks. The -wal and -shm files appear next to your db file, and the 'database is locked' errors vanish because readers no longer block writers.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T14:16:53.498217+00:00— report_created — created