Small. Fast. Reliable.
Choose any three.

SQLite C Interface

Register A Callback To Handle SQLITE_BUSY Errors

int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);

This routine sets a callback function that might be invoked whenever an attempt is made to open a database table that another thread or process has locked.

If the busy callback is NULL, then SQLITE_BUSY or SQLITE_IOERR_BLOCKED is returned immediately upon encountering the lock. If the busy callback is not NULL, then the callback will be invoked with two arguments.

The first argument to the handler is a copy of the void* pointer which is the third argument to sqlite3_busy_handler(). The second argument to the handler callback is the number of times that the busy handler has been invoked for this locking event. If the busy callback returns 0, then no additional attempts are made to access the database and SQLITE_BUSY or SQLITE_IOERR_BLOCKED is returned. If the callback returns non-zero, then another attempt is made to open the database for reading and the cycle repeats.

The presence of a busy handler does not guarantee that it will be invoked when there is lock contention. If SQLite determines that invoking the busy handler could result in a deadlock, it will go ahead and return SQLITE_BUSY or SQLITE_IOERR_BLOCKED instead of invoking the busy handler. Consider a scenario where one process is holding a read lock that it is trying to promote to a reserved lock and a second process is holding a reserved lock that it is trying to promote to an exclusive lock. The first process cannot proceed because it is blocked by the second and the second process cannot proceed because it is blocked by the first. If both processes invoke the busy handlers, neither will make any progress. Therefore, SQLite returns SQLITE_BUSY for the first process, hoping that this will induce the first process to release its read lock and allow the second process to proceed.

The default busy callback is NULL.

The SQLITE_BUSY error is converted to SQLITE_IOERR_BLOCKED when SQLite is in the middle of a large transaction where all the changes will not fit into the in-memory cache. SQLite will already hold a RESERVED lock on the database file, but it needs to promote this lock to EXCLUSIVE so that it can spill cache pages into the database file without harm to concurrent readers. If it is unable to promote the lock, then the in-memory cache will be left in an inconsistent state and so the error code is promoted from the relatively benign SQLITE_BUSY to the more severe SQLITE_IOERR_BLOCKED. This error code promotion forces an automatic rollback of the changes. See the CorruptionFollowingBusyError wiki page for a discussion of why this is important.

There can only be a single busy handler defined for each database connection. Setting a new busy handler clears any previously set handler. Note that calling sqlite3_busy_timeout() will also set or clear the busy handler.

The busy callback should not take any actions which modify the database connection that invoked the busy handler. Any such actions result in undefined behavior.

Invariants:

H12311 The sqlite3_busy_handler(D,C,A) function shall replace busy callback in the database connection D with a new a new busy handler C and application data pointer A.
H12312 Newly created database connections shall have a busy handler of NULL.
H12314 When two or more database connections share a common cache, the busy handler for the database connection currently using the cache shall be invoked when the cache encounters a lock.
H12316 If a busy handler callback returns zero, then the SQLite interface that provoked the locking event shall return SQLITE_BUSY.
H12318 SQLite shall invokes the busy handler with two arguments which are a copy of the pointer supplied by the 3rd parameter to sqlite3_busy_handler() and a count of the number of prior invocations of the busy handler for the same locking event.

Assumptions:

A12319 A busy handler must not close the database connection or prepared statement that invoked the busy handler.

See also lists of Objects, Constants, and Functions.


This page last modified 2008/12/09 18:44:04 UTC