Heroku部署Python应用使用ClearDB出现Connection reset by peer错误如何解决
问题根因
ClearDB默认会自动断开闲置时长超过阈值(免费版通常为30~60秒)的连接,若使用单长连接、未做有效性校验,再次调用已被服务端回收的连接时就会抛出Connection reset by peer错误。
方案1:使用MySQL Connector/Python内置连接池(推荐)
该方案通过连接池自动管理连接生命周期,配合主动回收机制避免拿到失效连接。
- 先安装依赖:
pip install mysql-connector-python
- 连接池实现代码:
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
相关产品推荐
相关产品推荐

