我正在使用System.Data.Sqlite来访问C#中的SQLite数据库。我有一个查询必须读取表中的行。在迭代行并且阅读器处于打开状态时,必须执行某些SQL更新。我遇到了“数据库被锁定”的异常。
SQLite文档中指出:
当进程想要从数据库文件中读取数据时,它会按照以下步骤进行:
1. 打开数据库文件并获取共享锁。
文档进一步说明了“共享”锁:
数据库可以被读取但不能被写入。任意数量的进程可以同时持有共享锁,因此可以有多个并发读取者。但是,在一个或多个共享锁处于活动状态时,不允许其他线程或进程写入数据库文件。 FAQ中指出:
多个进程可以同时打开同一个数据库。多个进程可以同时进行SELECT操作。但是,只有一个进程可以在任何时刻对数据库进行更改。
当进程想要从数据库文件中读取数据时,它会按照以下步骤进行:
1. 打开数据库文件并获取共享锁。
文档进一步说明了“共享”锁:
数据库可以被读取但不能被写入。任意数量的进程可以同时持有共享锁,因此可以有多个并发读取者。但是,在一个或多个共享锁处于活动状态时,不允许其他线程或进程写入数据库文件。 FAQ中指出:
多个进程可以同时打开同一个数据库。多个进程可以同时进行SELECT操作。但是,只有一个进程可以在任何时刻对数据库进行更改。
这本书《SQLite权威指南》中提到:
...通过使用read_uncommited命令,连接可以选择具有读未提交隔离级别。如果将其设置为true,则该连接将不会在读取表时放置读锁。因此,另一个写入者实际上可以更改表,因为以读未提交模式运行的连接既不能被其他连接阻塞,也不能阻塞其他连接。
我尝试在SQL查询命令语句中将pragma设置为读未提交,如下所示:
PRAGMA read_uncommitted = 1;
SELECT Column1, Column2 FROM MyTable
在使用不同的连接进行SQL更新时,仍然会出现“数据库已锁定”的异常。然后我尝试在连接实例上将隔离级别设置为读未提交。但是仍然出现相同的异常。
如何在保持打开数据读取器以循环遍历数据库行而不锁定数据库的情况下执行更新操作?
更新:
下面的两个答案都有效。但是,我已经不再使用默认的回滚日志,而是使用了Write-Ahead Logging,这提供了更好的数据库读写并发性。