mysql报错“too many connections”本质是当前活跃连接总数超过max_connections上限,而非用户数超限;需用root执行show variables like 'max_connections'、show status like 'threads_connected'和show status like 'max_used_connections'确认水位,threads_connected≥max_connections−1即告警,多出的1个连接专供super用户应急登录。

MySQL 报错 Too many connections 不是“用户超限”,而是当前活跃连接总数超过了 max_connections 上限——哪怕全是同一个用户建的连接,只要总数满了,新连接照样被拒。
怎么确认是不是真连满了
必须用管理员账号(如 root)登录后立刻执行三句:
-
SHOW VARIABLES LIKE 'max_connections';—— 看上限(默认常是 151) -
SHOW STATUS LIKE 'Threads_connected';—— 看当前已连多少个 -
SHOW STATUS LIKE 'Max_used_connections';—— 看历史峰值;若长期接近上限,说明不是瞬时高峰,而是泄漏或配置不合理
注意:Threads_connected ≥ max_connections − 1 就可能触发拒绝;MySQL 允许 max_connections + 1 个连接,多出那 1 个是留给有 SUPER 权限用户的“救命通道”——你还能登进去,靠的就是它。
为什么 SET GLOBAL max_connections 有时不生效
常见假象:命令返回成功,但查 SHOW VARIABLES LIKE 'max_connections' 还是旧值。根本原因通常是:
- 操作系统级文件描述符限制太低:
ulimit -n返回值(比如 1024)小于你想设的max_connections(比如 2000),MySQL 启动时会自动向下取整 - 配置写错了段落:必须在
[mysqld]段里写max_connections = 500,写在[client]或全局位置无效 - 多个配置文件冲突:MySQL 只加载一个主配置文件(可用
mysqld --help --verbose | grep "Default options"确认路径),后加载的覆盖前一个 - MySQL 8.0.22+ 用了
SET PERSIST:它会把值写进mysqld-auto.cnf,优先级高于my.cnf,改my.cnf不起作用
怎么安全清理僵死连接而不是硬 kill
别一上来就 KILL 所有 Sleep 连接——有些是正常长连接(比如监控、ETL 工具)。重点盯这些:
- 查出空闲太久的连接:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 300;(>5 分钟的才考虑) - 按用户/IP 归类看异常来源:
SELECT USER, HOST, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY USER, HOST ORDER BY COUNT(*) DESC; - 对确认无用的连接,用
KILL <code>ID;逐个终
应用层连接池配置不当才是高频根因
90% 的连接数爆满不是数据库配小了,而是应用端没管好连接生命周期。典型表现是 Threads_connected 高、Threads_running 低,大量连接卡在 Sleep 状态。
- HikariCP 建议设
maximumPoolSize≤ 20,避免单服务打爆 DB;idleTimeout设为 30000(5 分钟),maxLifetime设为 1800000(30 分钟) - Druid 要开
removeAbandonedOnBorrow和minEvictableIdleTimeMillis,防止泄漏连接长期滞留 - Spring Boot 应用务必检查是否误配了
spring.datasource.hikari.maximum-pool-size=100—— 多个实例叠加就是几百连接 - 脚本类任务(Python/PHP)没用连接池?那就必须显式
close(),且加finally保障释放
最易被忽略的是:连接池的 validationQuery 或 connection-test-query 配置错误,导致连接看似健康实则已断,不断新建却从不复用。











