应用突然报 too many connections,最直接的处理是调高 max_connections。这个动作有时能暂时恢复新连接,却也可能让更多会话继续占用内存,把连接泄漏从数据库拒绝变成整机内存压力。
排查连接数耗尽时,先查清上限、来源、会话状态和增长原因。 证据确认后再做最小改动,能避免盲目调大参数把问题暂时藏起来。

先保留一个可用于诊断的连接入口
PostgreSQL会为超级用户保留少量连接槽位,普通业务账号达到上限后,管理员仍可能从本机进入。不要让监控脚本和反复重试继续消耗剩余入口。
能够登录时先查询当前设置:
SHOW max_connections;
SHOW superuser_reserved_connections;
SELECT count(*) AS total_connections FROM pg_stat_activity;
max_connections 是并发连接上限,增加它会让PostgreSQL按更高连接数分配相关资源,而且该参数需要重启才能生效。调高上限属于容量变更,不是连接泄漏的证据。
完全无法登录时,可先限制应用重试或暂停非关键实例,再使用本机管理员入口。不要为了释放槽位直接重启数据库,重启会清空会话,同时让最有价值的现场消失。
用pg_stat_activity统计连接来源
先按数据库、用户、应用名、客户端地址和状态聚合:
SELECT datname, usename, application_name, client_addr, state,
count(*) AS connections
FROM pg_stat_activity
GROUP BY datname, usename, application_name, client_addr, state
ORDER BY connections DESC;
某个应用实例占用数量明显高于其他实例,通常应回到该应用的连接池配置。多个客户端同步增加,可能是统一发布后连接池大小变化,也可能是数据库变慢导致连接归还速度下降。
application_name 为空会降低判断效率,可以在连接字符串中为不同服务设置明确名称。客户端地址是代理或连接池地址时,还要继续查看代理侧指标,不能把所有连接都算到一个真实业务进程上。
区分active、idle和idle in transaction
active 表示会话正在执行查询,idle 表示等待客户端发送下一条命令。连接池保留一定数量的idle连接很正常,关键是数量是否符合池大小,并且能被复用。
idle in transaction 更值得警惕,它表示事务已经开始但客户端没有继续执行或提交。可以按持续时间查看会话:
SELECT pid, usename, application_name, client_addr, state,
now() - xact_start AS transaction_age,
now() - state_change AS state_age,
wait_event_type, wait_event
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
ORDER BY state_change;
长时间空闲事务不仅占连接,还可能阻止垃圾回收、扩大表膨胀。查询结果涉及业务SQL时应注意脱敏,工单中不要公开参数值和用户数据。
先排除数据库变慢造成的连接堆积
连接数量上涨不一定是应用忘记关闭连接。 慢查询、锁等待、磁盘延迟和下游服务卡住,都可能让请求迟迟不能结束,连接池只好不断等待或新建连接。
结合 wait_event_type、慢查询记录和锁信息检查相同时间段。大量active会话等待同一锁,应先处理阻塞链;大量新连接集中在短时间建立,则要检查应用重试、健康检查和连接池生命周期。
只看连接总数而不看状态,会把性能问题误判成简单容量不足。反过来,数据库性能正常但某个应用的idle连接持续超过连接池上限,则更接近多实例配置叠加或池没有正确关闭。
不要批量终止所有会话
pg_terminate_backend 可以终止指定后端,但正在执行事务的连接被终止后会回滚。批量清理全部会话可能扩大业务中断,还会让应用立即重新连接,几秒后再次占满。
先按应用名、客户端地址、状态和持续时间确认目标,再暂停造成增长的入口。需要释放连接时,从最明确的异常会话开始,并观察新连接是否再次出现。超级用户、复制连接和维护任务不能按普通业务会话一并处理。
最小改动的优先顺序是修正连接关闭逻辑、限制连接池、处理慢查询或锁,最后才评估提高上限。
什么时候需要连接池或提高上限
业务有大量短连接时,PgBouncer等连接池可以减少数据库后端数量,但池本身也需要按事务模式、会话需求和应用兼容性配置。引入连接池前应先统计峰值并发与实际活跃查询,而不是把客户端连接数原样映射成数据库连接数。
确实需要提高 max_connections 时,要评估每个后端的内存开销、工作内存配置和系统可用内存。准备新环境进行容量验证,可以在 萤光云 上复现数据库规格,也可以用按小时计费的 LightNode 做一轮峰值连接对照。测试必须使用相同连接池参数、查询类型和数据规模,否则更高上限没有可比性。
用重复峰值验证修复结果
修复后再次按应用名、客户端地址和状态统计连接,覆盖一次原本容易报错的流量峰值。连接数应在可解释范围内增长并能回落,idle in transaction不应持续积累。
同时观察数据库内存、查询延迟、错误日志和应用连接池等待时间。验收通过应满足不再出现连接槽位耗尽、异常来源连接数受控、事务能够结束、管理员保留入口仍可用。 只把报错推迟几分钟,不算根因关闭。
常见问题
把 max_connections 调得越大越好吗?
不是。连接上限越高,潜在后端进程和相关内存开销也越大。应先确认峰值活跃查询、连接池规模和服务器资源,再决定是否调整。
大量 idle 连接一定是连接泄漏吗?
不一定。连接池会保留一部分 idle 会话供复用,关键是数量是否符合实例数乘以池大小,并且能在低峰期回落。
可以直接终止 idle in transaction 会话吗?
先确认来源、事务持续时间和业务影响。终止后事务会回滚,应用也可能马上重连,因此要同时处理造成长事务的代码或超时设置。
温馨提示
生产环境执行终止会话、修改连接上限或重启数据库前,应先保留 pg_stat_activity 聚合结果和应用连接池指标。恢复新连接不等于根因已经消失,必须覆盖一次真实流量峰值再验收。


