8

相关问题如何在多线程应用程序中使用 SQLite。

我一直试图在多线程程序中从 SQLite3 中获得不错的性能。除了写入延迟外,它的性能给我留下了深刻的印象。这不是它的错,它必须等待磁盘旋转才能提交数据。但是在这些写入过程中阻止读取,即使它们可以从缓存中读取,也是非常不能容忍的。

我的用例涉及大量小型读取操作,以通过索引字段获取一个小对象,但延迟对于这些操作很重要,因为它们有很多。写入量很大,并累积到单个事务中。我不希望由于完成写入而导致读取有很大的延迟。

我首先只是使用带有互斥锁的单个连接来保护它。但是,当写入线程等待事务完成时,读取器在磁盘 I/O 上被阻塞,因为他们无法获取互斥锁,直到写入器释放它。我尝试使用多个连接,但后来我得到SQLITE_LOCKED了 from sqlite3_step,这意味着必须重新设计所有阅读代码。

我的写逻辑目前看起来像这样:

  1. 获取连接互斥锁。
  2. START TRANSACTION
  3. 做所有的写。(通常是 10 到 100 个小的。)
  4. END TRANSACTION-- 这里是阻塞的地方
  5. 释放互斥锁。

有什么我不知道的解决方案吗?如果条目在缓存中,是否有一种简单的方法可以让我的读者不必等待磁盘完成旋转,而不必重写我所有的阅读代码来处理SQLITE_LOCKED、重置和重试?

4

2 回答 2

6

要允许多个读取器和一个写入器同时访问数据库,请启用预写日志记录

WAL 适用于小型事务,因此您不需要累积写入。

请注意,WAL 不适用于网络文件系统,为了获得最佳性能,需要定期检查点。

于 2013-01-10T08:01:19.920 回答
1

首先,sqlite 自己提供多线程支持。您不必使用自己的互斥锁,因为您只会减慢整个程序的速度。如果您有任何疑问,请咨询sqlite 线程选项。

使用 write-ahead log 可能会解决您的问题,但它是一把双刃剑。只要正在进行读取,插入的数据就不会写入主数据库文件,WAL 日志就会增长。这在预写日志中有详细介绍

我在我的一个应用程序中以 WAL 模式使用 sqlite。对于少量数据,它运行良好。但是,当有大量数据时(每秒数百次插入,峰值甚至更多),我会遇到一些问题,我似乎无法通过任何干预 sqlite 配置来解决这些问题。

您可能会考虑使用多个数据库文件,每个文件都分配给特定的时间跨度。这仅适用于您的查询取决于时间。

我可能跑得太快了。WAL 杂志应该有所帮助:)

于 2013-01-10T08:23:04.463 回答