在 SQLite 中长时间保持读取事务打开是否可以?

Is it OK to keep a read transaction open for a long time in SQLite?

读取交易:https://www.sqlite.org/isolation.html

我们假设 WAL 已启用,因此我们可以在一个线程中读取而另一个线程正在写入。


我想达到的效果是这样的。

我有两个线程,一个是 UI 有时执行数据库读取的线程,另一个是数据库线程,它在事务中执行数据库 read/write。

UI线程中的结果被缓存,有时信息不完整,比如一个列表,我们只查询列表的大小,或者只查询该查询的前10项,然后我们当 UI 到达该部分时,以增量方式加载。

在 db 线程上,我们将执行事务并记住所有更改,然后 post(UI 线程是循环线程)对 UI 线程的更改并更新UI 增量缓存,以便尽可能少地阻塞 UI 线程。

问题是当数据库事务完成时,UI 线程可能会在循环线程处理该消息之前触发 UI 线程上的数据库读取,这也是由于 UI 框架工作,我们无法更新缓存,因为 UI 线程当前正在使用它。

所以我的想法是在UI线程上,在任何查询发生之前,开始一个读事务(以延迟模式开始一个事务,这个事务不会锁定数据库,因为没有写),然后在 UI 线程中发生的任何读取都将在该事务中发生,然后循环线程获取更新信息,结束事务,更新缓存,并开始另一个。因此数据库和缓存在 UI 线程中转换为新状态并同步。


那么我可以长时间保持读取事务打开吗?

所有读取都在一个事务中完成(如果需要,一个自动的),并且所有事务都锁定数据库。但是,WAL 模式下的只读锁只会阻塞 checkpoint operations.

长时间有一个活跃的事务是没有问题的,只要不断增长的WAL文件不溢出磁盘即可。 如果您的应用程序需要事务才能正常工作,那么您别无选择 – 替代方法是手动实现一些类似的事务机制,最好让数据库来处理。