在使用:memory:
中创建的SQLite base(通过sqlalchemy)时,我的脚本无法通过测试,并在使用使用物理文件创建的基础时通过测试。
脚本是多线程的。我知道将SQLite用于多个线程(锁定等)并不是最好的想法,但我只使用SQLite来测试脚本的数据库接口。
当我使用:memory:
时,脚本死于抱怨没有表:
OperationalError: (OperationalError)
no such table: content_info u'INSERT INTO content_info ...
测试程序(nose)如下:
def setup_database():
global global_engine
# create database columns
engine = sqlalchemy.create_engine(...)
Base.metadata.create_all(engine)
global_engine = engine
@with_setup(setup_database)
def test_task_spoolers():
check_database_content_from_another_thread()
def check_database_content_from_another_thread():
global global_engine
# from within other thread
# create new session using global_engine
# do some inserts
所以在设置中我做创建数据库和列。我也可以在日志(echo=True
)中看到它:
12:41:08 INFO sqlalchemy.engine.base.Engine
CREATE TABLE content_info (...
12:41:08 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
12:41:08 INFO sqlalchemy.engine.base.Engine INSERT INTO
content_info (base_id, request_id, timestamp, ...
12:41:08 INFO sqlalchemy.engine.base.Engine (0, 0, 0, 'dummy_variant',
None, 0)
12:41:08 INFO sqlalchemy.engine.base.Engine ROLLBACK
Exception in thread Thread-1:
Traceback (most recent call last):
OperationalError: (OperationalError)
no such table: content_info u'INSERT INTO ...
我的猜测是,当我在线程A中创建基础,然后我在线程B中使用它时,B在实际创建之前就开始在基础上运行。但是,我在time.sleep(3)
之后添加了create_all
,但它无效。
并且,如前所述,它在我使用文件而不是:memory:
时起作用,即使文件放在虚拟分区上(因此,实际上在内存中)。知道为什么会这样吗?
答案 0 :(得分:11)
您无法创建与内存数据库的多个连接。相反,与:memory:
的新连接会创建新数据库。
每一个:内存:数据库彼此不同。因此,打开两个数据库连接,每个连接的文件名为“:memory:”,将创建两个独立的内存数据库。
这与磁盘数据库不同,其中使用相同的连接字符串创建多个连接意味着您将连接到一个数据库。
您正在为该线程创建一个新连接,从而创建一个没有创建表的 new 数据库。
答案 1 :(得分:0)
您可以使用这种方法来共享多个线程之间的连接:
from sqlalchemy.pool import StaticPool
engine = create_engine('sqlite://',
connect_args {'check_same_thread':False},
poolclass=StaticPool)