asyncpg连接PostgreSQL闲置后报connection is closed错误的原因及解决方法
问题归属判定
该connection is closed错误为服务端与客户端配置不匹配共同导致,核心触发逻辑如下:
- PostgreSQL服务端默认配置了闲置连接回收规则,会主动断开超过指定时长无交互的连接,且不会主动同步断开状态给客户端
- asyncpg客户端如果未配置连接有效性校验、保活探测逻辑,会持续持有已被服务端断开的无效连接,发起操作时就会抛出对应错误
解决方案
优先调整客户端配置,避免修改服务端全局配置影响其他业务:
1. asyncpg客户端配置
- 配置连接池闲置回收参数:创建连接池时设置
max_inactive_connection_lifetime参数,取值小于服务端闲置连接超时时间即可,asyncpg会自动销毁超过该时长的闲置连接
参考代码:import asyncpg pool = await asyncpg.create_pool( user="数据库用户名", password="数据库密码", database="数据库名", host="数据库地址", # 示例:服务端闲置超时为300秒时,设置为240秒提前回收 max_inactive_connection_lifetime=240 ) - 开启TCP保活探测:创建连接池时开启TCP层保活配置,操作系统会自动探测连接有效性
参考代码:pool = await asyncpg.create_pool( # 其余基础连接参数省略 tcp_keepalive=True, # 闲置60秒后开始发送保活探测包 tcp_keepalive_idle=60, # 探测包发送间隔10秒 tcp_keepalive_interval=10, # 连续3次探测无响应判定连接失效 tcp_keepalive_count=3 ) - 业务逻辑加校验:每次从连接池取出连接后,先执行
SELECT 1做有效性校验,捕获到连接关闭异常时自动销毁旧连接、申请新连接后再执行业务逻辑
2. PostgreSQL服务端可选调整
如果业务确实需要长时间保留闲置长连接,可以修改postgresql.conf的对应参数,延长闲置连接回收阈值:
- 调整
idle_in_transaction_session_timeout:修改处于事务中的闲置连接超时时间,按需调大即可 - 对齐TCP保活参数:调整
tcp_keepalives_idle、tcp_keepalives_interval、tcp_keepalives_count参数,和客户端保活配置保持一致 - 配置修改完成后执行
SELECT pg_reload_conf();即可重载配置生效,无需重启数据库
内容的提问来源于stack exchange,提问作者Mathis Kirchner
相关产品推荐
相关产品推荐

