Python sqlalchemy和SQLite共享缓存
SQLite支持使用特殊URI打开Python sqlalchemy和SQLite共享缓存,python,sqlite,sqlalchemy,Python,Sqlite,Sqlalchemy,SQLite支持使用特殊URI打开:内存:数据库时的“共享缓存”(根据): [T] 同一内存数据库可以由两个或多个数据库打开 连接如下: rc=sqlite3\u open(“文件::内存:?缓存=共享”,&db) 通过使用forsqlite3.connect(),我可以在Python 3.4中利用这一点: 然而,我似乎无法让SQLAlchemy实现同样的功能: engine = sqlalchemy.create_engine('sqlite:///:memory:?cache=shared'
:内存:
数据库时的“共享缓存”(根据):
[T] 同一内存数据库可以由两个或多个数据库打开
连接如下:
rc=sqlite3\u open(“文件::内存:?缓存=共享”,&db)代码>
通过使用forsqlite3.connect()
,我可以在Python 3.4中利用这一点:
然而,我似乎无法让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
参数create\u engine
来解决这个问题,但在其他Python版本上仍然存在这个问题:
creator = lambda: sqlite3.connect('file::memory:?cache=shared', uri=True)
engine = sqlalchemy.create_engine('sqlite://', creator=creator)
engine.connect()
您应该避免在较旧的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()
关于SQLite方言的SQLAlchemy文档详细描述了问题和解决方案:
线程/池行为
Pysqlite的默认行为是禁止
在多个线程中使用单个连接。这是
最初打算使用不支持的SQLite的旧版本
支持各种情况下的多线程操作。在里面
特别是,较旧的SQLite版本不允许:memory:数据库
在任何情况下都可以在多个线程中使用
Pysqlite确实包含一个现在未记录的标志,称为
check\u same\u thread
将禁用此检查,但请注意
pysqlite连接在中并发使用仍然不安全
多线程。特别是,任何语句执行调用都会
需要进行外部静音,因为Pysqlite不提供
错误消息的线程安全传播。那么一会儿
甚至:内存:
数据库可以在现代SQLite中的线程之间共享,
Pysqlite没有提供足够的线程安全性,因此不值得使用它
它
SQLAlchemy设置池以使用Pysqlite的默认行为:
- 当指定
:memory:
SQLite数据库时,默认情况下方言为
将使用SingletonThreadPool
。此池维护单个连接
每个线程,以便在当前线程内对引擎的所有访问
使用相同的:内存:
数据库-其他线程将访问
不同的:内存:
数据库
- 指定基于文件的数据库时,方言将使用
NullPool
作为连接的来源。此池关闭并丢弃
立即返回到池的连接。数据库
基于文件的连接具有极低的开销,因此不需要池
必要的。该方案还防止再次使用连接
在不同的线程中,使用SQLite的粗粒度文件效果最好
锁定
在多线程中使用内存数据库
要使用:内存:
数据库
在多线程场景中,必须共享相同的连接对象
在线程之间,因为数据库只存在于该线程的范围内
连接。StaticPool
实现将维护一个
全局连接,并且可以将check\u same\u thread
标志传递给
Pysqlite为False
:
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
connect_args={'check_same_thread':False},
poolclass=StaticPool)
请注意,在多线程中使用:memory:
数据库需要最新版本的SQLite
来源:如果不将新的sqlite3模块功能向后移植到早期版本,我认为你无法做到这一点。亲爱的上帝,每个线程(不是进程)都有自己的独立数据库(不能与另一个线程的数据库通信)这一事实是微妙的。这篇文章节省了我几天的精力。
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
connect_args={'check_same_thread':False},
poolclass=StaticPool)