On 02/18/2015 06:53 AM, Tim Starling wrote: > We (Wikimedia) are observing SQLITE_BUSY errors in our integration > testing. The integration test consists of having a single browser > instance view a MediaWiki site which uses SQLite 3.8 for its backend. > The browser sends several parallel requests for CSS, JS, etc., and > MediaWiki writes to the SQLite database while servicing each of these > requests. Thus there is some lock contention. > > In strace we see SQLite sleeping when it fails to acquire a SHARED > lock, but when it tries to acquire a RESERVED lock, no sleep is done, > and an error is immediately reported to the application.
If you already have a busy-handler or busy-timeout configured but it is not being used when upgrading to a RESERVED lock, it is to avoid deadlock. Is the transaction something like: BEGIN; SELECT .... /* SHARED lock on database */ INSERT ... /* RESERVED lock on database */ In this case, blocking on the RESERVED lock is no good. The process currently holding it is a writer that will need to obtain the EXCLUSIVE lock in order to commit its transaction. And obtaining the EXCLUSIVE lock will of course require it to wait until all readers release their SHARED locks - including the reader waiting on RESERVED. So deadlock. One fix is to make sure that an active read-transaction is never upgraded to a write-transaction. Do this by making all transactions that may write to the database write-transactions from the start. Either by opening them with "BEGIN IMMEDIATE" or making sure that the first statement in the transaction is a writer. BEGIN IMMEDIATE; /* Blocks for RESERVED lock */ SELECT .... INSERT ... Dan. > > https://phabricator.wikimedia.org/T89180 > > The relevant code has a comment indicating that this is expected > behaviour: > > /* Obtain a RESERVED lock on the database file. If the exFlag parameter > ** is true, then immediately upgrade this to an EXCLUSIVE lock. The > ** busy-handler callback can be used when upgrading to the EXCLUSIVE > ** lock, but not when obtaining the RESERVED lock. > */ > rc = pagerLockDb(pPager, RESERVED_LOCK); > if( rc==SQLITE_OK && exFlag ){ > rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); > } > > > Is it possible to open a bug or feature request for making SQLite wait > on RESERVED locks? > > Also, do you have any suggestions for a workaround? > > -- Tim Starling > > _______________________________________________ > sqlite-users mailing list > sqlite-users at mailinglists.sqlite.org > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users