当:memory:
数据库使用特殊URI打开时,它支持“共享缓存”(根据sqlite.org):
[T]他可以通过两个或多个数据库打开相同的内存数据库 连接如下:
rc = sqlite3_open("file::memory:?cache=shared",&db);
我可以使用sqlite3.connect()
的{{3}}在Python 3.4中利用这一点:
sqlite3.connect('file::memory:?cache=shared', uri=True)
但是,我似乎无法为SQLAlchemy工作:
engine = sqlalchemy.create_engine('sqlite:///:memory:?cache=shared')
engine.connect()
...
TypeError: 'cache' is an invalid keyword argument for this function
有没有办法让SQLAlchemy使用共享缓存?
修改:
在Python 3.4上,我可以使用creator
参数来解决问题,但问题仍然存在于其他Python版本中:
create_engine
答案 0 :(得分:6)
你应该避免在旧的Python版本上传递uri=True
,问题将得到解决:
import sqlite3
import sys
import sqlalchemy
DB_URI = 'file::memory:?cache=shared'
PY2 = sys.version_info.major == 2
if PY2:
params = {}
else:
params = {'uri': True}
creator = lambda: sqlite3.connect(DB_URI, **params)
engine = sqlalchemy.create_engine('sqlite:///:memory:', creator=creator)
engine.connect()
答案 1 :(得分:0)
有关SQLite方言的SQLAlchemy文档详细描述了该问题和解决方案:
线程/池行为
Pysqlite的默认行为是禁止 一个线程在多个线程中的使用情况。这是 最初打算与旧版本的SQLite一起使用 支持各种情况下的多线程操作。在 特别是,较旧的SQLite版本不允许:memory:数据库 在任何情况下都可以在多个线程中使用。
Pysqlite确实包含一个尚未公开的标志,称为
check_same_thread
将禁用此检查,但是请注意 pysqlite连接仍然不能安全地在 多线程。特别是,任何语句执行调用都会 需要外部互斥,因为Pysqlite不提供 错误消息的线程安全传播。所以当 甚至:memory:
数据库都可以在现代SQLite中的线程之间共享, Pysqlite没有提供足够的线程安全性来使这种用法值得 它。SQLAlchemy设置池以使用Pysqlite的默认行为:
指定
:memory:
SQLite数据库时,默认情况下的方言 将使用SingletonThreadPool
。该池维护一个连接 每个线程,以便在当前线程内对引擎的所有访问 使用相同的:memory:
数据库-其他线程将访问 不同的:memory:
数据库。指定基于文件的数据库时,方言将使用
NullPool
作为联系的来源。该游泳池关闭并丢弃 连接将立即返回到池中。 SQLite的 基于文件的连接的开销非常低,因此池化不是 必要。该方案还防止再次使用连接 在不同的线程中,并且最适合与SQLite的粗粒度文件一起使用 锁定。在多个线程中使用内存数据库
使用
:memory:
数据库 在多线程方案中,必须共享同一连接对象 在线程之间,因为数据库仅存在于该线程的范围内 连接。StaticPool
实现将维护一个 全局连接,并且check_same_thread
标志可以传递给 Pysqlite为False
:from sqlalchemy.pool import StaticPool engine = create_engine('sqlite://', connect_args={'check_same_thread':False}, poolclass=StaticPool)
请注意,在多个线程中使用
:memory:
数据库需要最新版本的SQLite。
来源:https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#threading-pooling-behavior