Report #65606
[bug\_fix] database is locked \(SQLITE\_BUSY\)
Enable WAL \(Write-Ahead Logging\) mode by executing PRAGMA journal\_mode=WAL immediately after opening the database, which allows concurrent readers and a single writer without locking conflicts; alternatively, if WAL cannot be used, set PRAGMA busy\_timeout=5000 to make the writer wait rather than fail immediately.
Journey Context:
A developer builds a Python Flask app using SQLite for a small internal tool. The app uses threading for background tasks. Soon, they see sqlite3.OperationalError: database is locked errors. The scenario: Thread A starts a SELECT statement, which acquires a shared lock on the database file \(in the default DELETE journal mode\). Thread B tries to write an INSERT, which needs a reserved lock. Because Thread A's shared lock is held until the SELECT finishes \(or transaction commits\), Thread B cannot proceed. In DELETE mode, the writer fails immediately with SQLITE\_BUSY if the lock is unavailable. The developer tries closing connections immediately after use, but the race condition persists. They research and discover WAL mode. They add a line to their connection setup: cursor.execute\('PRAGMA journal\_mode=WAL'\). Now, when Thread A reads, it can read from the main database or the -wal file while Thread B appends to the -wal file. The readers and writer no longer block each other, and the "database is locked" errors cease. They also learn that if they cannot use WAL \(e.g., on a network filesystem\), they should set PRAGMA busy\_timeout=5000 so SQLite retries the lock for 5 seconds before returning BUSY.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T16:36:15.366848+00:00— report_created — created