http://www.sqlite.org/c3ref/busy_handler.html留着自己看的。
Register A Callback To Handle SQLITE_BUSY Errors
注册一个回调函数处理SQLITE_BUSY错误
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
This routine sets a callback function that might be invoked whenever an attempt is made to open a database table that another thread or process has locked.
本函数的目的是设置一个回调函数,如果你试图去打开一个被别的线程和进程锁定的数据库表的时候,这个回调函数会被调用。
If the busy callback is NULL, then SQLITE_BUSY or SQLITE_IOERR_BLOCKED is returned immediately upon encountering the lock. If the busy callback is not NULL, then the callback might be invoked with two arguments.
如果回调函数的参数为NULL,那么SQlite系统会在遇到一个锁的时候马上返回SQLITE_BUSY或者SQLITE_IOERR_BLOCKED。如果这个回调函数的参数不为NULL,那么这个回调函数会被调用,它带有2个参数。
The first argument to the busy handler is a copy of the void* pointer which is the third argument to sqlite3_busy_handler(). The second argument to the busy handler callback is the number of times that the busy handler has been invoked for this locking event. If the busy callback returns 0, then no additional attempts are made to access the database and SQLITE_BUSY or SQLITE_IOERR_BLOCKED is returned. If the callback returns non-zero, then another attempt is made to open the database for reading and the cycle repeats.
回调函数中的第一个参数是sqlite3_busy_handler()中的第三个参数的一份拷贝,第二个参数是回调函数因为这个锁定事件而被调用的次数。如果回调函数返回0,那么SQlite系统就不会再尝试访问数据库,SQLITE_BUSY或者SQLITE_IOERR_BLOCKED会被马上返回。如果回调函数返回非0,SQlite系统会再试着访问数据库。
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.
这个回调函数不能保证在任何遇到锁的情况下都会被调用。如果SQlite系统认为调用回调函数会导致死锁,那么它会直接返回SQLITE_BUSY或者SQLITE_IOERR_BLOCKED。假如,一个进程持有读锁并且想要试着提升为保留锁,另一个线程持有保留锁并且想要提升为排它锁,那么这种情况可能导致死锁,因为第一个线程在等待第二线程释放保留锁,而第二个线程也在等待第一个线程释放读锁。如果他们都调用回调函数的话,他们都不会获得任何进展。因此,SQLite会返回SQLITE_BUSY给第一个线程,它希望第一个线程能释放读锁,这样就能让第二个线程继续运行了。
The default busy callback is NULL.
默认的回调函数是NULL。
The SQLITE_BUSY error is converted to SQLITE_IOERR_BLOCKED when SQLite is in the middle of a large transaction where all the changes will not fit into the in-memory cache. SQLite will already hold a RESERVED lock on the database file, but it needs to promote this lock to EXCLUSIVE so that it can spill cache pages into the database file without harm to concurrent readers. If it is unable to promote the lock, then the in-memory cache will be left in an inconsistent state and so the error code is promoted from the relatively benign SQLITE_BUSY to the more severe SQLITE_IOERR_BLOCKED. This error code promotion forces an automatic rollback of the changes. See the CorruptionFollowingBusyError wiki page for a discussion of why this is important.
如果在大型事务中,改变不能存入内存缓冲区, SQLITE_BUSY错误码会变成SQLITE_IOERR_BLOCKED。还有一种情况,如果SQLite持有一个保留锁,为了不让一些读的事务出现数据的不一致,它必须将自己的锁提升为EXLUSIVE(排它)锁,这样才能将缓存页中的数据安全的写入数据库中。如果SQLite不能完成这种提升,内存缓冲区中的数据将会出现不一致,这是错误码会从相对温和的SQLITE_BUSY变成更严重的SQLITE_IOERR_BLOCKED。SQLITE_IOERR_BLOCKED会强迫这些改变的自动回滚。可以去CorruptionFollowingBusyErrorWiki页看看为什么这很重要。
There can only be a single busy handler defined for each database connection. Setting a new busy handler clears any previously set handler. Note that callingsqlite3_busy_timeout() will also set or clear the busy handler.
对于每一个数据库连接来说,只能注册一个回调函数,注册任何一个新的回调函数都会替换掉以前那个。注意:调用sqlite3_busy_timeout()也会注册或清除回调函数。
The busy callback should not take any actions which modify the database connection that invoked the busy handler. Any such actions result in undefined behavior.
A busy handler must not close the database connection or prepared statement that invoked the busy handler.
任何回调函数都不应该做出修改调用自己的数据库连接的行为,任何这种行为都会导致不可预知的情况。
回调函数必须不能关掉调用自己的数据库连接或者释放掉调用自己的准备语句。