【问题标题】:SQLite with in-memory and isolation具有内存和隔离的 SQLite
【发布时间】:2020-06-09 22:51:11
【问题描述】:

我想创建一个内存中的 SQLite DB。我想与这个内存数据库建立两个连接,一个用于修改,另一个用于读取数据库。修改器连接将打开一个事务并继续对数据库进行修改,直到发生特定事件,此时它将提交事务。另一个连接将运行读取数据库的 SELECT 查询。我不希望修改器连接所做的更改对读取器连接可见,直到修改器已提交(发生指定的事件)。我想将读者的连接与作者的连接隔离开来。

我正在用 C++ 编写我的应用程序。我尝试打开两个连接,如下所示:

int rc1 = sqlite3_open_v2("file:db1?mode=memory", pModifyDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_URI, NULL);
int rc2 = sqlite3_open_v2("file:db1?mode=memory", pReaderDb, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_URI, NULL);

我创建了一个表,添加了一些行并使用'pModifyDb' 将事务提交到数据库。当我尝试通过调用 sqlite3_exec() 使用第二个连接“pReaderDb”检索值时,我收到返回码 1 (SQLITE_ERROR)。

我尝试将 URI 指定为 "file:db1?mode=memory&cache=shared"。我不确定'cache=shared' 选项是否会再保持隔离。但是,当阅读器连接尝试执行 SELECT 查询时,这也不起作用,返回码为 6 (SQLITE_LOCKED)。也许是因为共享缓存选项统一了引擎盖下的两个连接?

如果我从 URI 中删除内存中的要求,改为使用 "file:db1",一切正常。我不想使用基于文件的数据库,因为我需要高吞吐量并且数据库的大小不会很大(~10MB)。

所以我想知道如何设置两个独立的连接到单个 SQLite 内存数据库?

提前致谢, 克里斯

【问题讨论】:

    标签: c++ sqlite in-memory isolation


    【解决方案1】:

    这对于内存数据库是不可能的。

    您必须使用数据库文件。 要加快速度,请将其放在 RAM 磁盘上(如果可能),并在每个连接中禁用同步写入 (PRAGMA synchronous=off)。

    要同时允许一个reader和一个writer,你必须把DB文件放到WAL mode

    【讨论】:

    • 同步不会产生影响。如果 OP 想在另一个连接写入数据库的同时从数据库中读取,它需要处于 WAL 日志模式(哪些内存数据库不支持,所以,是的,需要文件支持分贝)。
    • 感谢您的回复!我不认为我可以创建一个 RAM 磁盘(我的代码是一个运输应用程序,必须在各种平台上运行,我不确定事情会如何发展)。现在我已经缓存了所有修改 SQL 语句,并在所述事件发生时执行它们。
    【解决方案2】:

    这似乎是可能的,因为version 3.7.13 (2012-06-11):

    为内存数据库启用共享缓存允许同一进程中的两个或多个数据库连接访问同一个内存数据库。共享缓存中的内存数据库会自动删除,并在与该数据库的最后一个连接关闭时回收内存。

    Docs

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 2015-06-14
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多