Python 线程 - 访问 PostgreSQL 时崩溃

1 投票
2 回答
1487 浏览
提问于 2025-04-15 12:59

这里有一个简单的多线程程序,运行得很好:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency

    def run(self):
        global SQLConnection
        global cursor
        SQLString = "Select dval from ddata where dname ='%s' and ddate = '2009-07-17'" \
                %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            print SQLString

SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
cursor = SQLConnection.cursor()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()

但是,一旦我尝试在线程中访问postgresql数据库,使用以下代码时,我总是会遇到崩溃的问题:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency

    def run(self):
        global SQLConnection
        global cursor
        SQLString = "Select dval from ddata where dname ='%s'and ddate = '2009-07-17'" %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            cursor.execute(SQLString)
            print cursor.fetchall()

SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
cursor = SQLConnection.cursor()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()

这两者之间唯一的区别在于while循环。我对多线程编程还比较陌生。请问postgres库(psycopg2)是不是不“线程安全”?这一切都是在Windows XP上运行的。我能做些什么呢?

谢谢。

2 个回答

0

太好了,问题解决了。之前有人给出了一个答案,但后来似乎把它删掉了,答案是给每个线程分配一个独立的连接。果然,这样做就解决了问题。所以这段代码可以正常运行:

import psycopg2
import threading
import time

class testit(threading.Thread):
    def __init__(self, currency):
        threading.Thread.__init__(self)
        self.currency = currency 
        self.SQLConnection = psycopg2.connect(database = "db", user = "xxxx", password = "xxxx")
        self.cursor = self.SQLConnection.cursor()

    def run(self):
        SQLString = "Select dval from ddata where dname ='%s' and ddate = '2009-07-17'" \
                %self.currency
        z = time.time()
        while (time.time() - z) < 2:
            self.cursor.execute(SQLString)
            print self.cursor.fetchall()

a = testit('EURCZK')
b = testit('EURPLN')
a.start()
b.start()
2
global SQLConnection
global cursor

看起来你是在多个线程中访问全局变量?你绝对不应该这样做,除非这些全局变量是线程安全的,或者你自己提供了合适的锁定机制。

现在你有两个线程在同时访问同一个连接和同一个游标,它们会互相干扰。虽然psycopg2的连接可能是线程安全的,但游标却不是。

每个线程应该使用一个游标(可能也要使用一个连接)。

撰写回答