"Edzard Pasma" <edz...@volcanomail.com> writes:
> --- nikol...@rath.org wrote:
>> "Igor Tandetnik" <itandet...@mvps.org> writes:
>>> Nikolaus Rath <nikol...@rath.org> wrote:
>>>> I am accessing the same database from different threads. Each
>>>> thread
>>>> has its own connection. I have set the busy timeout for each
>>>> connection to 5000 milliseconds.
>>>>
>>>> However, in some testcases I still get SQLITE_BUSY errors from
>>>> sqlite3_step. Moreover, the whole testcases run in much less than
>>>> 5
>>>> seconds, to apparently sqlite does not even try to wait for the
>>>> lock
>>>> to disappear.
>>>
>>> You are getting a deadlock. The scenario goes like this: thread A
>>> runs a
>>> transaction that starts as a reader (with a SELECT statement) but
>>> later
>>> becomes a writer (by executing INSERT, UPDATE or DELETE). Thread B
>>> also
>>> runs a transaction like this, or a simple writer transaction. Then
>>> the
>>> following sequence of events occurs:
>>>
>>> 1. Thread A starts as reader and takes a shared lock
>>> 2. Thread B starts as writer, takes a pending lock and waits for
>>>    readers
>>> to clear.
>>> 3. Thread A tries to become a writer and promote its lock to
>>>    reserved,
>>> but can't because there's already a writer on the database.
>>>
>>> The two threads deadlock. No amount of waiting by either thread
>>> would
>>> get them out of the impasse: the only way out is for one of the
>>> threads
>>> to roll back its transaction and start from scratch. When SQLite
>>> detects
>>> this situation, it returns SQLITE_BUSY immediately, without calling
>>> the
>>> busy handler (because, again, waiting won't help any).
>>>
>>> To avoid the possibility of a deadlock, start your
>>> reader-turning-writer
>>> transactions with BEGIN IMMEDIATE (this essentially makes the 
>>> transaction a writer right away).
>>
>> Ah, I see. I expected that a deadlock would actually result in both
>> threads hanging forever, rather than SQLite detecting it and
>> abandoning
>> immediately. The later is of course even better once you know about
>> it.
>> Thanks for the explanations! I should be able to fix my problem
>> now..
>
> Hi,
>
> Just in case it appears difficult to fix, I like to suggest to try
> using shared cache mode. The shared cache locking model does not have
> this particular deadlock situation. I'm assuming that the database is
> accessed from within a single process only.

Thanks for the idea. But after reading
http://www.sqlite.org/sharedcache.html it seems to me that to avoid the
above deadlock, I would not only need to enable shared cache mode but
also read-uncommitted. Is that right?

I'm hesitating a bit to do that, because I'm not sure what the
"[read-uncommited] can lead to inconsistent query results" phrase on the
above page may imply.

Best,

   -Nikolaus

-- 
 »Time flies like an arrow, fruit flies like a Banana.«

  PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6  02CF A9AD B7F8 AE4E 425C

_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to