引用“如何在Python多处理或os.fork()中使用引擎/连接/会话?”
特别强调:
SQLAlchemy Engine对象引用现有数据库连接的连接池。因此,当将此对象复制到子进程时, 目标是确保没有数据库连接被继承 。
和
但是,对于共享事务活动会话或连接的情况,没有自动解决方案。应用程序需要确保新的子进程仅启动新的Connection对象和事务以及ORM
Session对象。
问题源自分叉的子进程继承了live global
session,而live全局仍保持不变
Connection。当
target调用时
init,它将覆盖对
engine和的全局引用
session,从而将其子代中的refcounts减少为0,从而迫使它们最终确定。例如,如果您以一种方式或另一种方式在子代中创建对继承的会话的另一个引用,则可以防止对该子代进行清理,但不要这样做。后
main加入并返回到一切如常它试图用现在完成潜在的-
或以其他方式不同步-连接。至于为什么这只会在经过一定数量的迭代后才导致错误,我不确定。
使用全局变量处理这种情况的唯一方法是
- 关闭所有会议
- 呼叫
engine.dispose()
在分叉之前。这将防止连接泄漏到孩子。例如:
def main(): global session init() try: dummy = Dummy(value=1) session.add(dummy) session.commit() dummy_id = dummy.id # Return the Connection to the pool session.close() # Dispose of it! engine.dispose() # ...or call your cleanup() function, which does the same p = multiprocessing.Process(target=target, args=(dummy_id,)) p.start() p.join() # Start a new session session = Session() dummy = session.query(Dummy).get(dummy_id) assert dummy.value == 2 finally: cleanup()
您的第二个示例不会在子级中触发终结处理,因此它似乎只能工作,尽管它可能与第一个示例一样坏,因为它仍继承会话的副本及其在本地定义的连接
main。



