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-boun...@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