root能登录而应用连不上,是因为mysql为connection_admin权限用户预留max_connections+1连接位,仅限本地socket(-s)访问;tcp连接(-h)仍占普通连接位。

能连上就别重启,先杀 Sleep 连接;连不上时 root 用 socket 登录仍有后门;临时调大 max_connections 只是止血,不是根治。
为什么 root 还能登录,而应用连不上?
MySQL 为有 CONNECTION_ADMIN 权限的用户(如 root)预留了第 max_connections + 1 个连接位。哪怕 Threads_connected 已等于 max_connections,root 仍可通过本地 socket(如 /var/lib/mysql/mysql.sock)强制登录。这是设计好的紧急通道,不是 bug。
- 必须用
-S指定 socket 路径,不能走 TCP(-h 127.0.0.1或-h localhost都会占用普通连接位) - 如果连 socket 也失败,说明系统级资源耗尽(如文件描述符满),需查
ulimit -n和dmesg - 不要依赖这个后门长期运行——它只用于诊断和应急,不是容灾方案
怎么快速确认是不是 Sleep 连接堆积?
执行 SHOW STATUS LIKE 'Threads_connected'; 和 SHOW STATUS LIKE 'Threads_running'; 对比两个值:
- 若
Threads_connected接近max_connections,但Threads_running很小(比如 Sleep 状态没释放 - 再跑
SHOW PROCESSLIST;,重点关注Command列为Sleep、Time值大于 300 的行 - 别直接
KILL所有 Sleep 连接——有些可能是健康长连接(如监控探针、心跳连接),先看User和Host判断来源
临时调大 max_connections 有哪些坑?
SET GLOBAL max_connections = 1000; 立即生效,但 MySQL 重启后失效。这操作看似简单,实际容易踩三个坑:
- 每个连接约消耗 256KB–2MB 内存,设成 2000 以上可能触发 OOM,尤其在 4GB 内存的机器上
- 不改
wait_timeout(默认 28800 秒),Sleep 连接仍会堆积,几天后照旧打满 - 应用层连接池(如 HikariCP 的
maximumPoolSize)若也设得过大,多个服务加起来可能远超数据库承载能力
真正要改的其实是这三个参数
永久解决不能只盯 max_connections,必须同步调整配套参数:
-
wait_timeout:非交互式连接空闲超时,建议从 28800 改为300(5 分钟)或600(10 分钟) -
interactive_timeout:交互式连接超时,通常与wait_timeout设为相同值 -
max_connections:根据服务器内存估算,例如 8GB 内存、每个连接按 512KB 算,上限不宜超过 16000,生产环境常见值是 500–2000
改完记得写进 my.cnf 的 [mysqld] 段,并重启 MySQL——否则配置不持久。最常被忽略的是:改了配置却不重启,或者重启后没验证是否生效(SHOW VARIABLES LIKE 'wait_timeout'; 必须查)。











