Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`sqlite3` ignores `sqlite3_busy_timeout`?

Tags:

c++

c

sqlite

I use sqlite3 in multiple threads application (it is compiled with SQLITE_THREADSAFE=2). In watch window I see that sqlite->busyTimeout == 600000, i. e. that it is supposed to have 10 minutes timeout. However, sqlite3_step returns SQLITE_BUSY obvoiusly faster than after 10 minutes (it returns instantly actually, like if I never called sqlite3_busy_timeout). What is the reason that sqlite3 ignores timeout and return error instantly?

like image 871
Vitalii Avatar asked Feb 11 '23 01:02

Vitalii


1 Answers

One possibility: SQLite ignores the timeout when it detects a deadlock.

The scenario is as follows. Transaction A starts as a reader, and later attempts to perform a write. Transaction B is a writer (either started that way, or started as a reader and promoted to a writer first). B holds a RESERVED lock, waiting for readers to clear so it can start writing. A holds a SHARED lock (it's a reader) and tries to acquire RESERVED lock (so it can start writing). For description of various lock types, see http://sqlite.org/lockingv3.html

The only way to make progress in this situation is for one of the transactions to roll back. No amount of waiting will help, so when SQLite detects this situation, it doesn't honor the busy timeout.

There are two ways to avoid the possibility of a deadlock:

  1. Switch to WAL mode - it allows one writer to co-exist with multiple readers.
  2. Use BEGIN IMMEDIATE to start a transaction that may eventually need to write - this way, it starts as a writer right away. This of course reduces the potential concurrency in the system, as the price of avoiding deadlocks.
like image 118
Igor Tandetnik Avatar answered Feb 13 '23 03:02

Igor Tandetnik