数据库连接池被占满,三分钟从监控定位到具体 SQL

举报
yd_286814013 发表于 2026/11/02 12:33:04 2026/11/02
【摘要】 线上突然大量报错,日志里清一色是获取连接超时。这时候先别急着重启,重启只是把所有等待中的请求一起掐掉,十分钟后大概率复发。按下面四步走,通常三分钟内能锁定是哪类 SQL 把池子耗干了。第一步,确认是「池子小」还是「有人不还」。看连接池监控的三个数:活跃连接数、空闲连接数、等待队列长度。活跃数长时间顶在 maxPoolSize 上、等待队列持续增长,说明池子被占满;如果活跃数不高但等待队列很长...

线上突然大量报错,日志里清一色是获取连接超时。这时候先别急着重启,重启只是把所有等待中的请求一起掐掉,十分钟后大概率复发。按下面四步走,通常三分钟内能锁定是哪类 SQL 把池子耗干了。

第一步,确认是「池子小」还是「有人不还」。

看连接池监控的三个数:活跃连接数、空闲连接数、等待队列长度。活跃数长时间顶在 maxPoolSize 上、等待队列持续增长,说明池子被占满;如果活跃数不高但等待队列很长,那是获取连接的路径本身被卡住,比如网络抖动或者数据库端连接建立慢,两者的处理方式完全不同。

第二步,按状态给连接分组。

在数据库侧查 information_schema.processlist 或者 pg_stat_activity,按 state 和执行时长排序。重点看两类:执行时间很长的(慢查询占着连接不放),以及 state 是 Sleep 但时间很长的(连接借出去没还,典型是应用侧忘了关闭或者事务没提交)。

第三步,把长事务和慢 SQL 拎出来。

MySQL 用 sys.innodb_trx 看事务持续时间和持有的锁,长事务不提交,它占的连接不会释放,后面的请求只能排队。慢 SQL 则直接看执行计划,常见的坑是索引失效后全表扫描,一条语句从毫秒级变成几十秒,几个并发就把池子占满。

第四步,看连接池配置有没有被误改。

有几种典型配置会放大问题:最小空闲连接设得太小,流量突增时要临时建连;连接最大存活时间比数据库侧 wait_timeout 还长,会拿到已经被服务端断掉的死连接;借出连接后没有设置获取超时,请求会无限期等待,把线程也一起拖死。

治标和治本要分开做。

治标是临时把池子调大、把慢 SQL 下掉或者在入口做限流,先把业务救回来。治本得落到三件事上:给所有慢 SQL 加监控和阈值告警;事务范围尽量收窄,别在事务里调用外部接口;连接池的获取超时和最大存活时间按数据库实际参数配,别用默认值。

最后提醒一句,连接池打满往往不是连接池的问题,是上游某个接口变慢导致的连锁反应。只盯着池子调参数,下次换个入口还会再来一次。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。