我sqlite3
在多线程应用程序中使用(它是用它编译的SQLITE_THREADSAFE=2
).在观察窗口中我看到了sqlite->busyTimeout == 600000
,即它应该有10分钟超时.然而,sqlite3_step
回报SQLITE_BUSY
比10分钟之后快得多(它实际上立即返回,就像我从未打过电话一样sqlite3_busy_timeout
).什么原因sqlite3
忽略超时并立即返回错误?
一种可能性:SQLite在检测到死锁时忽略超时.
方案如下.事务A
以读者身份开始,后来尝试执行写入.交易B
是一个作家(或者以这种方式开始,或者作为读者开始并首先提升为作家).B
持有一把RESERVED
锁,等待读者清理,以便开始写作.A
持有一个SHARED
锁(它是一个读者)并试图获取RESERVED
锁(因此它可以开始写).有关各种锁类型的说明,请参阅http://sqlite.org/lockingv3.html
在这种情况下取得进展的唯一方法是回滚其中一个事务.没有多少等待会有所帮助,因此当SQLite检测到这种情况时,它不会遵循忙碌超时.
有两种方法可以避免死锁的可能性:
BEGIN IMMEDIATE
启动一个事务,最终可能需要写-这种方式,它开始作为一个作家的时候了.这当然会降低系统中潜在的并发性,因为避免死锁的代价.