On some Unix-like systems, SQLite may be configured to use POSIX blocking locks by:
Blocking locks may be advantageous as (a) waiting database clients do not need to continuously poll the database lock, and (b) using blocking locks facilitates transfer of OS priority between processes when a high priority process is blocked by a lower priority one.
Only read/write clients use blocking locks. Clients that have read-only access to the *-shm file nevery use blocking locks.
Threads or processes that access a single database at a time never deadlock as a result of blocking database locks. But it is of course possible for threads that lock multiple databases simultaneously to do so. In most cases the OS will detect the deadlock and return an error.
Wal database "recovery" is a process required when the number of connected database clients changes from zero to one. In this case, a client is considered to connect to the database when it first reads data from it. Before recovery commences, an exclusive WRITER lock is taken.
Without blocking locks, if two clients attempt recovery simultaneously, one fails to obtain the WRITER lock and either invokes the busy-handler callback or returns SQLITE_BUSY to the user. With blocking locks configured, the second client blocks on the WRITER lock.
Usually, read-only are not blocked by any other database clients, so they have no need of blocking locks.
If a read-only transaction is being opened on a snapshot, the CHECKPOINTER lock is required briefly as part of opening the transaction (to check that a checkpointer is not currently overwriting the snapshot being opened). A blocking lock is used to obtain the CHECKPOINTER lock in this case. A snapshot opener may therefore block on and transfer priority to a checkpointer in some cases.
A database writer must obtain the exclusive WRITER lock. It uses a blocking lock to do so if any of the following are true:
In other words, in all cases except when an open read-transaction is upgraded to a write-transaction. In that case a non-blocking lock is used.
Database checkpointers takes the following locks, in order:
All of the above use blocking locks.
With blocking locks configured, the only cases in which clients should see an SQLITE_BUSY error are:
In all other cases the blocking locks implementation should prevent clients from having to handle SQLITE_BUSY errors and facilitate appropriate transfer of priorities between competing clients.
Clients that lock multiple databases simultaneously must be wary of deadlock.