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

Heroku部署Python应用使用ClearDB出现Connection reset by peer错误如何解决

问题根因

ClearDB默认会自动断开闲置时长超过阈值(免费版通常为30~60秒)的连接,若使用单长连接、未做有效性校验,再次调用已被服务端回收的连接时就会抛出Connection reset by peer错误。

方案1:使用MySQL Connector/Python内置连接池(推荐)

该方案通过连接池自动管理连接生命周期,配合主动回收机制避免拿到失效连接。

  1. 先安装依赖:
pip install mysql-connector-python
  1. 连接池实现代码:
import mysql.connector
from mysql.connector import pooling
from mysql.connector.errors import OperationalError, InterfaceError

# 可直接解析Heroku环境变量CLEARDB_DATABASE_URL获取对应参数
db_config = {
    "host": "ClearDB主机地址",
    "user": "数据库用户名",
    "password": "数据库密码",
    "database": "数据库名",
    "charset": "utf8mb4"
}

# 初始化连接池
connection_pool = pooling.MySQLConnectionPool(
    pool_name="cleardb_pool",
    pool_size=3,  # 单worker场景2-5即可,多worker需注意总连接数不超过ClearDB的连接数上限(免费版为10)
    pool_recycle=20,  # 核心参数:连接超过20秒自动回收重建,必须小于ClearDB的闲置超时时间
    **db_config
)

# 封装数据库操作方法
def execute_query(query, params=None):
    conn = None
    cursor = None
    try:
        # 从连接池获取连接
        conn = connection_pool.get_connection()
        # 额外校验连接有效性,极端场景下自动重连
        conn.ping(reconnect=True)
        cursor = conn.cursor(dictionary=True)
        cursor.execute(query, params or ())
        if query.strip().upper().startswith("SELECT"):
            return cursor.fetchall()
        else:
            conn.commit()
            return cursor.rowcount
    except (OperationalError, InterfaceError) as e:
        # 捕获连接断开类错误,重试一次
        if conn:
            try:
                conn.rollback()
                conn.close()
            except:
                pass
        # 重试获取新连接执行
        conn = connection_pool.get_connection()
        conn.ping(reconnect=True)
        cursor = conn.cursor(dictionary=True)
        cursor.execute(query, params or ())
        if query.strip().upper().startswith("SELECT"):
            return cursor.fetchall()
        else:
            conn.commit()
            return cursor.rowcount
    finally:
        if cursor:
            cursor.close()
        if conn:
            # 此处不是真的关闭连接,是将连接归还到连接池
            conn.close()
方案2:单连接加自动重连机制

如果场景简单不想用连接池,可以每次调用数据库前先校验连接有效性:

import mysql.connector
from mysql.connector.errors import OperationalError, InterfaceError

conn = None
db_config = {
    "host": "ClearDB主机地址",
    "user": "数据库用户名",
    "password": "数据库密码",
    "database": "数据库名",
    "charset": "utf8mb4"
}

def get_db_conn():
    global conn
    try:
        if conn and conn.is_connected():
            conn.ping(reconnect=True)
            return conn
    except (OperationalError, InterfaceError):
        pass
    # 连接失效则重建
    conn = mysql.connector.connect(**db_config)
    return conn
额外注意事项
  • 日志中同时出现了urllib3的连接重置错误,若你的脚本还会调用外部HTTP接口,需要给requests添加重试机制,避免第三方接口断开导致崩溃
  • ClearDB免费版连接数上限很低,不要把连接池大小设置过高,避免出现连接数超限错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 02:45:08