c++ - sqlite3_wal_checkpoint_v2 总是返回 SQL_BUSY

标签 c++ sqlite

上下文

我在 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 行并更新第三个表。

我的应用程序有一个 400 毫秒的周期,数据库用于在每个周期开始时突发的 9 个事务。知道我的平均事务需要 15 毫秒(在 60 毫秒处非常罕见的峰值(Windows FlushFileBuffers 函数中大约 6 万个事务中有 1 个时间丢失)),数据库仅在 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。

问题

是什么导致数据库繁忙,知道数据库上只使用一个连接,这个连接被多个线程使用但在我的应用程序端通过互斥体序列化?

更多信息:

  • 我正在使用几个准备好的语句,这些语句在整个周期中保留(甚至一个用于 TRANSACTION BEGIN 和 TRANSACTION COMMIT)
  • 在提交第一个事务后,数据库似乎很忙。

尽管我在 sqlite 网站上阅读,但我还是很难理解 sqlite 的锁定和繁忙方案。有没有人对此有一些好的链接?

最佳答案

我找到了我的问题的原因,这是我这边的两件愚蠢的事情:

使用“PRAGMA page_size”查询页面大小,我只是读取行,而不是使用“sqlite3_reset”或 sqlite3_finalize 重置或完成语句(它有点被我测试的 C++ 包装器隐藏了)。

这导致数据库被锁定。然后,我在关闭数据库之前没有完成此查询,这导致数据库在重新打开后返回繁忙状态。

关于c++ - sqlite3_wal_checkpoint_v2 总是返回 SQL_BUSY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7250883/

相关文章:

c++ - 如何修复内存不足错误(openCV)

WAL模式下的Java SQLite : the database is locked

c++ - 如何在 C++ 中对方法的副作用进行单元测试?

c++ - 数组的指针,那个数组的每个元素的内存空间信息存放在哪里?

SQLite个人书籍数据库设计评论

java - 我无法将数据插入我的数据库

MySQL:如何获得 View 的模块化,但较长代码的优化?

android - 在 SQLite 中比较日期的问题

c++ - Windows C++ 子窗口无响应

c++ - 如何为继承自QFrame的小部件设置边框?