views:

715

answers:

2

Hello,

I'm running a number of threads which each attempt to perform INSERTS to one SQLite database. Each thread creates it's own connection to the DB. They each create a command, open a Transaction perform some INSERTS and then close the transaction. It seems that the second thread to attempt anything gets the following SQLiteException: The database file is locked. I have tried unwrapping the INSERTS from the transaction as well as narrowing the scope of INSERTS contained within each commit with no real effect; subsequent access to the db file raises the same exception.

Any thoughts? I'm stumped and I'm not sure where to look next...

+1  A: 

Update your insertion code so that if it encounters an exception indicating database lock, it waits a bit and tries again. Increase the wait time by random increments each time (the "random backoff" algorithm). This should allow the threads to each grab the global write lock. Performance will be poor, but the code should work without significant modification.

However, SQLite is not appropriate for highly-concurrent modification. You have two permanent solutions:

  • Move to a "real" database, such as PostgreSQL or MySQL
  • Serialize all your database modifications through one thread, to avoid SQLite's modifications.
John Millikin
cool.. i considered this, but does this actually guarantee that it will never lock? i feel as tho it will just take longer (in other words lower the chances of) to lock up again. im operating on a very large amount of data and the process will take hours if not days...
sweeney
also when you say highly concurrent, what exactly do you mean? my app will run between 1 and 20 of these threads under normal usage. is this considered high concurrency?
sweeney
If serialized to one thread, it won't have locking errors. Alternatively, if you retry on locking errors, they won't prevent the program from completing. SQLite is not designed for concurrency, but it can be made to work for a couple threads that don't INSERT often. If you've got 3+ threads that all insert, you should use a different database.
John Millikin
well increasing the db timeout seems to have done the trick. if that proves unreliable upon further testing i'll try serializing to one thread, as you've suggested. thanks for the advice!just in case anyone is interested, the test i ran was against 6 threads with occasional INSERTS and it seems to run fine.
sweeney
+1  A: 

Two things to check:

1) Confirmed that your version of SQLite was compiled with THREAD support

2) Confirm that you are not opening the database EXCLUSIVE

Noah