I just want to add another hint that I learned yesterday:

when sqlite3_step() returns SQLITE_LOCKED be aware
that sqlite3_reset() will most likely also return
SQLITE_LOCKED and thus it is necessary to repeat calling
it until it returns SQLITE_OK.

Maybe it would be agood idea to have these kind of
info somewhere bundled in the sqlite docs?
I found it sometimes difficult to get such issues
extracted or collected from the sqlite pages, resulting
in a lot of try and error loops and generating traffic
on the mailing list... :-)

Marcus

>
> On Mar 6, 2009, at 2:53 AM, Hynes, Tom wrote:
>
>> Dan,
>>
>> I am a little confused now about how to treat a SQLITE_LOCKED
>> error.  Is this to be treated the same as SQLITE_BUSY (i.e. can
>> retry, unless an explicit transaction is in effect and the statement
>> is not a COMMIT, in which case should roll back), or should it be
>> treated differently?  If the latter, should it generally be handled
>> like most other db errors (e.g. SQLITE_CONSTRAINT, SQLITE_CANTOPEN,
>> etc.), or is there some specific error handling for SQLITE_LOCKED
>> that is recommended?
>
> Usually when sqlite3_step() returns something other than SQLITE_ROW, the
> statement needs to be reset (sqlite3_reset()) before execution
> can be re-attempted. However, SQLITE_BUSY errors are an exception.
> After SQLITE_BUSY is returned, you can call sqlite3_step() again
> immediately.
> This I either didn't know, or forgot.
>
> An SQLITE_LOCKED error means there is something preventing execution
> within the same process. For example a lock on a shared-cache table.
> For some applications, for example if another thread may release the
> lock shortly, it may be appropriate to retry the query. In other apps,
> for example single-threaded apps, it may not.
>
> To retry a query that has failed with an SQLITE_LOCKED error, you need
> to reset the statement before trying sqlite3_step() again.
>
> Dan.
>
>
>
>
>> Thanks,
>>
>> Tom
>>
>> -----Original Message-----
>> From: sqlite-users-boun...@sqlite.org
>> [mailto:sqlite-users-boun...@sqlite.org
>> ] On Behalf Of Dan
>> Sent: Thursday, March 05, 2009 12:38 PM
>> To: General Discussion of SQLite Database
>> Subject: Re: [sqlite] shared cache and SQLITE_MISUSE on sqlite3_step()
>>
>>
>> On Mar 6, 2009, at 12:22 AM, Marcus Grimm wrote:
>>
>>> Dan,
>>>
>>> I'm not sure what you mean by technically the SQLITE_BUSY is
>>> also wrong. In the test program I get the SQLITE_BUSY quite
>>> often and by retrying the sqlite3_step() it will sooner or
>>> later succeed.
>>
>> Huh. My mistake.
>>
>>
>>
>>> Thanks for confirming that it may happend only for the
>>> first call to sqlite3_step(). This is an important point and
>>> it makes it in fact easy to workaround.
>>> I've changed my test application accordingly and now it can
>>> run endless, I even increased now to 10 reader threads and 2 writer
>>> threads in
>>> parallel without making sqlite particular nervous. Wonderful... :-)
>>>
>>> Thanks again
>>>
>>> Marcus
>>>
>>> Dan wrote:
>>>> On Mar 5, 2009, at 11:14 PM, Marcus Grimm wrote:
>>>>
>>>>> Hi Dan,
>>>>>
>>>>> thank you!
>>>>>
>>>>> Yes! I was not aware that it is wrong to redo a step
>>>>> when it previously returned the LOCKED state.
>>>>> That was the reason for the (correct) MISSUSE return on
>>>>> the 2nd attempt.
>>>>>
>>>>> I think this is the main difference in my case between
>>>>> shared cache on/off: Without shared cache I never
>>>>> get this lock state and it just does the BUSY handling correctly.
>>>>
>>>> Technically the SQLITE_BUSY handling is also wrong, for the
>>>> same reasons. But it's harder to hit a real SQLITE_BUSY than it
>>>> is to hit an SQLITE_LOCKED in shared-cache mode.
>>>>
>>>>> I'll change my locking handling accordingly, seems to be a problem
>>>>> of the very first step after a prepare, so that's should to be easy
>>>>> to reset...
>>>>
>>>> That's correct. An SQLITE_LOCKED or SQLITE_BUSY may only occur
>>>> on the first call to sqlite3_step().
>>>>
>>>> Dan.
>>>>
>>>>
>>>>
>>>>> Thanks again for your feedback
>>>>>
>>>>> Marcus
>>>>>
>>>>> Dan wrote:
>>>>>> On Mar 5, 2009, at 9:57 PM, Marcus Grimm wrote:
>>>>>>
>>>>>>> Hi again,
>>>>>>>
>>>>>>> I did a little test program that simulates the multi threading
>>>>>>> issue to understand better why I get a MISSUSE error even
>>>>>>> when sqlite_prepare returns no error.
>>>>>>> The test program will printout some errors on the console
>>>>>>> and exits in that case. If I don't use the shared cache it
>>>>>>> runs endless without any problem.
>>>>>>>
>>>>>>> The code is to long to be placed here, but I would be very happy
>>>>>>> if somebody could take a look. I've put it on a web server to
>>>>>>> download:
>>>>>>>
>>>>>>> http://www.exomio.de/sqlitethreadtest.c
>>>>>>>
>>>>>>> I'm using MS Visual Studio 2008, the program is started within a
>>>>>>> dosbox to see the error output. Using it on my dual core PC
>>>>>>> it allmost immediately stops with the missuse error, ....but why?
>>>>>>   do
>>>>>>   {
>>>>>>       rc = sqlite3_step(hs);
>>>>>>
>>>>>>       if( (rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED) )
>>>>>>       {
>>>>>>           Sleep(SQLTM_TIME);
>>>>>>
>>>>>>           n++;
>>>>>>       }
>>>>>>   }while( (n < SQLTM_COUNT) && ((rc == SQLITE_BUSY) || (rc ==
>>>>>> SQLITE_LOCKED)));
>>>>>>
>>>>>> If sqlite3_step() returns SQLITE_BUSY or SQLITE_LOCKED, you need
>>>>>> to
>>>>>> reset the statement before trying the sqlite3_step() again.
>>>>>>
>>>>>> Dan.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> Thanks you
>>>>>>>
>>>>>>> kind regards
>>>>>>>
>>>>>>> Marcus Grimm
>>>>>>>
>>>>>>> Marcus Grimm wrote:
>>>>>>>> Hi Ken,
>>>>>>>>
>>>>>>>> yes, I do check the return values also for the
>>>>>>>> sqlite3_prepare_v2 call. This is allways
>>>>>>>> successful, the first sqlite_step call right after
>>>>>>>> this one returns the magic MISSUSE.
>>>>>>>>
>>>>>>>> Yes, I also tried to call sqlite_reset right
>>>>>>>> after this first error and in this case
>>>>>>>> sqlite_reset return the LOCK state. I didn't
>>>>>>>> yet go on to handle this...
>>>>>>>>
>>>>>>>> I can't post the code of the original implementation here,
>>>>>>>> but also for my debugging and tests I'll produce
>>>>>>>> a simplified test application. Just to see if that
>>>>>>>> can be used to reproduce the effect. If that one runs
>>>>>>>> without any problem, it's my fault, if not: I'll post
>>>>>>>> it here for further discussions... ;)
>>>>>>>>
>>>>>>>> Thanks for your feedback
>>>>>>>>
>>>>>>>> Marcus
>>>>>>>>
>>>>>>>>
>>>>>>>>> Marcus,
>>>>>>>>>
>>>>>>>>> I'm not sure if this will help or not...
>>>>>>>>>
>>>>>>>>> But I noticed your sample code does not test the return value
>>>>>>>>> from
>>>>>>>>> the
>>>>>>>>> sqlite3_prepare_v2 call. Could the code be entering the do
>>>>>>>>> loop
>>>>>>>>> when an
>>>>>>>>> error was returned from prepare?
>>>>>>>>>
>>>>>>>>> Just an idea.
>>>>>>>>>
>>>>>>>>> Have you tried the reset call as DRH had suggested?
>>>>>>>>> Your prior post indicated you had more code and another loop.
>>>>>>>>> Can
>>>>>>>>> you post
>>>>>>>>> the full code for both loops?
>>>>>>>>>
>>>>>>>>> HTH
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --- On Wed, 3/4/09, Marcus Grimm <mgr...@medcom-online.de>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> From: Marcus Grimm <mgr...@medcom-online.de>
>>>>>>>>>> Subject: Re: [sqlite] shared cache and SQLITE_MISUSE on
>>>>>>>>>> sqlite3_step()
>>>>>>>>>> To: kennethinbox-sql...@yahoo.com, "General Discussion of
>>>>>>>>>> SQLite
>>>>>>>>>> Database" <sqlite-users@sqlite.org>
>>>>>>>>>> Date: Wednesday, March 4, 2009, 4:31 PM
>>>>>>>>>> Ken,
>>>>>>>>>>
>>>>>>>>>> you are of course right that it needs some checks
>>>>>>>>>> for locks and busy states. I left that out to
>>>>>>>>>> simplify the code given below. My original code
>>>>>>>>>> checks that and it usually works quite well.
>>>>>>>>>> that's basically the reason why I was puzzled
>>>>>>>>>> by the randomly MISUSE results after I added the shared
>>>>>>>>>> cache.
>>>>>>>>>>
>>>>>>>>>> I'm not yet finished with my debugging since it is a
>>>>>>>>>> multithreading/collision issue - ugly to trace.
>>>>>>>>>>
>>>>>>>>>> My feeling is that it is related to the condition when
>>>>>>>>>> one thread is attempting or holding an exclusive lock
>>>>>>>>>> while another thread is just doing an sqlite_step (read
>>>>>>>>>> only)
>>>>>>>>>> on an allready created statement. Both threads use their
>>>>>>>>>> own
>>>>>>>>>> DB connections. For example: when I do a sqlite_reset
>>>>>>>>>> right after sqlite_step returns SQLITE_MISUSE, as Richard
>>>>>>>>>> suggest,
>>>>>>>>>> I get immediately a SQLITE_LOCK return code from
>>>>>>>>>> sqlite_reset in this case. Why I didn't get that before
>>>>>>>>>> or
>>>>>>>>>> from the sqlite_prepare ?
>>>>>>>>>>
>>>>>>>>>> Anyway, I'm going on to workaround this.... ALso I
>>>>>>>>>> would like
>>>>>>>>>> to mention once more that it is only during an artificial
>>>>>>>>>> stress
>>>>>>>>>> test, mainly to verify my implementation. Under normal
>>>>>>>>>> usercondition it is very unlikely to happend and sqlite
>>>>>>>>>> works perfect as expected.
>>>>>>>>>>
>>>>>>>>>> Thanks
>>>>>>>>>>
>>>>>>>>>> Marcus
>>>>>>>>>>
>>>>>>>>>>> Marcus,
>>>>>>>>>>>
>>>>>>>>>>> You might want to also add some checks in for
>>>>>>>>>> sqlite_busy as on the result
>>>>>>>>>>> of the prepare and the first call to sqlite_step.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On the inner loop test for the most common case first
>>>>>>>>>> (SQLITE_ROW) then
>>>>>>>>>>> test for errors... Slight performance improvement...
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --- On Wed, 3/4/09, Marcus Grimm
>>>>>>>>>> <mgr...@medcom-online.de> wrote:
>>>>>>>>>>>> From: Marcus Grimm <mgr...@medcom-online.de>
>>>>>>>>>>>> Subject: Re: [sqlite] shared cache and
>>>>>>>>>> SQLITE_MISUSE on sqlite3_step()
>>>>>>>>>>>> To: "General Discussion of SQLite
>>>>>>>>>> Database" <sqlite-users@sqlite.org>
>>>>>>>>>>>> Date: Wednesday, March 4, 2009, 10:25 AM
>>>>>>>>>>>> Richard, thanks again for the feedback.
>>>>>>>>>>>>
>>>>>>>>>>>> However, I don't see how it can happend that
>>>>>>>>>> the
>>>>>>>>>>>> statement
>>>>>>>>>>>> is completed internally without returning
>>>>>>>>>> SQLITE_DONE.
>>>>>>>>>>>> In the particular code of the "reading
>>>>>>>>>> thread" I
>>>>>>>>>>>> do something like:
>>>>>>>>>>>>
>>>>>>>>>>>> --
>>>>>>>>>>>> sqlite3_prepare_v2(db, "SELECT * FROM
>>>>>>>>>> TableA",
>>>>>>>>>>>> -1, &stmt, 0);
>>>>>>>>>>>> /** step throu table result **/
>>>>>>>>>>>> do
>>>>>>>>>>>> {
>>>>>>>>>>>> rc = sqlite3_step(stmt);
>>>>>>>>>>>> if( rc == SQLITE_MISUSE )
>>>>>>>>>>>> {  fprintf(stderr, "ERROR...\n");
>>>>>>>>>> break; }
>>>>>>>>>>>> else
>>>>>>>>>>>> if( rc == SQLITE_ROW )
>>>>>>>>>>>>  read_data_etc();
>>>>>>>>>>>> else
>>>>>>>>>>>>  break;
>>>>>>>>>>>> }while( rc != SQLITE_DONE );
>>>>>>>>>>>>
>>>>>>>>>>>> sqlite3_finalize(stmt);
>>>>>>>>>>>> --
>>>>>>>>>>>>
>>>>>>>>>>>> The prepare statement pointer is defined locally
>>>>>>>>>> and no
>>>>>>>>>>>> other
>>>>>>>>>>>> thread can access it, except sqlite internal
>>>>>>>>>> maybe.
>>>>>>>>>>>> To me it looks that in case a parallel thread is
>>>>>>>>>> inserting
>>>>>>>>>>>> or
>>>>>>>>>>>> updating data, the above loop is somehow affected
>>>>>>>>>> and
>>>>>>>>>>>> returns the
>>>>>>>>>>>> MISUSE.
>>>>>>>>>>>>
>>>>>>>>>>>> Your reply so far indicates either a bug on my
>>>>>>>>>> side or a
>>>>>>>>>>>> missusage.
>>>>>>>>>>>> I'll go on and try to find the reason why the
>>>>>>>>>> magic
>>>>>>>>>>>> number is resetted
>>>>>>>>>>>> without knowing from calling functions.
>>>>>>>>>>>>
>>>>>>>>>>>> calling sqlite3_reset in these cases is difficult
>>>>>>>>>> for me
>>>>>>>>>>>> since it might
>>>>>>>>>>>> not be the first step and previous data is
>>>>>>>>>> allready in use
>>>>>>>>>>>> in the upper loop.
>>>>>>>>>>>> But maybe an option for the very first step if
>>>>>>>>>> that
>>>>>>>>>>>> fails... hm... I'll try that.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks again
>>>>>>>>>>>>
>>>>>>>>>>>> kind regards
>>>>>>>>>>>>
>>>>>>>>>>>> Marcus Grimm
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> D. Richard Hipp wrote:
>>>>>>>>>>>>> On Mar 4, 2009, at 9:35 AM, Marcus Grimm
>>>>>>>>>> wrote:
>>>>>>>>>>>>>> hi,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> OK, the value of p->magic is 519C2973
>>>>>>>>>>>> (VDBE_MAGIC_HALT)
>>>>>>>>>>>>> That means the prepared statement has run to
>>>>>>>>>>>> completion and needs to
>>>>>>>>>>>>> be reset using sqlite3_reset() before you
>>>>>>>>>> continue.
>>>>>>>>>>>>> D. Richard Hipp
>>>>>>>>>>>>> d...@hwaci.com
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>>>>> 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
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> 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
>>>>>>>>
>>>>>>> --
>>>
>>>>>>> _______________________________________________
>>>>>>> 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
>>>>>>
>>>>> --
>>>
>>>>> _______________________________________________
>>>>> 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
>>>>
>>> _______________________________________________
>>> 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
>>
>>
>> _______________________________________________
>> 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
>


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

Reply via email to