SQLite 多线程——避免读者不必要的阻塞

SQLite multithread - avoid unnecessary blocking for readers

很久以前,我将使用相同 sqlite 数据库的 多线程应用程序 (php 脚本)上的所有事务打包到 BEGIN IMMEDIATE TRANSACTION 中。我记得,我在 SO 的某处读到:need to wrap all transactions withBEGIN IMMEDIATEon multithread environment to avoidSQLITE_BUSY` 状态。

现在,我正在考虑一些优化。

Sqlite 文档说:After a BEGIN IMMEDIATE, no other database connection will be able to write to the database or do a BEGIN IMMEDIATE. Other processes can continue to read from the database, however.

那么,只用 IMMEDIATE 包装 WRITE 交易也许是安全的(或任何陷阱)?并使用默认 "BEGIN TRANSACTION" 实时 READ 交易?或者也许检查我的代码,只避开 BEGIN IMMEDIATE 开始的地方,然后去写,然后读,然后写等等,然后重写这个圈子,比如:

BEGIN IMMEDIATE
ALL READS
then
ALL WRITES
END

如果我没记错的话,在后一种情况下,SQLite 只会在 WRITE 开始时锁定整个数据库,而不是在 BEGIN IMMEDIATE 星时锁定整个数据库?其他线程将能够读取并从那里开始 BEGIN IMMEDIATE statements?

当两个事务想要将读锁升级为写锁时,可能会发生死锁。 为保证这种情况不会发生,至少其中一项交易必须使用 BEGIN IMMEDIATE.

只读事务不涉及此类死锁(它们总是在不需要更多锁的情况下结束),因此它们可以使用 BEGIN DEFERRED.

您可以使用预写日志 (WAL)。 WAL 提供了更多的并发性,因为读者不会阻止作者,而作者也不会阻止读者。读和写可以同时进行。可以找到更多关于它的信息 here.

要在您的应用程序中启用它,请在连接字符串中使用 journal mode=WALPRAGMA journal_mode=WAL;