error 1040 表示 threads_connected ≥ max_connections,确已打满;应优先用 socket 直连查 threads_connected 与 threads_running,清理 sleep 连接、缩短 wait_timeout,并校准连接池配置,而非盲目调大 max_connections。

max_connections 被真正打满了
报 ERROR 1040 (HY000): Too many connections,不是“快满了”,而是当前连接数(Threads_connected)已经 ≥ max_connections。MySQL 拒绝新连接的那一刻,就是阈值被踩中的瞬间。
关键要看两个值:
-
show variables like 'max_connections';—— 服务器允许的最大并发连接数(MySQL 5.7/8.0 默认是151) -
show status like 'Threads_connected';—— 当前已建立的连接总数(含大量Sleep状态)
如果后者接近或等于前者,就是真打满了。注意:root 用户通过本地 socket(如 /var/lib/mysql/mysql.sock)登录时,MySQL 会预留一个额外连接位,所以你还能进——这不是数据库没满,只是给你留了后门。
大量 Sleep 连接不释放是主因
绝大多数线上故障里,Threads_connected 高但 Threads_running 很低,说明连接没在干活,只是挂着不动。这些 Sleep 连接往往来自:
- 应用代码里
connection.close()被漏掉,尤其在try/catch异常分支里没兜底 - 连接池配置不合理:比如
max-idle过大、min-idle过高,或idle-timeout设成几小时 - ORM 框架事务嵌套没解耦,或手动开启事务后忘记
commit/rollback - 脚本类任务(Python/PHP)每次请求都新建连接,用完不关
这些连接不会自动消失,只会等 wait_timeout(默认 28800 秒 = 8 小时)超时才断开——等不及就爆了。
临时调大 max_connections 是饮鸩止渴
执行 set global max_connections = 1000; 确实能立刻缓解,但它掩盖了真实问题:
- 每个连接平均消耗 512KB~2MB 内存,盲目调大会导致 MySQL OOM
- 系统级文件描述符(
ulimit -n)可能跟不上,新连接仍建不起来 - 根本没解决连接泄漏,过几小时又回到原点
- 多个微服务共用同一 MySQL 实例时,各自调大反而加速打满
真正该优先调的是 wait_timeout 和 interactive_timeout,建议设为 300(5 分钟)——让空闲连接快速释放,比硬堆连接数更安全有效。
连接池和应用层才是根治入口
DBA 调参只能应急,根治必须从应用代码和中间件入手:
- 确认所有数据库操作都在
try-with-resources(Java)或with connection:(Python)里执行 - 检查连接池实际生效参数:比如 HikariCP 的
maximumPoolSize是否远超业务需要;Druid 的maxActive是否设得过大 - 避免在事务里调外部 HTTP/RPC 接口——事务一卡住,连接就锁死
- 对报表类长耗时查询,改用异步队列 + 临时表,别占着连接不放
最隐蔽的坑是:你以为用了连接池,其实配置项名写错(比如 maxPoolSize 写成 max-pool-size),导致实际没生效——务必查日志确认连接池启动时加载的参数值。











