多处理模块和不同的 psycopg2 连接
multiprocessing module and distinct psycopg2 connections
我对一些使用 psycopg2 与 postgres 数据库并行查询的多处理代码的行为感到非常困惑。
本质上,我正在对更大 table 的各个分区进行相同的查询(使用不同的参数)。我正在使用 multiprocessing.Pool 分叉一个单独的查询。
我的多处理调用如下所示:
pool = Pool(processes=num_procs)
results=pool.map(run_sql, params_list)
我的 run_sql 代码如下所示:
def run_sql(zip2):
conn = get_connection()
curs = conn.cursor()
print "conn: %s curs:%s pid=%s" % (id(conn), id(curs), os.getpid())
...
curs.execute(qry)
records = curs.fetchall()
def get_connection()
...
conn = psycopg2.connect(user=db_user, host=db_host,
dbname=db_name, password=db_pwd)
return conn
所以我的期望是每个进程都会通过调用 get_connection()
获得一个单独的数据库连接,并且 print id(conn)
会显示一个不同的值。但是,情况似乎并非如此,我无法解释。连 print id(curs)
都一样。只有 print os.getpid()
显示出差异。它是否以某种方式为每个分叉进程使用相同的连接?
conn: 4614554592 curs:4605160432 pid=46802
conn: 4614554592 curs:4605160432 pid=46808
conn: 4614554592 curs:4605160432 pid=46810
conn: 4614554592 curs:4605160432 pid=46784
conn: 4614554592 curs:4605160432 pid=46811
我想我已经弄明白了。答案在于 Python 中的多处理是无共享的,因此整个内存 space 都被复制,函数和所有。因此,对于每个进程,即使 pid 不同,内存 space 也是彼此的副本,并且内存 space 中的连接地址最终是相同的。同样的原因是为什么像我最初那样声明一个全局连接池是没有用的,每个进程最终都有自己的连接池,一次只有 1 个连接处于活动状态。
我对一些使用 psycopg2 与 postgres 数据库并行查询的多处理代码的行为感到非常困惑。
本质上,我正在对更大 table 的各个分区进行相同的查询(使用不同的参数)。我正在使用 multiprocessing.Pool 分叉一个单独的查询。
我的多处理调用如下所示:
pool = Pool(processes=num_procs)
results=pool.map(run_sql, params_list)
我的 run_sql 代码如下所示:
def run_sql(zip2):
conn = get_connection()
curs = conn.cursor()
print "conn: %s curs:%s pid=%s" % (id(conn), id(curs), os.getpid())
...
curs.execute(qry)
records = curs.fetchall()
def get_connection()
...
conn = psycopg2.connect(user=db_user, host=db_host,
dbname=db_name, password=db_pwd)
return conn
所以我的期望是每个进程都会通过调用 get_connection()
获得一个单独的数据库连接,并且 print id(conn)
会显示一个不同的值。但是,情况似乎并非如此,我无法解释。连 print id(curs)
都一样。只有 print os.getpid()
显示出差异。它是否以某种方式为每个分叉进程使用相同的连接?
conn: 4614554592 curs:4605160432 pid=46802
conn: 4614554592 curs:4605160432 pid=46808
conn: 4614554592 curs:4605160432 pid=46810
conn: 4614554592 curs:4605160432 pid=46784
conn: 4614554592 curs:4605160432 pid=46811
我想我已经弄明白了。答案在于 Python 中的多处理是无共享的,因此整个内存 space 都被复制,函数和所有。因此,对于每个进程,即使 pid 不同,内存 space 也是彼此的副本,并且内存 space 中的连接地址最终是相同的。同样的原因是为什么像我最初那样声明一个全局连接池是没有用的,每个进程最终都有自己的连接池,一次只有 1 个连接处于活动状态。