【问题标题】:Sharing DB client among multiple processes in Python?在 Python 中的多个进程之间共享数据库客户端?
【发布时间】:2021-12-31 04:35:19
【问题描述】:

我的 python 应用程序使用 concurrent.futures.ProcessPoolExecutor 和 5 个工作人员,每个进程进行多个数据库查询。

选择为每个进程提供自己的数据库客户端,还是让所有进程共享一个客户端,这被认为更安全和传统?

【问题讨论】:

    标签: python python-3.x concurrent.futures


    【解决方案1】:

    简答:为每个进程(需要它)提供自己的数据库客户端。

    长答案:你想解决什么问题?

    在进程之间共享数据库客户端基本上不会发生;您必须拥有一个进程,它确实让数据库客户端代理来自其他人的查询,使用或多或少自己的协议。如果该协议特定于您的应用程序,这可能会带来好处,但它会增加复杂性:您的程序中现在将有两种不同类型的工作程序,而不仅仅是一种,加上它们之间的协议。您需要确保好处大于额外的复杂性。

    通常可以在线程之间共享数据库客户端;您必须查看文档以查看哪些对象和操作是“线程安全的”。但是,由于您的应用程序在其他方面占用大量 CPU,因此由于 Python 限制(GIL),线程不适合。

    同时,在每个进程中拥有一个 DB 客户端的成本很低;在任何情况下,您都需要一些类型的客户,它也可能是直接客户。

    不会有更多的 IO,因为这主要基于查询的总数和数据量,无论是来自一个进程还是分散在多个进程中。唯一的额外 IO 将在登录中,这并不多。

    如果您的数据库连接不足,您可以调整/升级您的数据库以获得更多连接,或者使用单独的现成“连接池”来共享它们;这可能比尝试从头开始实现连接池要好得多。

    更一般地说,这远远超出了这个特定的问题,通常最好以直接的方式组合几个现成的部分,而不是尝试将一个定制的复杂部分组合在一起来完成所有事情一次。

    那么,你想解决什么问题?

    【讨论】:

    • 谢谢,我只需要完成多个任务,其中每个任务独立执行相当数量的数据库查询(IO 密集型),然后使用 matplotlib 绘制结果。 (CPU 密集型)。我更喜欢多处理,但是通过这种方法,我很难共享一个通用模块(即全局记录器)?
    • 同样,使用现成的日志记录比自己滚动更容易
    【解决方案2】:

    最好使用多线程或异步方法而不是多处理,因为它会消耗更少的资源。这样你就可以使用单个数据库连接,但我建议为每个工作程序或协程创建一个单独的会话,以避免一些异常或锁定问题。

    【讨论】:

    • 如果不讨论 GIL 等权衡取舍,这真的不是一个完整的答案吗?
    • 应用程序将在查询后绘制一些图形(使用 matlibplot),这非常占用 CPU。就 DB IO 而言,多处理是否比多线程更糟糕?
    • DB IO 不会有太大不同...
    • ...而 Python GIL 会降低线程中任何 CPU 密集型的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 2013-06-20
    相关资源
    最近更新 更多