sqlalchemy和SQLite共享缓存

时间:2015-01-12 21:13:53

标签: python sqlite sqlalchemy

: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

2 个答案:

答案 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