【问题标题】:Avoid sqlite vacuum "database is locked" by application level retrying通过应用程序级重试避免sqlite Vacuum“数据库被锁定”
【发布时间】:2013-10-09 20:03:34
【问题描述】:

我正在使用一个简单的 sqlite DB 作为进程之间的持久性消息队列机制。为了在超过一定限制后减小文件大小,我想使用“vacuum”命令。一般来说,这一切都很好,只是我在清理时时不时收到“数据库已锁定”错误。

在阅读了网络上的各种资源后,我了解到在 sqlite 级别上我无能为力。

但是,除了附带问题“为什么会这样?使用常规的 busyHandler 机制重试获取所需的锁会有什么问题?”我想出了在应用程序级别实现完全相同的busyHandler机制的想法。

现在是基本问题:这有什么问题吗?

非常感谢!!

【问题讨论】:

  • SQLite 自动重用已释放的数据库页面,因此文件大小最终将保持不变。你不需要VACUUM,除非你真的知道数据总量会变小并且未来不会增加。
  • true,但在我的场景中(作为 msg 队列),我必须支持诸如最大队列大小之类的东西。所以如果我超过了这个,我就不能再写入数据库了——即使数据库同时是完全空的(因为读者现在已经消耗了所有的味精)。嗯,除非我能确定实际的实际数据量(而不仅仅是文件大小)......会考虑......

标签: sqlite locking vacuum


【解决方案1】:

使用 SQLite 的 built-in retrying mechanism 和自己实现并没有太大区别。 但是,编写不需要编写的代码是徒劳的,并且会增加引入错误的机会。

【讨论】:

  • 同意。但根据我最初的设计,我仍然认为(但会重新考虑——实际上不需要它更优雅)我确实需要它,但它不存在——因此我自己做。所以,也许“为什么它不存在”这个问题可能更重要。 sqlite的人是不是故意漏掉的?最有可能的。因为它增加了技术。问题还是仅仅因为他们不想要针对这种情况的特殊解决方案?
  • 您认为缺少什么?
  • 好吧,重试获取真空操作的锁(例如,通过使用busyHandler或类似的东西),或者更好的是,有可能为其他操作启用这样的机制
  • 没错。通常是的,但在吸尘时不会
  • 为我工作。 (SQLite 尝试获取锁的方式没有区别。)
【解决方案2】:

在又解决了一段时间后,我通过完全删除清理来更改我的应用程序逻辑,而是使用“pragma max_page_count”来限制数据库大小。唯一需要注意的是,这似乎是特定于会话的,即每次连接数据库后必须重新设置编译指示。

关于最初的问题:我发现@CL 基本上是正确的——清理确实涉及标准的忙处理程序。而且在 Linux 上这也很好地工作,只是在 Windows 上它并不可靠(尽管可能是偶然的,而是由系统速度引起的,......)。在我的自定义busyHandler中使用一点printf()我可以看到它在大多数情况下被调用,但有时它不是并且“pragma Vacuum”只返回“DB锁定”。 可能是由于并发进程试图同时清空(?)......无论如何,重新设计的设计更清洁/更容易。

【讨论】:

猜你喜欢
  • 2015-08-03
  • 2017-04-29
  • 2011-08-31
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 2011-08-05
  • 2015-05-11
相关资源
最近更新 更多