← 中文资源

简体中文版本

诊断 PgBouncer 连接池耗尽

区分连接池耗尽与数据库过载,读取 PgBouncer 统计找出占用大户,并按数据库容量而非恐慌来定池大小。

阅读英文原文

目标

当所有请求都在获取连接上超时、而数据库 CPU 只有 8% 时,问题出在客户端与服务器之间的连接池。PgBouncer 的管理命令用一条查询让看不见的队列现形:cl_waiting 是愤怒客户端数,sv_active 是真正忙碌的服务端连接数,两者的差距就是故事本身——池过小、客户端囤积或连接泄漏。

步骤要点

  1. 执行 SHOW POOLS,观察 cl_waiting 高企而 sv_active 未饱和,即可断定池耗尽而非数据库过载。
  2. 用 SHOW CLIENTS 按用户统计连接归属,找出独占池的那个部署。
  3. 统计 idle 状态客户端:大量 idle 无等待是客户端囤着不还;大量等待而 sv_idle 为 0 才是池真不够。
  4. 客户端侧给连接池设 max=10、idleTimeout=30s、connectionTimeout=5s,让占用可预测、获取有期限。
  5. 调整服务端池上限后 RELOAD 并复跑 SHOW POOLS:同负载下 cl_waiting 归零、sv_active 稳定在数据库真实可服务范围内。

排错提示

经 PgBouncer 事务模式下命名预处理语句会失效,要么走二进制协议要么把该库切成 session 模式;池调大后数据库反而饱和,说明池此前掩盖了数据库扛不住的并发,应回调池并修掉让客户端长时间持连接的慢查询;某个微服务总在囤连接就给它独立 pgbouncer 条目与独立上限,让坏客户端只饿自己。

适用边界

SHOW 统计需要配置 stats 用户并定期重置才好读;事务池化改变会话语义,依赖会话状态的特性需要 session 模式或重新设计。

代码示例

psql -p 6432 pgbouncer -c "SHOW POOLS;"

# Key columns:
#   cl_active  cl_waiting  sv_active  sv_idle  maxused
#       3          214          20         0        20
#  -> pool exhausted while servers are the real limit