我想创建一个用Python编写的数据库应用程序编程接口,并使用SQLAlchemy(或任何其他数据库连接器,如果它被告知使用SQLAlchemy进行此类任务不是一个好方法)。该设置是在Linux或BSD上运行的MySQL服务器,以及在Linux或BSD机器上运行的Python软件(无论是外国还是本地)。
基本上我想要做的是为每个连接生成一个新线程,协议将是自定义的并且非常简单,尽管对于每个请求我想打开一个新事务(或者我已阅读的会话)然后我需要提交会话。我现在面临的问题是,另一个会话很可能同时从另一个连接发生。
我的问题是我应该怎样处理这种情况?
答案 0 :(得分:46)
会话对象不是线程安全的,但是线程本地。 From the docs:
“
Session
对象完全被设计为以非并发方式使用,在多线程方面意味着”一次仅在一个线程中“。某些进程需要在适当的位置,以便多个线程的多个调用实际上不会获得同一个会话的句柄。我们将这个概念称为线程本地存储。“
如果您不想自己管理线程和会话,SQLAlchemy有ScopedSession
对象来处理这个问题:
默认情况下,
ScopedSession
对象使用[threading.local()]作为存储,因此为所有调用Session
注册表的人维护一个ScopedSession
,但仅限于单个线程的范围。在另一个线程中调用注册表的调用者获得一个本地其他线程的Session实例。使用这种技术,
ScopedSession
提供了一种快速且相对简单的方法,可以在应用程序中提供可以安全地从多个线程调用的单个全局对象。
请参阅Contextual/Thread-local Sessions中的示例,了解如何设置自己的线程安全会话:
# set up a scoped_session
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
session_factory = sessionmaker(bind=some_engine)
Session = scoped_session(session_factory)
# now all calls to Session() will create a thread-local session
some_session = Session()
# you can now use some_session to run multiple queries, etc.
# remember to close it when you're finished!
Session.remove()