首要动作是执行SHOW PROCESSLIST或查询information_schema.PROCESSLIST过滤非Sleep且Time>300的会话,通过Host列定位客户端IP和端口,结合Command、State、Time判断连接异常类型,并配合应用侧连接池监控与日志分析根因。

查当前活跃连接和来源 IP
MySQL 报 Too many connections 时,首要动作不是重启,而是快速定位谁在占着连接不放。执行:
SHOW PROCESSLIST;
重点看 Host 列(格式通常是 xxx.xxx.xxx.xxx:port),能直接暴露客户端 IP 和端口;Command 列为 Sleep 且 Time 值很大(比如 > 300 秒)的,大概率是应用没正确关闭连接;State 是 Sending data 或 Locked 的,则可能卡在慢查询或锁等待上。
如果权限足够,更推荐用:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE COMMAND != 'Sleep' OR TIME > 300;
这样过滤掉大量无意义的空闲连接,聚焦可疑会话。
区分应用连接池与真实客户端
看到 HOST 是 127.0.0.1:xxxxx 或 localhost,别急着认为是本地脚本——它更可能是中间件(如 Nginx + PHP-FPM、Tomcat、Node.js 进程)发起的连接。真实来源需结合应用日志或部署结构判断:
- Java 应用常用 HikariCP/Druid,检查
spring.datasource.hikari.maximum-pool-size是否设得过大(如 100+),且未配置connection-timeout或idle-timeout - PHP 的
mysqlnd默认不复用连接,mysqli每次 new 一个实例就新建连接,容易在循环里失控 - Python 的
pymysql或mysql-connector-python若没用with或显式close(),连接会在 GC 前一直挂着
单纯靠 MySQL 端无法区分“同一个 IP 下的多个进程”,必须配合应用侧连接池监控(如 HikariCP 的 /actuator/metrics/hikaricp.connections.active)。
临时释放连接 + 防止雪崩
确认某类连接异常后,可手动 kill:
KILL 12345;
但注意:KILL 对 Sleep 状态有效,对正在执行的事务可能只中断客户端,服务端仍需完成回滚;批量杀连接慎用,避免误杀核心业务会话。
更稳妥的做法是临时调高上限,争取排查时间:
SET GLOBAL max_connections = 500;
但这只是掩耳盗铃——真正要改的是应用行为。常见错误配置包括:
-
wait_timeout和interactive_timeout设为 0(永不过期),导致空闲连接永远不释放 - 应用代码中
try里开连接、finally忘了close(),尤其在异常分支下 - 使用连接池却把
min-idle设太高(如 50),冷启动时直接占满一半连接数
长期监控该盯哪些指标
靠人工 SHOW PROCESSLIST 只能救火,不能根治。上线后必须盯住:
- MySQL 的
Threads_connected(当前总连接数) vsmax_connections,持续 > 80% 就该预警 - 应用侧的连接池
active/idle/pending数,比数据库端更早暴露泄漏苗头 - 慢查询日志中
Rows_examined极高但返回行数极少的语句——这类查询会长时间占用连接,拖垮整个池
很多团队卡在“知道连接多”,但没打通“应用连接池 → 数据库连接 → 网络链路”的全链路追踪,结果每次都是 kill 完事,过两天又爆。真正的瓶颈往往不在 MySQL 配置,而在某段没加超时的 JDBC URL 或某个忘记 close 的 ResultSet。










