SQLite支持使用特殊URI打开:memory:数据库时的“共享缓存”(根据sqlite.org):
内存中的相同数据库可以由两个或多个数据库连接打开,如下所示:
rc = sqlite3_open("file::memory:?cache=shared",&db);
我可以在Python3.4中利用这一点,使用URI参数 for sqlite3.connect()
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利用共享缓存吗?
编辑
在Python3.4上,我可以使用creator参数来解决create_engine问题,但问题仍然存在于其他Python版本上:
creator = lambda: sqlite3.connect('file::memory:?cache=shared', uri=True)
engine = sqlalchemy.create_engine('sqlite://', creator=creator)
engine.connect()发布于 2016-02-02 00:46:57
您应该避免在旧版本上传递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()发布于 2019-05-15 09:16:08
关于SQLAlchemy方言的SQLite文档详细描述了这个问题并给出了解决方案:
线程/池行为 Pysqlite的默认行为是禁止在多个线程中使用单个连接。这最初是为了处理在各种情况下不支持多线程操作的较早版本的SQLite。特别是,旧的SQLite版本不允许在任何情况下在多个线程中使用内存:数据库。 Pysqlite确实包含一个名为
check_same_thread的无文档标记,它将禁用此检查,但是请注意,在多线程中并发使用pysqlite连接仍然不安全。特别是,任何语句执行调用都需要外部互斥,因为Pysqlite不提供线程安全传播错误消息等功能。因此,即使是:memory:数据库也可以在现代SQLite中的线程之间共享,但是Pysqlite并没有提供足够的线程安全来实现这种使用。 SQLAlchemy设置池以处理Pysqlite的默认行为:
:memory: SQLite数据库时,默认情况下方言将使用SingletonThreadPool。这个池维护每个线程一个连接,以便当前线程中对引擎的所有访问都使用相同的:memory:数据库--其他线程将访问不同的:memory:数据库。NullPool作为连接的源。此池关闭并丢弃立即返回到池的连接。基于SQLite文件的连接开销极低,因此不需要池。该方案还防止在不同线程中再次使用连接,并且最好地处理SQLite的粗粒度文件锁定。在多线程中使用内存数据库
要在多线程场景中使用:memory:数据库,必须在线程之间共享相同的连接对象,因为数据库只存在于该连接的范围内。StaticPool实现将全局维护单个连接,check_same_thread标志可以作为False传递给Pysqlite。
从sqlalchemy.pool导入StaticPool engine = create_engine('sqlite://',connect_args={‘check_StaticPool_线程’:False},poolclass=StaticPool)
注意,在多个线程中使用:memory:数据库需要最新版本的SQLite。
来源:https://docs.sqlalchemy.org/en/13/dialects/sqlite.html#threading-pooling-behavior
https://stackoverflow.com/questions/27910829
复制相似问题