在python多进程之间共享一个postgres连接池

los*_*ost 6 python postgresql psycopg2 multiprocessing

我正在尝试将 psycopg2 的连接池与 python 的多进程库一起使用。

目前,尝试以上述方式在线程之间共享连接池会导致:

psycopg2.OperationalError: SSL error: decryption failed or bad record mac
Run Code Online (Sandbox Code Playgroud)

下面的代码应该重现错误,警告读者必须设置一个简单的 postgres 数据库。

psycopg2.OperationalError: SSL error: decryption failed or bad record mac
Run Code Online (Sandbox Code Playgroud)

我已经尝试过的:

  1. 让每个进程打开和关闭自己的数据库连接,而不是尝试使用连接池。这很慢。
  2. 让每个进程使用自己的连接池,这也很慢。
  3. 将连接传递给每个进程的 psycopg2 连接对象,而不是使用withsql 查询中的语句隐式调用它。这会引发一个错误,声称连接对象不可pickle。

注意:如果我sleep在除一个进程之外的所有进程中进行操作,非休眠进程运行良好并执行其查询,直到其余线程不休眠,然后我收到上述错误。

我已经读过的:

  1. 在 Python 中跨进程共享与 postgres 数据库的连接
  2. Python:从线程调用时解密失败或错误记录mac
  3. SQLAlchemy 和多个进程的连接问题

最后:

如何将连接池 (psycopg2) 与 python 的多进程(多处理)一起使用。我愿意使用其他库,只要它们与 python 和 postgresql 数据库一起工作。

los*_*ost 1

这是我的解决方案。解决方案可以分为两部分:

  1. 有一个将由每个唯一进程执行的包装函数。这个包装函数的主要目的是创建自己的连接池
  2. 对于步骤 1 中包装函数执行的每个查询,将连接池传递给查询函数(在上面的示例中,这是test_query

更详细地参考问题中的示例:

步骤1

创建将在每个进程中重复使用一个连接池的包装函数:

def multi_query(list_of_cols):
    # create a new connection pool per Process
    new_pool = new_connection_pool()

    # Pass the pool to each query
    for col in list_of_cols:
        test_query(col, new_pool)
Run Code Online (Sandbox Code Playgroud)

第2步

修改查询函数以接受连接池:

老的test_query

def test_query(col_attribute):
    """
    Simple SQL query
    """
    query = f"""SELECT *
                FROM col
                WHERE col = {col_attribute}
                ;"""
   with ConnectionFromPool() as cursor:
        cursor.execute(query)
        result = cursor.fetchall()
   return result
Run Code Online (Sandbox Code Playgroud)

新的test_query

def test_query(col_attribute, connection_pool=None):
    """
    Simple SQL query
    """
    query = f"""SELECT *
                FROM col
                WHERE col = {col_attribute}
                ;"""
    with ConnectionFromPool(connection_pool) as cursor:
        cursor.execute(query)
        result = cursor.fetchall()
    return result
Run Code Online (Sandbox Code Playgroud)