【问题标题】:What is correct way to use psycopg2 cursors in threads?在线程中使用 psycopg2 游标的正确方法是什么?
【发布时间】:2021-02-12 13:12:21
【问题描述】:

我觉得我的问题的答案在这两个 SO 问题中,但我发现答案的措辞非常糟糕(或高于我的工资等级)

  1. multi thread python psycopg2
  2. Are transactions in PostgreSQL via psycopg2 per-cursor or per-connection?

问题:使用 psycopg2 确保线程安全的正确方法是什么

选项 1:每个线程都有自己的光标

import threading
import psycopg2

conn = psycopg2.connect (
    host=127.0.0.1,
    user='john',
    password='1234',
    dbname='foo',
    port=1234)

class Foo (threading.Thread):
    def __init__ (self):
        threading.Thread.__init__(self)

    def run (self):
        global conn

        cur = conn.cursor()
        sql_query="SELECT * from foo;"
        print(cur.execute (sql_query))
        conn.commit()

num_threads = 100
threads = []

for i in seq (num_threads):
    threads.append (Foo())

for i in seq (num_threads):
    threads[i].start()

for i in seq (num_threads):
    threads[i].join()

选项 2:每个线程都有自己的连接

import threading
import psycopg2

db_conn = psycopg2.connect (
    host=127.0.0.1,
    user='john',
    password='1234',
    dbname='foo',
    port=1234)

class Foo (threading.Thread):
    def __init__ (self):
        threading.Thread.__init__(self)
        self.conn = psycopg2.connect (
            host=127.0.0.1,
            user='john',
            password='1234',
            dbname='foo',
            port=1234)

    def run (self):
        cur = self.conn.cursor()
        sql_query="SELECT * from foo;"
        print(cur.execute (sql_query))
        conn.commit()

num_threads = 100
threads = []

for i in seq (num_threads):
    threads.append (Foo())

for i in seq (num_threads):
    threads[i].start()

for i in seq (num_threads):
    threads[i].join()

【问题讨论】:

    标签: python-3.x postgresql psycopg2 psql


    【解决方案1】:

    每个线程都应该有自己的数据库连接。

    一个 PostgreSQL 连接在给定时间只能处理一个语句(除非您使用 server side cursor,但即便如此,该连接也只能同时处理一个 FETCH)。

    因此,如果多个线程要共享一个数据库连接,它们必须仔细协调以确保只有一个线程同时使用该连接。例如,您不能在另一个线程仍在等待查询结果时发送新查询。

    【讨论】:

    • 谢谢。如果我可能很贪心,您能否快速评论一下数据库连接过多是否存在性能/瓶颈问题?
    • 数据库连接过多绝对是个坏主意。这就是您使用包含有限数量的持久数据库连接的连接池 的原因。对于线程想要执行的每个事务,您获取一个池连接并在完成后返回它。我确信 psycopg2 中有内置的连接池。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多