MySQL 连接数爆满的四类真实原因与排查顺序
生产环境里 MySQL 连接数爆掉往往不是「用户太多」,而是几个具体写法把连接池拖住了。这篇按排查顺序整理四类最常见原因。
一、先看连接到底被谁占着
SHOW STATUS LIKE 'Threads_connected';
SHOW PROCESSLIST;
SELECT user, host, db, command, time, state, LEFT(info, 80) FROM information_schema.processlist ORDER BY time DESC LIMIT 20;
time 很大且 command 是 Sleep 的连接最可疑——它们是连接池里的空闲连接,一旦数量超过上限就会把新请求挡在门外。
二、antd 连接池配置与 MySQL 上限对不上
SHOW VARIABLES LIKE 'max_connections';
应用侧 maximumPoolSize 乘以实例数量,必须明显小于 max_connections,否则滚动发布时新旧实例叠加会把额度吃穿。经验值是应用总连接数不超过 max_connections 的 70%。
三、事务里做了外部调用
这是最隐蔽的一类:事务开启后去调 HTTP 接口或发消息,外部一慢,连接就一直被占着不释放。看 processlist 里状态是 query end 或 Waiting for table metadata lock 的基本都是这种。
正确做法是把外部调用挪到事务外面,或者用 @Transactional(propagation = REQUIRES_NEW) 拆开。
四、连接泄露:拿了没还
手写 JDBC 时忘了 close(),或者用 DataSource.getConnection() 之后异常路径没走 finally。连接池会报 HikariPool-1 - Connection is not available, request timed out,但根因在业务代码。
排查技巧:开 leakDetectionThreshold(HikariCP 配 60000 即 60 秒),泄露的连接会在日志里打出获取时的堆栈。
五、几个立即可用的缓解手段
- 把
wait_timeout从默认 28800 秒调到 600 秒,让空闲连接尽快回收 - 应用侧设
maxLifetime小于 MySQL 的wait_timeout,避免用到被服务端已断开的连接 - 加连接池监控指标(活跃/空闲/等待数),比出事后再查便宜得多
连接数问题的本质几乎都是「连接被占着但没在干活」,按这个思路查比反复调大 max_connections 有效。
- 点赞
- 收藏
- 关注作者
评论(0)