← 中文资源

简体中文版本

MySQL ERROR 1040 连接数过多 — 诊断与修复

对比 Threads_connected 与 max_connections,统计 processlist 中的 Sleep 会话,定位连接泄漏并用连接池、wait_timeout 与管理连接修复 MySQL 1040。

阅读英文原文

现象

应用报 ERROR 1040 (HY000): Too many connections,已有请求仍能继续,但新连接全部失败;Threads_connected 顶到 max_connections;information_schema.processlist 中大量应用账号的 Sleep 会话;高峰期或某个定时任务启动后集中出现。

诊断

先看连接上限与真实并发:

SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'wait_timeout';

Threads_connected 接近上限而 Threads_running 很低,说明连接大多空闲,问题在连接池或泄漏,而不是 CPU 压力。再按用户、来源和状态聚合:

SELECT user, host, db, command, COUNT(*) AS sessions, MAX(time) AS max_idle
FROM information_schema.processlist
GROUP BY user, host, db, command ORDER BY sessions DESC;

同一主机数百个 Sleep 会话通常意味着连接池没有上限,或框架每个请求新建连接;少量长时间 Query 则可能是报表或锁等待占着槽位。普通连接已满时,MySQL 8.0.14 起可用 mysql --admin -uroot -p 通过管理接口登录排查。

修复

为每个服务显式设置连接池上限,并乘以副本数,确保总和低于 max_connections;在 finally 中关闭连接,设置合理的 wait_timeout;客户端很多时引入 ProxySQL 或 MySQL Router 统一复用。只有在确认内存与线程开销后才提高 max_connections,每个会话都要占用缓冲区。

紧急恢复时优先 KILL 已知泄漏客户端的空闲会话,而不是重启 MySQL;KILL CONNECTION 会回滚该会话事务,操作前要确认没有批处理在跑。

验证

重新压测并按秒采样 Threads_connected,它应在各池上限之和以下形成平台;峰值期间从应用副本新建连接不再出现 1040。对比 SHOW GLOBAL STATUS LIKE 'Aborted_connects'; 的前后值,若持续增长说明仍有客户端撞到上限或认证失败。同时确认 Threads_running 远低于上限,避免只是把空闲连接换成了繁忙连接。