You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

每分钟多次更新数据库表的正确方式及cursor已关闭异常排查

问题分析与解决方案

你的当前实现完全错误,出现cursor already closed异常和操作冲突的核心原因是:psycopg2的数据库连接和游标不是线程安全的,绝对不能在多线程间共享全局实例。多线程同时操作同一个连接/游标时,会导致内部状态混乱——比如一个线程关闭了游标,另一个线程还在尝试使用,就会抛出游标已关闭的异常。

不要用全局连接/游标,也不需要加锁

加锁确实能避免多线程冲突,但会让所有更新操作串行执行,在每分钟600次调用的场景下,性能会暴跌,这是治标不治本的方案。正确的思路是让每个线程/每次请求使用独立的连接和游标。

基础改进:每次调用创建独立连接

直接在函数内创建和销毁连接,逻辑简单,对于大多数场景已经够用:

def update_data(name, type, value):
    # 每次调用创建新连接
    conn = psycopg2.connect(dbname='MyDB', user='...', password='...', host='127.0.0.1')
    try:
        with conn.cursor() as cursor:
            cursor.execute("UPDATE Datas SET Value = %s WHERE Name = %s and Type = %s", (value, name, type))
        conn.commit()
    finally:
        # 无论成功失败都关闭连接
        conn.close()

def get_all_data():
    conn = psycopg2.connect(dbname='MyDB', user='...', password='...', host='127.0.0.1')
    try:
        with conn.cursor() as curs:
            curs.execute('SELECT * FROM Datas')
            return curs.fetchall()
    finally:
        conn.close()

优化方案:使用连接池

针对每分钟600次的高频率调用,推荐用连接池复用连接,减少连接创建/销毁的开销,同时保证线程安全。psycopg2自带连接池实现:

from psycopg2 import pool

# 初始化连接池,根据并发量调整最小/最大连接数
# 比如最小2个,最大10个,避免连接过多耗尽数据库资源
connection_pool = pool.SimpleConnectionPool(
    minconn=2,
    maxconn=10,
    dbname='MyDB',
    user='...',
    password='...',
    host='127.0.0.1'
)

def update_data(name, type, value):
    # 从连接池获取连接
    conn = connection_pool.getconn()
    try:
        with conn.cursor() as cursor:
            cursor.execute("UPDATE Datas SET Value = %s WHERE Name = %s and Type = %s", (value, name, type))
        conn.commit()
    finally:
        # 将连接放回连接池,供后续请求复用
        connection_pool.putconn(conn)

def get_all_data():
    conn = connection_pool.getconn()
    try:
        with conn.cursor() as curs:
            curs.execute('SELECT * FROM Datas')
            return curs.fetchall()
    finally:
        connection_pool.putconn(conn)

关键注意事项

  • 永远不要在多线程环境下共享psycopg2的连接或游标实例,这是官方明确禁止的行为。
  • 连接池的最大连接数不要设置过大,否则会导致数据库连接耗尽,一般根据并发线程数调整即可。
  • 务必保证连接使用后放回连接池(或关闭),避免连接泄漏。

内容的提问来源于stack exchange,提问作者Fresto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:42:38