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, 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.