Reputation: 178
My application consists of a number of threads (typically 5-10) and each is responsible for reading a value from an SQLite database, working on it for an amount of time and then writing a new value back to the database.
Each of the threads is running by itself without any synchronization.
My question is: Do I need to write the synchronization code myself or it is possible to interact with the SQLite C API in such a way that this gets taken care of for you. IE. If there is a transaction in progress to write a value and a different thread tries to write or read the same row, SQLite will block until it's okay to do so?
Upvotes: 1
Views: 2727
Reputation: 52344
If there is a transaction in progress to write a value and a different thread tries to write or read the same row, SQLite will block until it's okay to do so?
The easy way to do this is use mult-threaded mode, with one connection object per thread. Then threads can acquire a lock on the database with a BEGIN IMMEDIATE
transaction, and if you get a SQLITE_BUSY
error, the thread can either do something else for a while before trying again, or if you had set up a busy timeout ahead of time to a reasonable for your needs timeout, the thread will just sleep for up to that length of time trying to acquire the transaction lock periodically before giving up.
If you use serialized mode and a single connection for the entire program, you have to include all the logic and locking to make sure that only one particular thread can access the database when a transaction is active yourself. Much easier to use sqlite's native, well tested, support for that functionality.
Upvotes: 2
Reputation: 180181
Do I need to write the synchronization code myself or it is possible to interact with the SQLite C API in such a way that this gets taken care of for you.
The SQLite documentation covers this. In a nutshell, SQLite has three different threading models available:
single-thread, in which all internal mutexes are disabled, and the SQLite API cannot safely be used by multiple threads at the same time;
multi-thread, in which the library can safely be used concurrently by multiple threads, but database connections can be used only by a single thread at a time; and
serialized, in which multiple threads can use the API concurrently without restriction.
There is a built-in default selected at compile time (which is "serialized" mode in a standard build). A different mode can be selected during library initialization (sqlite3_config()
), and a per-connection thread mode can be specified when you open a new connection, except that single-thread mode cannot be overridden.
But note well that under all circumstances, SQLite provides a single transaction at a time per connection. Thus, you may need your own synchronization even in "serialized" mode.
If there is a transaction in progress to write a value and a different thread tries to write or read the same row, SQLite will block until it's okay to do so?
If an SQLite connection is in serialized mode and has autocommit enabled, then you're fine, in the sense that each statement will be executed in its own transaction, and different threads will not interfere with each other (but they may counteract each other). If a connection is instead in the weaker "multi-thread" mode then you must provide your own synchronization, so that different threads do not attempt to use the connection concurrently. If autocommit is disabled, then you will probably need to synchronize even in "serialized" mode to accommodate multiple threads using the same connection, else you will be unable to effectively control transaction boundaries and the contents of each transaction.
With respect to a single, established connection, there is no meaningful difference between "multi-thread" mode and "single-thread" mode.
Upvotes: 4