数据库 / MySQL更新于 约 4 分钟阅读 · 执行耗时因环境而异
MySQL 连接池耗尽:如何找出连接泄漏与慢查询
“Too many connections” 是容量、泄漏或慢事务的结果。先确定连接被谁占住,再决定限流、扩容或修复代码。
维护者 Kevin · Ovalk
适用范围与前提
适用于 MySQL 8.x;托管数据库可能限制管理命令,并通过控制台提供指标。
使用获准的数据库连接,不把密码写进命令历史。查看其他用户会话需要相应权限,并记录应用副本数与连接池上限。
示例不是可以直接粘贴的指令。请替换示例域名、路径、服务名和大写占位符。先收集证据;重载、回滚、清理及执行任务会改变系统状态,需批准影响范围与恢复计划。不要分享凭据或未脱敏日志。
常见症状
- 应用报 Too many connections
- 数据库 CPU 不高但新请求无法建立连接
- Sleep 连接数量持续增长或长时间不回落
1. 确认连接是短时峰值还是持续泄漏
同时查看当前连接数、最大连接数和按用户/主机分组的连接。如果连接数在流量下降后仍不回落,优先怀疑连接释放、事务收尾或连接池回收策略。
mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';"
mysql -e "SELECT USER,HOST,COMMAND,COUNT(*) c FROM performance_schema.processlist GROUP BY 1,2,3 ORDER BY c DESC;"2. 查看长连接和正在执行的 SQL
PROCESSLIST 只能提供快照;结合 slow query log、应用追踪和连接池指标判断是慢查询拖住连接,还是请求未归还连接。不要在未确认来源前批量 KILL 连接,避免中断写事务。
mysql -e "SELECT ID,USER,HOST,DB,COMMAND,TIME,STATE,LEFT(INFO,160) FROM performance_schema.processlist WHERE COMMAND <> 'Sleep' ORDER BY TIME DESC;"3. 有序恢复服务
临时将非关键流量限流或摘流,降低新建连接竞争;再对明确的异常客户端滚动重启。只有在内存余量和每连接开销已评估时才调高 max_connections。
mysql -e "SHOW ENGINE INNODB STATUS\G"解读证据
| 观察结果 | 下一步检查 |
|---|---|
| 大量 Sleep 会话 | 连接池空闲连接可能正常。先对照池大小与未结束事务,不能直接认定泄漏。 |
| 池等待增加且连接接近上限 | 降低请求压力并定位占用连接的任务,增加连接可能加剧竞争。 |
| 仅某个用户的连接增长 | 追踪该用户对应的实例与发布,通过多次快照区分持续增长和稳定连接池。 |
说明性诊断案例
以下假设案例用于解释推理,并非客户真实事故,也不代表已在你的技术环境中测试。
假设应用连接预算为 180,六个副本各设 30 个连接已用满预算;滚动发布临时增加两个副本后可达 240。即使没有泄漏也会耗尽容量。连接池规划应包含发布临时副本、后台任务和管理保留量。
验证恢复
- 在正常流量下确认新连接成功且连接池等待下降,不能只看重启后的短暂恢复。
- 恢复流量时检查事务延迟与数据库内存,并重新汇总各副本连接池预算。
回滚与停止条件
记录原连接池设置并逐步调整。若竞争加剧,恢复上一次可承受的配置并保留限流;撤销配置无法恢复被终止的事务。
预防与长期修复
- 连接池上限应小于数据库可用连接预算,并按实例数汇总计算。
- 设置连接获取超时、最大生命周期与空闲回收,并记录 pool wait time。
- 为慢查询建立告警,避免把连接池当作排队系统。
参考资料与纠错
请使用与你安装版本匹配的文档。以下资料解释基础行为,命令仍需结合实际环境验证。
向 Kevin 提交更正,请附页面地址、版本与脱敏复现步骤。请查看编辑原则(英文)。