先确认是否真连满:用root登录后执行show variables like 'max_connections'; show status like 'threads_connected'; show status like 'max_used_connections';若threads_connected远低于max_connections,则问题在应用重试、连接池配置或健康检查,而非连接数不足。

怎么确认是不是真连满了
别信报错就去改配置。MySQL 允许 max_connections + 1 个连接,多出那 1 个是留给有 SUPER 权限的管理员的——所以你还能用 root 本地 socket 登进去,就是靠它。
登录后立刻执行这三句:
-
SHOW VARIABLES LIKE 'max_connections';—— 看上限(默认常是 151,云数据库可能设 1000+) -
SHOW STATUS LIKE 'Threads_connected';—— 看当前活连接数 -
SHOW STATUS LIKE 'Max_used_connections';—— 看历史峰值,比瞬时值更可靠
如果 Threads_connected 是 80 而 max_connections 是 151,那报错大概率不是连接不够,而是应用在疯狂重试、健康检查轮询建连,或连接池配置失当。
怎么揪出“占着茅坑不拉屎”的连接
SHOW PROCESSLIST; 是核心命令,但默认只显示当前用户权限下的连接;查全量需用 root 或具备 PROCESS 权限的账号,否则看不到其他应用的连接。
重点关注三类连接:
-
State = 'Sleep'且Time > 300:空闲超 5 分钟,基本是应用没关连接或连接池idleTimeout设得太长 -
State = 'Sending data'或'Locked'且Time持续增长:SQL 卡住了,可能是慢查询、锁等待或大事务 - 同一
User+Host出现几十个连接:大概率是某个应用实例泄漏,比如 PHP 脚本异常退出未归还连接
更稳妥的定位方式是按来源聚合:SELECT USER, HOST, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY USER, HOST ORDER BY COUNT(*) DESC;
为什么 SET GLOBAL max_connections 经常不生效
执行 SET GLOBAL max_connections = 500; 后发现值没变?常见卡点不在语法,而在三道硬限制:
- Linux 文件描述符限制太低:
ulimit -n返回 1024,而你想设 2000 → MySQL 启动时自动向下取整,日志里会有Could not increase number of max_open_files - 配置文件写错段落:
max_connections必须放在[mysqld]段下,写在[client]或全局位置无效 - MySQL 8.0.22+ 已用
SET PERSIST持久化过该参数 →my.cnf修改会被忽略,得查mysqld-auto.cnf
验证是否生效,别信配置文件,要查运行时值:SELECT @@global.max_connections;
连接池 idleTimeout 和 wait_timeout 必须匹配
90% 的真实原因是应用侧配置失当。比如 HikariCP 或 Druid 常见错配:
-
maximumPoolSize(HikariCP)或max-active(Druid)设得比max_connections还高,多个服务一起压就爆 -
wait_timeout设为 300 秒,但连接池的idleTimeout设成 600 秒,连接永远归还不回去 -
connection-timeout默认 30 秒,网络抖动易堆积;建议调到 10–15 秒,并开leak-detection-threshold
关键原则:idleTimeout 必须严格小于 wait_timeout,否则连接被 MySQL 断掉后,池子还当它活着,下次用就报错。
临时 kill Sleep 连接只是抢出几个名额,几小时后又满——因为泄漏还在继续。真正要盯的是 USER 和 HOST,不是数字本身。











