【问题标题】::memory: database with shared cache is not so temporary:memory: 共享缓存的数据库不是那么临时的
【发布时间】:2018-07-01 11:59:50
【问题描述】:

内存数据库的 SQLite 文档 (https://www.sqlite.org/inmemorydb.html) 指出要共享 :memory: 跨连接,您应该使用 URI 命名并设置 cache=shared,就像这样(C API):

rc = sqlite3_open("file::memory:?cache=shared", &db);

我从 Python 2.7.14 尝试过这个,具有以下属性:

>>> sqlite3.version
'2.6.0'
>>> sqlite3.apilevel
'2.0'
>>> sqlite3.sqlite_version
'3.20.1'

我发现数据库并不像我预期的那么短暂。这是一个会话。

首先,创建一个数据库并插入一行...

% python
Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 17:05:42) 
[GCC 7.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> conn = sqlite3.Connection("file::memory:?cache=shared")
>>> curs = conn.cursor()
>>> curs.execute("select * from sqlite_master").fetchall()
[]
>>> curs.execute("create table XYZ (x int, y int, z varchar)")
<sqlite3.Cursor object at 0x7ff4b2a06110>
>>> curs.execute("insert into XYZ values (?, ?, ?)", (1, 2, '3'))
<sqlite3.Cursor object at 0x7ff4b2a06110>
>>> curs.execute("select * from sqlite_master").fetchall()
[(u'table', u'XYZ', u'XYZ', 2, u'CREATE TABLE XYZ (x int, y int, z varchar)')]
>>> curs.execute("select * from XYZ").fetchall()
[(1, 2, u'3')]
>>> conn.close()
>>> 

看这里,有一个剩余文件:

% ls -l file*
-rw-r--r-- 1 skip skip 8192 Jan 22 12:49 file::memory:?cache=shared

而且会话中似乎还剩下一些内容:

% strings -a file*
SQLite format 3
atableXYZXYZ
CREATE TABLE XYZ (x int, y int, z varchar)

确实,我可以打开它。虽然它看起来是空的(我没有在第一个会话中明确地 commit(),所以也许这就是原因),数据库仍然存在并且可以访问:

% python
Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 17:05:42) 
[GCC 7.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sqlite3
>>> conn = sqlite3.Connection("file::memory:?cache=shared")
>>> curs = conn.cursor()
>>> curs.execute("select * from XYZ").fetchall()
[]
>>> curs.execute("select * from sqlite_master").fetchall()
[(u'table', u'XYZ', u'XYZ', 2, u'CREATE TABLE XYZ (x int, y int, z varchar)')]

当我第一次看到“file::memory?cache=shared”表单时,我觉得它看起来很奇怪。它是否应该更像“file://:memory:?cache=shared”?我试过了,收到一个错误。尽管如此,虽然记录的名称有效,但它显然会将文件写入文件系统。当我注意到它与普通的旧“:memory:”相比有多慢以及生成的文件有多大时,我很偶然地发现了这一点。不幸的是,这些文件被写入了一个 NFS 挂载的文件系统,这可能解释了很多缓慢的原因。

有没有办法保证内存数据库可以在同一进程中从多个连接访问?

【问题讨论】:

    标签: python caching memory sqlite


    【解决方案1】:

    以共享缓存模式打开内存数据库需要URI filename。你的 Python 版本不支持这个;它总是将整个字符串视为文件名。

    Python 3.4 及更高版本支持 URI 文件名:

    db = sqlite3.connect("file::memory:?cache=shared", uri=True)
    

    【讨论】:

      【解决方案2】:

      如果通过 SQLAlchemy 连接,则需要在 URI 本身上设置 uri=true 标志,例如:

      sqlalchemy.create_engine('sqlite:///:memory:?cache=shared&uri=true')
      

      详情请见https://docs.sqlalchemy.org/en/14/dialects/sqlite.html#uri-connections

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多