【问题标题】:SQLAlchemy/Python: Using an engine per process, and injecting that engine into dependenciesSQLAlchemy/Python:每个进程使用一个引擎,并将该引擎注入依赖项
【发布时间】:2014-08-17 18:39:21
【问题描述】:

SQLAlchemy 建议每个进程使用一个引擎,因为底层 DBAPI 连接不一定可以安全地跨进程使用。

我有全局的 enginesession 变量,它们分别被 SQLAlchemy 引擎和会话工厂懒惰地填充。这使得编写依赖的数据库帮助程序变得容易,这些帮助程序可以在运行时调用 get_session() 以在 init_db 为其分配值后使用 session 变量。

这对于让需要访问enginesession 的助手在初始化enginesession 之前导入非常有效。但是这种模式使我无法在全局范围内使用enginesession

但是,我真正需要做的是:

engine, session = init_db(DB_URL)

...来自调用应用程序/方法,然后将会话注入这些数据库助手。为什么?好吧,我需要每个进程使用一个引擎。我想我在这里需要一种控制模式的反转,但是在想出一些可行的方法时遇到了麻烦(这不涉及在每次调用时将会话传递给助手,这很笨拙,也是最后的手段)。

我想我可以在os.fork() 之后设置引擎。每个进程都以engine=None 开头,然后实例化它。但是engine 在父进程和子进程中具有相同的内存地址。这是有道理的;这就是 Python 的工作原理。

from utils import init_db, engine, DB_URL
import os

def connect():
    print('before fork, engine is: {}'.format(id(engine)))
    newpid = os.fork()

    if newpid == 0:
        init_db(DB_URL)
        print('child engine is: {}'.format(id(engine))) # id(engine) is equal to below call
    else:
        init_db(DB_URL)
        print('parent engine is: {}'.format(id(engine))) # id(engine) is equal to above call

if __name__ == '__main__':
    connect()

根据进程 ID 创建排序池是我的最佳选择吗?如果可能的话,我想使用一个干净的控制模式反转。

NullPool 不会汇集连接,并且可以完成这项工作,但我认为这不是一件好事 - 不断打开和关闭连接似乎很昂贵?

Python 版本:3.4.0

SQLAlchemy 版本:0.9.7

【问题讨论】:

    标签: python sqlalchemy inversion-of-control python-3.4


    【解决方案1】:

    id() 结果由于虚拟内存而具有欺骗性。您的 Python 对象在 fork() 之后彼此独立运行,并且不共享对其状态的修改。问题是 pre-fork 打开的文件、管道和套接字将被共享,这就是为什么如果您使用连接池则需要单独的引擎。

    如果不知道您的init_db 具体做什么,如果引擎是在fork 之后创建的,您应该没问题 - 每个进程都有自己的打开套接字。将import 移到fork 之后可能会更清晰,也可以明确您的意图。

    【讨论】:

    • init_db 在第二次调用的结果上调用 SQLAlchemy 方法 create_enginesessionmaker(bind=engine)scoped_session(),然后是 create_all_tables()。如果我在fork之前在父进程中调用init_db,并将engine分配给子进程中init_db返回的新引擎呢?那是我的实际用例。但这样做会导致“psycopg2.OperationalError:SSL 连接已意外关闭”。
    • create_engine 应该在fork 之后。我认为您的其他模型设置也可以,但是如果有理由需要在分叉前设置它,您可以关闭 bind 参数,然后在创建引擎后设置它们。
    猜你喜欢
    • 2022-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多