bba*_*les 17 python sqlite sqlalchemy
:memory:当使用特殊URI打开数据库时,SQLite支持数据库的"共享缓存" (根据sqlite.org):
[T]他可以通过两个或多个数据库连接打开相同的内存数据库,如下所示:
rc = sqlite3_open("file::memory:?cache=shared",&db);
我可以通过利用这个在Python 3.4 URI参数为sqlite3.connect():
sqlite3.connect('file::memory:?cache=shared', uri=True)
Run Code Online (Sandbox Code Playgroud)
但是,我似乎无法为SQLAlchemy工作:
engine = sqlalchemy.create_engine('sqlite:///:memory:?cache=shared')
engine.connect()
...
TypeError: 'cache' is an invalid keyword argument for this function
Run Code Online (Sandbox Code Playgroud)
有没有办法让SQLAlchemy使用共享缓存?
编辑:
在Python 3.4上,我可以使用creator参数create_engine来解决问题,但问题仍然存在于其他Python版本中:
creator = lambda: sqlite3.connect('file::memory:?cache=shared', uri=True)
engine = sqlalchemy.create_engine('sqlite://', creator=creator)
engine.connect()
Run Code Online (Sandbox Code Playgroud)
关于 SQLite 方言的 SQLAlchemy 文档详细描述了问题和解决方案:
\n\n\n\n\n线程/池行为
\n\nPysqlite\xe2\x80\x99s 默认行为是禁止在多个线程中使用单个连接。这最初是为了与旧版本的 SQLite 一起使用,而旧版本的 SQLite 在各种情况下不支持多线程操作。特别是,旧版 SQLite 不允许在任何情况下在多线程中使用 :memory: 数据库。
\n\nPysqlite 确实包含一个现在未记录的标志,
\n\ncheck_same_thread该标志将禁用此检查,但请注意,在多个线程中同时使用 pysqlite 连接仍然不安全。特别是,任何语句执行调用都需要在外部进行互斥,因为 Pysqlite 不提供错误消息的线程安全传播。因此,虽然:memory:数据库可以在现代 SQLite 中的线程之间共享,但 Pysqlite 并没有提供足够的线程安全性来使这种使用值得。SQLAlchemy 设置池以与 Pysqlite\xe2\x80\x99s 默认行为一起使用:
\n\n\n
\n\n- \n
当
:memory:指定 SQLite 数据库时,方言默认\n 将使用SingletonThreadPool。该池为每个线程维护一个连接,以便当前线程内对引擎的所有访问都使用相同的:memory:数据库 - 其他线程将访问不同的:memory:数据库。- \n
当指定基于文件的数据库时,方言将使用
NullPool\n 作为连接源。此池关闭并丢弃立即返回到池的连接。SQLite 基于文件的连接的开销极低,因此不需要池。该方案还可以防止连接在不同的线程中再次使用,并且与 SQLite\xe2\x80\x99s 粗粒度文件锁定配合使用效果最佳。在多线程中使用内存数据库
\n\n若要在多线程方案中使用
\n\n:memory:数据库,必须在线程之间共享同一个连接对象,因为数据库仅存在于该连接的范围内。该StaticPool实现将在全局范围内维护单个连接,并且check_same_thread可以将标志传递给 Pysqlite,如下所示False:Run Code Online (Sandbox Code Playgroud)\n\nfrom sqlalchemy.pool import StaticPool\nengine = create_engine(\'sqlite://\',\n connect_args={\'check_same_thread\':False},\n poolclass=StaticPool)\n请注意,在多线程中使用
\n:memory:数据库需要最新版本的 SQLite。
来源:https ://docs.sqlalchemy.org/en/13/dialects/sqlite.html#threading-pooling-behavior
\n你应该避免传递uri=True较旧的Python版本,问题将得到解决:
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()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2195 次 |
| 最近记录: |