When a transaction cannot lock the database, because it is already
locked by another one, SQLite by default throws an error:
database is locked. This behavior is usually not appropriate when
concurrent access is needed, typically when multiple processes write to
the same database.
sqliteSetBusyHandler() lets you set a timeout or a handler for these
events. When setting a timeout, SQLite will try the transaction multiple
times within this timeout. To set a timeout, pass an integer scalar to
Another way to set a timeout is to use a
PRAGMA, e.g. the SQL query
sets the busy timeout to three seconds.
A SQLiteConnection object.
Specifies what to do when the database is locked by another transaction. It can be:
Note that SQLite currently does not schedule concurrent transactions fairly. If multiple transactions are waiting on the same database, any one of them can be granted access next. Moreover, SQLite does not currently ensure that access is granted as soon as the database is available. Make sure that you set the busy timeout to a high enough value for applications with high concurrency and many writes.
handler argument is a function, then it is used as a callback
function. When the database is locked, this will be called with a single
integer, which is the number of calls for same locking event. The
callback function must return an integer scalar. If it returns
then no additional attempts are made to access the database, and
an error is thrown. Otherwise another attempt is made to access the
database and the cycle repeats.
Handler callbacks are useful for debugging concurrent behavior, or to implement a more sophisticated busy algorithm. The latter is currently considered experimental in RSQLite. If the callback function fails, then RSQLite will print a warning, and the transaction is aborted with a "database is locked" error.
Note that every database connection has its own busy timeout or handler function.
sqliteSetBusyHandler() on a connection that is not connected
is an error.