相关问题:How to use SQLite in a multi-threaded application.
我一直试图在多线程程序中从SQLite3中获得不错的性能。除了写入延迟之外,我的表现给我留下了非常深刻的印象。这不是它的错,它必须等待磁盘旋转才能提交数据。但是在这些写入期间阻塞读取,即使它们可以从缓存中读取,也是非常难以忍受的。
我的用例涉及大量的小型读取操作,以通过索引字段获取一个小对象,但延迟对于这些操作很重要,因为它们有很多。写入很大并且累积到单个事务中。我不希望读取因完成写入而产生巨大的延迟。
我首先使用单个连接与互斥锁来保护它。但是,当写入线程正在等待事务完成时,读取器在磁盘I / O上被阻止,因为在编写器释放它之前它们无法获取互斥锁。我尝试使用多个连接,但后来我从SQLITE_LOCKED
获得sqlite3_step
,这意味着必须重新设计所有阅读代码。
我的写逻辑目前看起来像这样:
START TRANSACTION
END TRANSACTION
- 这是阻挡的地方是否有一些我不知道的解决方案?如果条目在缓存中而不必重写所有读取代码以处理SQLITE_LOCKED
,重置和重试,是否有一种简单的方法可以让我的读者不必等待磁盘完成旋转?
答案 0 :(得分:6)
要允许多个读者和一个编写者同时访问数据库,请启用write-ahead logging。
WAL适用于小事务,因此您不需要累积写入。
请注意,WAL不适用于网络文件系统,为了获得最佳性能,需要定期检查点。
答案 1 :(得分:1)
首先,sqlite自己提供多线程支持。您不必使用自己的互斥锁,因为只会降低整个程序的速度。如果您有任何疑问,请咨询sqlite thread options。
使用预写日志可以解决您的问题,但这是一把双刃剑。只要正在进行读取,插入的数据就不会写入主数据库文件,WAL日志也会增长。 Write-Ahead Logging
详细介绍了这一点我在我的一个应用程序中使用WAL模式的sqlite。对于少量数据,它运作良好。但是,当有大量数据(每秒数百次插入,峰值甚至更多)时,我遇到了一些问题,我似乎无法通过任何插入sqlite配置来修复。
您可以考虑使用多个数据库文件,每个文件都分配给特定的时间跨度。仅当您的查询取决于时间时,此选项才适用。
我可能跑得太远了。 WAL日记应该有所帮助:)