Actually, I inspected carefully the code and to avoid any deadlocks and make
the intentions very explicit, every time we're about to write we do:

Begin immediate transaction
Our updates
Commit transaction

Anytime we read we do

Begin transaction
read
rollback transaction (there was a mix of commit and rollback, but I made it
uniform by using rollback only)

I still can't find the hole in our code. More info: after the scenario is
done, any read in C (thus a begin/rollback) doesn't affect A, but _any_
write transaction (thus begin immediate/commit) results in SQLITE_BUSY.

Could this be related to this: in A, the database connection is created in
the main program, but is passed down to a dll that loads another dll that
uses the connection to do the writes. Maybe the dll should open its own
connection?

Normand



-----Original Message-----
From: sqlite-users-boun...@sqlite.org
[mailto:sqlite-users-boun...@sqlite.org] On Behalf Of Igor Tandetnik
Sent: October-29-13 6:41 PM
To: sqlite-users@sqlite.org
Subject: Re: [sqlite] Problem with SQLITE_BUSY

You haven't explained what the second connection in A is doing. My educated
guess is, the two connections enter into a deadlock. This is possible when
at least one connection starts as a reader and later attempts to write (the
other could be a straight writer). The scenario goes like this: the reader
acquires a SHARED lock and starts reading. 
Meanwhile, the writer is ready to write, so it gets a PENDING lock and waits
for readers to clear. But instead, the reader tries to start writing by
acquiring a RESERVED lock - which it cannot do for as long as the other
writer is active.

Once this deadlock happens, the only way to make progress is for one of the
two connections to roll back its transaction. One can avoid this scenario by
starting the transaction with BEGIN IMMEDIATE (or BEGIN
EXCLUSIVE) - this marks the transaction as a writer right away, by obtaining
a RESERVED (or EXCLUSIVE) lock from the start.

Igor Tandetnik

On 10/29/2013 6:26 PM, Normand Mongeau wrote:
> Hi,
>
>
>
> I have a situation where I always run into an SQLITE_BUSY error. It's 
> quite involved, here's the high picture:
>
>
>
> -3 processes (A, B and C) each have a connection to the same db. 
> Everybody has a busy handler set for 5 seconds.
>
>
>
> -1 of these processes (A) opens more than one connection, as it loads 
> a DLL that opens its own connection.
>
>
>
> -A needs to check for data at regular intervals, so every second it 
> does a begin transaction, read then commit transaction.
>
>
>
> -C deletes data within a transaction. Then it triggers about 400 
> transactions in B (it basically sends data to B via a TCP/IP layer, B 
> receives the data and writes in the DB).
>
>
>
> -A then sees that data has arrived, and does its own processing, 
> eventually recording some more data (always within a begin/write/commit).
>
>
>
> -After A is done, it goes back into its "check for data" at the same 
> regular interval.
>
>
>
> So far so good. I see the A's begin/read/commit succeed.
>
>
>
> As soon as I trigger another transaction in C (any transaction), A 
> gets the SQLITE_BUSY error, even though the transaction goes through 
> normally in C (i.e. begin transaction, write, commit transaction).
>
>
>
> Any ideas as to what's wrong in the above scenario? How do I avoid the 
> SQLITE_BUSY error? Is it possible to recover from that error? 
> (Apparently not. I close the B and C processes (proper shutdown) and A 
> still gets the error).
>
>
>
> Thanks,
>
>
>
> Normand
>


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

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

Reply via email to