On 06/23/2015 03:49 PM, Harmen de Jong - CoachR Group B.V. wrote:
> Is there anyone who can confirm that the first read transaction with WAL 
> enabled locks the database because it triggers the SchemaLoaded?

When a database in wal mode is first queried, SQLite takes a SHARED lock 
on the file. This is the same SHARED lock that is used when reading in 
rollback mode - except in wal mode it is held until the connection is 
closed.

And acquiring a SHARED lock requires temporarily obtaining a PENDING lock:

   http://www.sqlite.org/src/artifact/27cc135e2d0b8?ln=3030-3032

So yes, I think your analysis is correct.

Dan.




>
> Does anybody have a better suggestion to circumvent this locking issue than 
> serializing the first read transaction?
>
> -----Original Message-----
> From: sqlite-users-bounces at mailinglists.sqlite.org 
> [mailto:sqlite-users-bounces at mailinglists.sqlite.org] On Behalf Of Harmen 
> de Jong - CoachR Group B.V.
> Sent: donderdag 18 juni 2015 15:02
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] SQLite PENDING lock before SHARED lock with WAL enabled
>
> Thanks for your feedback. We can confirm that the database is in WAL mode. 
> After some further digging, we have found out It only happens with the very 
> first query. SQLite calls sqlite3InitOne when DbHasProperty(db, 1, 
> DB_SchemaLoaded) is false. Apparently, the schema is loaded into memory via 
> the common SHARED locking mechanism. So when multiple threads perform their 
> first query at the very same moment, they lock each other out.
>
> We assume that the locking of the PENDING byte during initialization does not 
> lock out a writer on another already initialized connection. Can your confirm 
> this?
>
> We can solve the issue by using our own locking mechanism around the first 
> query, so that these queries never occur simultaneously. However, it would be 
> great if there would be a more neat solution, because some of our databases 
> have a lot of tables and therefore loading the database schema can cost a lot 
> of time (relatively). Therefore, we would like to be able to open multiple 
> parallel connections and initialize them at the same time. Do you have any 
> suggestions for this?
>
> Best regards,
>
> Harmen de Jong
>
> -----Original Message-----
> From: sqlite-users-bounces at mailinglists.sqlite.org 
> [mailto:sqlite-users-bounces at mailinglists.sqlite.org] On Behalf Of Richard 
> Hipp
> Sent: donderdag 18 juni 2015 13:00
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] SQLite PENDING lock before SHARED lock with WAL enabled
>
> On 6/18/15, Harmen de Jong - CoachR Group B.V. <harmen at coachr.com> wrote:
>> A SELECT query obtains a SHARED lock on the database file. Doing so,
>> there can be many simultaneous readers according to the documentation
>> at https://www.sqlite.org/lockingv3.html. However, before the SHARED
>> lock is obtained in winLock(sqlite3_file *id, int locktype), a
>> temporary PENDING lock is requested.
>>
>> So when multiple threads start a SELECT query on different sqlite3*
>> objects at the exact same time, some of them will result in a
>> SQLITE_BUSY error, because they all request the exclusive PENDING
>> lock. Is there a way to work around this, so that I can execute SELECT 
>> queries really simultaneously?
>>
>> We have WAL enabled,
> Please double-check that you really have WAL mode enabled.  From the 
> sqlite3.exe command-line shell run commands like:
>
>       PRAGMA journal_mode;
>       .dbinfo
>
> In the second command, the "write format" and "read format" should both be 
> "2".
>
> I do not think you are really in WAL mode because a SHARED lock should never 
> happen in WAL mode.
>
>
>
>> so we were under the assumption that it should be possible to have
>> multiple readers at the same time, however the UNLOCKED -> PENDING ->
>> SHARED transition seems to intervene with the principle of having
>> multiple readers at the same time.
>>
>> This is the callstack of one of the threads:
>>
>>>              SQLService.exe!winLock(sqlite3_file * id=0x0e42aab0, int
>>> locktype=1) Line 35956
>>                 SQLService.exe!sqlite3OsLock(sqlite3_file *
>> id=0x0e42aab0, int lockType=1) Line 16294
>>                 SQLService.exe!pagerLockDb(Pager * pPager=0x0e42a998,
>> int
>> eLock=1) Line 42356
>>                 SQLService.exe!pager_wait_on_lock(Pager *
>> pPager=0x0e42a998, int locktype=1) Line 45027
>>                 SQLService.exe!sqlite3PagerSharedLock(Pager *
>> pPager=0x0e42a998) Line 46249
>>                 SQLService.exe!lockBtree(BtShared * pBt=0x0e429ea0)
>> Line
>> 55204
>>                 SQLService.exe!sqlite3BtreeBeginTrans(Btree *
>> p=0x0e428250, int wrflag=0) Line 55562
>>                 SQLService.exe!sqlite3InitOne(sqlite3 * db=0x0e427e38,
>> int iDb=0, char * * pzErrMsg=0x0d861654) Line 104635
>>                 SQLService.exe!sqlite3Init(sqlite3 * db=0x0e427e38,
>> char * *
>> pzErrMsg=0x0d861654) Line 104814
>>                 SQLService.exe!sqlite3ReadSchema(Parse *
>> pParse=0x0d861650) Line 104851
>>                 SQLService.exe!sqlite3LocateTable(Parse *
>> pParse=0x0d861650, int isView=0, const char * zName=0x0dd4ad38, const
>> char * zDbase=0x00000000) Line 90098
>>                 SQLService.exe!sqlite3LocateTableItem(Parse *
>> pParse=0x0d861650, int isView=0, SrcList_item * p=0x0dd4adc0) Line 90143
>>                 SQLService.exe!selectExpander(Walker *
>> pWalker=0x0cd6ec58, Select * p=0x0dd4acb8) Line 109480
>>                 SQLService.exe!sqlite3WalkSelect(Walker *
>> pWalker=0x0cd6ec58, Select * p=0x0dd4acb8) Line 80316
>>                 SQLService.exe!sqlite3SelectExpand(Parse *
>> pParse=0x0d861650, Select * pSelect=0x0dd4acb8) Line 109726
>>                 SQLService.exe!sqlite3SelectPrep(Parse *
>> pParse=0x0d861650, Select * p=0x0dd4acb8, NameContext * pOuterNC=0x00000000) 
>> Line 109812
>>                 SQLService.exe!sqlite3Select(Parse * pParse=0x0d861650,
>> Select * p=0x0dd4acb8, SelectDest * pDest=0x0cd6ef70) Line 110055
>>                 SQLService.exe!yy_reduce(yyParser *
>> yypParser=0x0d8665c0, int
>> yyruleno=111) Line 124055
>>                 SQLService.exe!sqlite3Parser(void * yyp=0x0d8665c0, int
>> yymajor=1, Token yyminor={...}, Parse * pParse=0x0d861650) Line 125147
>>                 SQLService.exe!sqlite3RunParser(Parse *
>> pParse=0x0d861650, const char * zSql=0x0141a4c4, char * * 
>> pzErrMsg=0x0cd6f09c) Line 125987
>>                 SQLService.exe!sqlite3Prepare(sqlite3 * db=0x0e427e38,
>> const char * zSql=0x0141a4c4, int nBytes=-1, int saveSqlFlag=1, Vdbe *
>> pReprepare=0x00000000, sqlite3_stmt * * ppStmt=0x0cd6f138, const char
>> * *
>> pzTail=0x0cd6f144) Line 105039
>>                 SQLService.exe!sqlite3LockAndPrepare(sqlite3 *
>> db=0x0e427e38, const char * zSql=0x0141a4c4, int nBytes=-1, int
>> saveSqlFlag=1, Vdbe * pOld=0x00000000, sqlite3_stmt * *
>> ppStmt=0x0cd6f138, const char * *
>> pzTail=0x0cd6f144) Line 105139
>>                 SQLService.exe!sqlite3_prepare_v2(sqlite3 *
>> db=0x0e427e38, const char * zSql=0x0141a4c4, int nBytes=-1,
>> sqlite3_stmt * * ppStmt=0x0cd6f138, const char * * pzTail=0x0cd6f144) Line 
>> 105215
>>                 SQLService.exe!sqlite3_exec(sqlite3 * db=0x0e427e38,
>> const char * zSql=0x0141a4c4, int (void *, int, char * *, char * *) *
>> xCallback=0x00000000, void * pArg=0x00000000, char * *
>> pzErrMsg=0x00000000) Line 100638
>>
>> Best regards,
>>
>> Harmen de Jong
>> CoachR Group B.V.
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users at mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>
> --
> D. Richard Hipp
> drh at sqlite.org
> _______________________________________________
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
> _______________________________________________
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
> _______________________________________________
> sqlite-users mailing list
> sqlite-users at mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to