SQLAlchemy触发Exception during reset类异常不影响功能 如何避免报错?
问题根因
这个报错是SQLAlchemy连接池在回收废弃连接时触发的,和你当前的正常业务操作无关,所以你会发现业务功能完全不受影响:
- 你开启的
pool_pre_ping只会在从连接池取出连接供业务使用前做存活检测,正常请求拿到的都是可用连接,所以读写操作都正常 - 报错发生在SQLAlchemy要清理长时间未使用的废弃连接时,尝试对连接做回滚重置操作,但此时该连接已经被PostgreSQL服务端主动断开(触发原因一般是空闲超时、防火墙规则掐断长连接等),就会抛出这个异常
- 你代码里的核心问题是创建的Session从未主动关闭,大量连接长期占用不还给连接池,空闲时间超过服务端阈值后就会被服务端强制断开,等到回收时就会触发报错。长期不修复会导致连接泄漏,最终耗尽数据库的可用连接数,业务完全无法访问数据库。
解决方案
1. 正确管理Session生命周期(必改,核心修复)
在Session使用完成后主动关闭,将连接还给连接池,避免连接长期空闲。修改你的查询函数如下,新增finally块保证不管业务正常执行还是抛出异常,内部创建的Session都会被关闭:
def get_user_name(username: str, s=None) -> str: local_session = s if s is not None else SessionLocal() try: user_obj = local_session.query(User).filter_by(username=username) if len(list(user_obj)) < 1: return username return user_obj.first().first_name except Exception as ex: local_session.rollback() logger.exception(f"Failed while Error : {ex}") return username finally: # 外部传入的Session由调用方管理生命周期,仅关闭内部自主创建的Session if s is None: local_session.close()
2. 调整连接池回收参数
在create_engine的参数中新增pool_recycle配置,设置连接在池中的最大存活时间,值要小于PostgreSQL服务端的idle_in_transaction_session_timeout、idle_session_timeout以及网络设备的长连接超时阈值,通常设置为1800秒(30分钟)即可:
engine = create_engine( settings.SQLALCHEMY_DATABASE_URI, pool_pre_ping=True, echo=False, connect_args={"connect_timeout": 30}, pool_size=20, max_overflow=100, pool_recycle=1800 # 新增配置,单位为秒 )
3. 可选:屏蔽对应日志(不推荐,仅临时应急用)
如果暂时无法修复代码,只想屏蔽错误输出,可以调整sqlalchemy连接池模块的日志级别,过滤警告类日志:
import logging logging.getLogger("sqlalchemy.pool").setLevel(logging.ERROR)
该方案仅隐藏日志输出,不会解决连接泄漏的根问题,仅建议作为临时处理手段。
内容的提问来源于stack exchange,提问作者Vlade
相关产品推荐
相关产品推荐

