Python、线程、SQLalchemy

2 python multithreading sqlalchemy

我的 Python 无限循环检测运行线程的操作 - Python next 函数。每个线程都使用 SQLalchemy 对象来操作(相同的)MySQL DB。该线程会在几个小时甚至几天内启动,或者同时启动多个线程 - 取决于用户活动。使用数据库的最佳方式是什么/应该是什么?他们所有人都可以使用相同的全局数据库对象,或者他们每个人都应该创建新的?

Iva*_*hoo 5

请注意,SQLAlchemy 会话/连接不是线程安全的

\n\n
\n

Session 对象完全设计为以非并发方式使用,就多线程而言,这意味着 \xe2\x80\x9 一次仅在一个线程中\xe2\x80\x9d。

\n
\n\n

简而言之,每个会话都有一个后备存储来跟踪会话中添加/删除/修改的所有对象(模型实例)。跨线程共享会话和跟踪对象不会很好地使用此后备存储,因为您无法保证线程安全。

\n\n

您可以使用scoped_session它提供会话对象(和底层连接池)的范围管理。这样,您的会话就绑定到线程局部作用域,并且您可以在线程操作中使用单个会话,而不必担心并发性。

\n\n
\n

我们将此概念称为线程本地存储,这意味着使用一个特殊的对象来为每个应用程序线程维护一个不同的对象。Python 通过 threading.local() 构造提供此功能。

\n
\n\n

Ascoped_session用作存储,并且在单个线程范围内调用时维护theading.local()Single 。session来自不同线程的调用者scoped_session将获得不同的session对象。

\n\n
from sqlalchemy.orm import scoped_session\nfrom sqlalchemy.orm import sessionmaker\n\n# Note that session_factory, some_engine, \n# and scoped_session are global objects\nsession_factory = sessionmaker(bind=some_engine)\nSession = scoped_session(session_factory)\n\n# Calls to `Session` will return a `session` object\n# that is backed by a thread-local store\nsome_session = Session()\n\n# Somewhere down the line you call `Session` again \n# within the same thread will yield the same session object\n\nsome_other_session = Session()\nsome_session is some_other_session # True\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

上面,some_session 是 Session 的一个实例,我们现在可以用它来与数据库对话。这个会话也存在于我们创建的scoped_session注册表中。如果我们第二次调用注册表,我们将返回相同的会话:

\n
\n\n
# All objects managed by `some_session` is stored in thread-local \nsome_session.add(..)\nsome_session.remove(..)\nsome_session.query(..)\nsome_session.commit() # or .rollback()\n\n# Calling `Session.remove()` closes `some_session`\n# and returns the `connection` back to the pool for reuse\nSession.remove()\n
Run Code Online (Sandbox Code Playgroud)\n\n

重要的是调用Session.remove()(这里的 Session 是 a scoped_session)而不是仅仅调用some_session.close()。这具有清理工作的效果。

\n\n
\n

scoped_session.remove() 方法首先对当前 Session 调用 Session.close() ,其作用是首先释放 Session 拥有的任何连接/事务资源,然后丢弃 Session 本身。\xe2\x80\x9cReleasing\xe2\x80\x9d 这里意味着连接被返回到它们的连接池,并且任何事务状态都被回滚,最终使用底层 DBAPI 连接的 rollback() 方法。

\n
\n