首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sqlalchemy和SQLite共享缓存

sqlalchemy和SQLite共享缓存
EN

Stack Overflow用户
提问于 2015-01-12 21:13:52
回答 2查看 4.9K关注 0票数 20

SQLite支持使用特殊URI打开:memory:数据库时的“共享缓存”(根据sqlite.org):

内存中的相同数据库可以由两个或多个数据库连接打开,如下所示: rc = sqlite3_open("file::memory:?cache=shared",&db);

我可以在Python3.4中利用这一点,使用URI参数 for sqlite3.connect()

代码语言:javascript
复制
sqlite3.connect('file::memory:?cache=shared', uri=True)

然而,对于SQLAlchemy,我似乎无法做到同样的事情:

代码语言:javascript
复制
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版本上:

代码语言:javascript
复制
creator = lambda: sqlite3.connect('file::memory:?cache=shared', uri=True)
engine = sqlalchemy.create_engine('sqlite://', creator=creator)
engine.connect()
EN

回答 2

Stack Overflow用户

发布于 2016-02-02 00:46:57

您应该避免在旧版本上传递uri=True,问题将得到解决:

代码语言:javascript
复制
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()
票数 9
EN

Stack Overflow用户

发布于 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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27910829

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档