Thanks for the input Ned--I thought there had to be more going on.  

After reading about BEGIN TRANSACTION some more, it seems like some
times my retry strategy works (a reader gets SQLITE_BUSY because a
writer is holding an exclusive lock, in which case retrying the same
sqlite3_ call later in the reader would work--and does from what I've
seen).  But once the deadlock case is hit, one must abort/rollback as
you point out.  

Is there a way to detect the deadlock situation (will SQLite return
SQLITE_LOCKED), or would it be better to retry a couple of times and
then rollback?  

Is it best to bail out by closing the database handle, or calling
sqlite3_prepare16 on a "rollback" statement and trying to execute it?

Thanks again for your time.



-----Original Message-----
From: Ned Batchelder [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, November 30, 2005 11:54 AM
To: sqlite-users@sqlite.org
Subject: RE: [sqlite] Concurrency handling question

You can't simply loop on retrying the last sqlite3_* call.  You need to
rollback one of the transactions and retry the entire transaction.  Your
two threads are deadlocked because (roughly) each has acquired a lock
that the other needs.  One needs to release the locks it holds.  Rolling
back is the way to do that.

--Ned.
http://nedbatchelder.com
 

-----Original Message-----
From: Doug Nebeker [mailto:[EMAIL PROTECTED]
Sent: Wednesday, 30 November, 2005 11:04 AM
To: sqlite-users@sqlite.org
Subject: [sqlite] Concurrency handling question

I've written a C++ wrapper for SQLite which has been working great.
Lately though I've started getting what might be deadlocks when running
two threads against the same database.  One thread is a reader and the
other is a writer (at the moment, I'm getting 'database locked' errors,
but that's after many hours of failures so not sure where it started).
It's possible to have two or three readers and/or writers, but not more
than that.

Each thread has it's own database handle, however, I keep the database
handle open for many calls (where each 'call' opens a transaction,
executes SQL statements, then closes the transaction).

I've read about concurrency, and it sounds like the best way to work is
just to retry the last call if SQLITE_BUSY is ever returned, but that
doesn't seem to be working for me in this case.  I've stripped my main
processing loop down to make it concise (it is not completely correct
nor will it compile as shown, but it shows the flow).

Can anyone see what I'm doing wrong?  Is the fact that I keep the
database handle open between calls and between retries the problem?  If
the retry loops finally fails, sqlite3_finalize gets called,
sqlite3_close and then sqlite3_open16 to re-initialize the state.

Thanks in advance for any insight.

        do
        {
                long prepareLoopCount = 0;

PrepareLoop:
                if(SQLITE_BUSY == (res = sqlite3_prepare16(m_hDB,
nextStatement, -1, &pStmt, &tail)))
                {
                        if(prepareLoopCount++ < 200)
                        {
                                Sleep(300 ms);
                                goto PrepareLoop;
                        }
                }

                if((SQLITE_OK == res) && (NULL != pStmt)) 
                {
                        long stepLoopCount = 0;
StepLoop:
                        res = sqlite3_step(pStmt);
                        if(SQLITE_BUSY == res)
                        {
                                if(stepLoopCount++ < 200)
                                {
                                        Sleep(300 ms);
                                        goto StepLoop;
                                }
                        }
                        else do other processing like fetching the
rows....

                }

                if(NULL != pStmt)
                {
                        sqlite3_finalize(pStmt);
                        pStmt = NULL;
                }
        }
        while(NULL != nextStatement)


To find out more about Reuters visit www.about.reuters.com

Any views expressed in this message are those of the individual sender,
except where the sender specifically states them to be the views of
Reuters Ltd.




To find out more about Reuters visit www.about.reuters.com

Any views expressed in this message are those of the individual sender, except 
where the sender specifically states them to be the views of Reuters Ltd.

Reply via email to