在线程中使用 psycopg2 游标的正确方法是什么?

puk*_*puk 5 postgresql psycopg2 python-3.x psql

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

  1. 多线程 python psycopg2
  2. PostgreSQL 中的事务是通过psycopg2每个游标还是每个连接进行的?

问题:使用 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()
Run Code Online (Sandbox Code Playgroud)

选项 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()
Run Code Online (Sandbox Code Playgroud)

Lau*_*lbe 6

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

一个 PostgreSQL 连接在给定时间只能处理一条语句(除非您使用服务器端游标,但即使如此,该连接同时也只能处理一条语句FETCH)。

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

  • 拥有太多的数据库连接绝对是一个坏主意。这就是为什么您使用包含有限数量的持久数据库连接的“连接池”。对于线程想要执行的每个事务,您都会获取一个池连接并在完成后将其返回。我确信 psycopg2 中有内置的连接池。 (2认同)