On Mon, Apr 02, 2012 at 07:40:58PM +0400, Gregory Petrosyan scratched on the wall: > Hello, > > I am experiancing a weird problem: sometimes (1 time in a 10-100) when > 2 processes try to open the same database file (and execute something > like 'create table foo if not exists'), one of them fails with > SQLITE_BUSY ??? despite 1 second (or bigger) timeout. > > Processes themselves produce almost no DB activity; they merely start > and initialize the database roughly at the same time. > sqlite3_open_v2() is immediately followed by sqlite3_busy_timeout(). > > Unfortunately I can't write a small program that reproduces this > reliably: my test program never crashes this way (except when timeout > is really small ??? say, 10ms). Yet, this behaviour is rare but > reproducible, both from Python (apsw) on Windows, Python (apsw) on OS > X and native C API on OS X (in entirely different program). > > Can you please point me at what can be the cause of this?
You may be seeing a deadlock situation. This is most commonly associated with explicit transactions (that are open for a longer period of time), but it is possible with implicit transactions. If two connections attempt to write to the DB at the same time, it is possible for them to deadlock on the file locking. SQLite recognizes this and has one of the connections back off with an SQLITE_BUSY error. If this happens in an explicit transaction, the program needs to ROLLBACK the current transaction and start over. In the case of an implicit transaction around a statement, you can safely re-run the statement. http://sqlite.org/c3ref/busy_handler.html The presence of a busy handler does not guarantee that it will be invoked when there is lock contention. If SQLite determines that invoking the busy handler could result in a deadlock, it will go ahead and return SQLITE_BUSY or SQLITE_IOERR_BLOCKED instead of invoking the busy handler. Consider a scenario where one process is holding a read lock that it is trying to promote to a reserved lock and a second process is holding a reserved lock that it is trying to promote to an exclusive lock. The first process cannot proceed because it is blocked by the second and the second process cannot proceed because it is blocked by the first. If both processes invoke the busy handlers, neither will make any progress. Therefore, SQLite returns SQLITE_BUSY for the first process, hoping that this will induce the first process to release its read lock and allow the second process to proceed. -j -- Jay A. Kreibich < J A Y @ K R E I B I.C H > "Intelligence is like underwear: it is important that you have it, but showing it to the wrong people has the tendency to make them feel uncomfortable." -- Angela Johnson _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users