是连接数爆满:先查max_connections上限和Threads_connected当前值,若后者≥前者的90%且Max_used_connections近期猛涨,再结合SHOW PROCESSLIST中大量高Time的Sleep连接,即可确认;Sleep连接久不释放多因wait_timeout过长或连接池配置失配。

确认服务不可用是否真由连接数打满引起,而不是网络、权限或底层资源问题——先查 Threads_connected 是否逼近 max_connections,再看 SHOW PROCESSLIST 里有没有大量挂住的 Sleep 连接。
怎么快速判断是不是连接数真爆了
别一报错就改配置。先登录 MySQL 执行三句:
-
SHOW VARIABLES LIKE 'max_connections';—— 看上限是多少(默认常为 151) -
SHOW STATUS LIKE 'Threads_connected';—— 看当前连了多少,如果 ≥ 上限 90%,基本就是它 -
SHOW STATUS LIKE 'Max_used_connections';—— 如果这个值近期猛涨,说明不是瞬时毛刺,是持续堆积
注意:Threads_connected 包含所有已建立但未断开的连接,哪怕应用端已经 close(),只要 MySQL 还没回收(比如 wait_timeout 没到),就算在内。
为什么 Sleep 连接特别危险
大量 Sleep 状态且 Time 值很高(比如 > 300 秒)的连接,90% 是应用层没正确释放连接,或者连接池参数和 MySQL 超时设置不匹配。
-
wait_timeout和interactive_timeout默认常设为 28800(8 小时),太长;建议设为 300~600 秒 - HikariCP 的
idleTimeout必须 wait_timeout,否则空闲连接永远等不到 MySQL 主动断开 - Druid 的
removeAbandonedOnBorrow若关闭,泄漏连接不会被强制回收 - ORM 如 Django 默认用长连接,若没配
CONN_MAX_AGE=0或设太长,也会积累Sleep连接
临时救火但别依赖的手段
紧急恢复可用性可以做,但只是兜底,不能替代根因修复:
- 手动
KILL掉长时间Sleep的非关键连接(避开system user和复制线程) -
SET GLOBAL wait_timeout = 300;让空闲连接更快释放(需SUPER权限) -
SET GLOBAL max_connections = 500;仅限应急,重启失效,且每个连接吃内存(约 256KB~1MB),设太高可能触发 OOM
这些 SET GLOBAL 操作在 MySQL 8.0+ 需 SYSTEM_VARIABLES_ADMIN 权限,5.7 及更早版本必须有 SUPER。
真正要盯住的三个协同点
连接数反复爆满,问题一定出在「应用连接池」、「MySQL 超时参数」、「业务代码释放逻辑」三者的错位上:
- 连接池最大连接数(如 HikariCP 的
maximumPoolSize)× 应用实例数,不能超过max_connections的 70% -
wait_timeout必须比连接池的idleTimeout大,但差值不宜超过 60 秒,否则连接池以为连接还活,MySQL 却已悄悄断开,下次复用直接报错 - 任何带
try的数据库操作,finally块里必须显式close(),尤其嵌套事务、RPC 调用后,容易漏掉
最隐蔽的坑是:连接池健康检测(如 connection-test-query)本身会建连接,如果检测失败又没清理干净,会悄悄拖慢整个池子的回收节奏。


















