语境
我在Windows C ++程序中使用sqlite 3.7.7.1版,正在创建仅与SQLITE_OPEN_READWRITE具有一个连接的数据库。SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX。
我使用SQLite是因为我需要非常快速的ACID事务。数据库存储在Windows XP sp3的NTFS固态驱动器上。
该数据库有3个表,每个事务包含3个表,最大的事务在一个表中插入12行,在另一个表中插入1行并更新第三个表。
我的应用程序有一个400ms的周期,该数据库用于每个周期开始时发生的9次事务突发。知道我的平均事务需要15毫秒(在60毫秒时确实是非常罕见的高峰(约60万事务中的1事务在Windows FlushFileBuffers函数中浪费了时间),因此数据库仅用于400毫秒周期的前150毫秒。
进行基准测试后,WAL期刊为我的应用程序提供了最佳性能。
但是,我对WAL日记存在问题:xxx-wal文件正在增长并且不断增长(在进行500k交易后,wal文件为8GB!)。激活auto_checkpoint没有帮助。
当尝试通过使用SQLITE_CHECKPOINT_RESTART选项调用sqlite3_wal_checkpoint_v2手动执行检查点时,sqlite3始终返回SQLITE_LOCKED。
我发现当我使用sqlite3_exec创建表时,连接将永远锁定。有什么解释?有办法避免这种情况吗?
因此,关闭连接并重新打开它,我尝试调用sqlite3_wal_checkpoint_v2,但是这次,它返回了SQLITE_BUSY。即使我在1秒内调用sqlite3_busy_timeout,它仍然会返回SQLITE_BUSY。
问题
是什么导致数据库繁忙,知道数据库上仅使用了一个连接,并且该连接被多个线程使用,但是在我的应用程序侧通过互斥锁进行了序列化?
更多信息:
尽管我在sqlite网站上进行了阅读,但我很难理解sqlite的锁定和繁忙方案。有人对此有很好的联系吗?
我找到了问题的原因,这是我这边的两件事:
使用“ PRAGMA page_size”查询页面大小时,我只是在读取行,而不是使用“ sqlite3_reset”或sqlite3_finalize重置或完成该语句(我测试过的C ++包装器将其隐藏了)。
这导致数据库被锁定。然后,我没有在关闭数据库之前完成此查询,这导致数据库在重新打开后返回繁忙状态。