1. Too many connections 是什么意思?
网站或应用连接 MySQL 时,有时会出现:
Too many connections
这表示 MySQL 当前可用的客户端连接已经被占满,新的普通连接暂时无法建立。
比较常见的表现包括:
- 网站突然提示数据库连接失败
- WordPress 显示“建立数据库连接时出错”
- Java、PHP、Node.js 应用无法连接数据库
- MySQL 客户端登录时提示连接数过多
- Nginx 后端出现 502 或 500
- Docker 应用不断重试数据库连接
- 数据库恢复正常一段时间后再次出现问题
出现这个错误时,不建议只重启 MySQL。
重启虽然可以临时清空连接,但如果真正原因没有解决,连接数还会再次达到上限。
2. 先确认是不是连接数达到上限

进入 MySQL:
mysql -uroot -p
根据提示输入数据库管理员密码。
查看最大连接数:
SHOW VARIABLES LIKE 'max_connections';
可能看到:
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
这里的数值表示 MySQL 当前允许的普通并发连接上限。
不同版本和不同服务器配置可能不一样,应以实际查询结果为准。
3. 查看当前已经建立多少连接
执行:
SHOW GLOBAL STATUS LIKE 'Threads_connected';
例如:
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 146 |
+-------------------+-------+
如果:
Threads_connected
已经非常接近:
max_connections
说明当前连接数确实已经接近上限。
还可以查看当前正在执行工作的线程:
SHOW GLOBAL STATUS LIKE 'Threads_running';
Threads_connected 表示当前保持连接的会话数量。
Threads_running 更偏向当前正在执行任务的线程数量。
如果连接很多,但真正运行的线程很少,可能存在大量空闲连接。
4. 查看历史连接峰值
执行:
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
例如:
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 151 |
+----------------------+-------+
如果历史峰值已经达到当前 max_connections,说明服务器之前确实触碰过连接上限。
需要注意,Max_used_connections 是从 MySQL 本次启动后开始统计的。
MySQL 服务重启以后,该统计值会重新开始计算。
5. 查看因连接上限产生的错误次数
可以执行:
SHOW GLOBAL STATUS LIKE 'Connection_errors_max_connections';
如果该值持续增加,说明客户端连接确实因为达到最大连接数而被拒绝。
还可以查看服务器启动以来总共尝试建立的连接数量:
SHOW GLOBAL STATUS LIKE 'Connections';
这些数据可以辅助判断问题是偶发峰值,还是应用长期不断创建连接。
6. 使用 SHOW FULL PROCESSLIST 查看连接

执行:
SHOW FULL PROCESSLIST;
常见字段包括:
Id
连接 ID。
User
使用的 MySQL 账户。
Host
客户端来源地址和端口。
db
当前数据库。
Command
当前连接状态。
Time
当前状态持续的时间。
State
当前正在执行的阶段。
Info
正在执行的完整 SQL。
如果不加 FULL:
SHOW PROCESSLIST;
较长的 SQL 内容可能只显示一部分。
因此排查时更建议使用:
SHOW FULL PROCESSLIST;
7. Sleep 连接是什么意思?
在进程列表中,经常可以看到:
Command: Sleep
这表示客户端已经连接到 MySQL,但当前没有执行 SQL。
少量 Sleep 连接通常属于正常现象。
例如应用连接池会保留一部分空闲连接,以减少每次请求都重新连接数据库的开销。
需要重点关注的是:
- Sleep 连接数量特别多
- Sleep 时间特别长
- 连接数持续增长不下降
- 同一个应用主机建立了大量连接
- 应用请求量不高,但连接数接近上限
这种情况可能说明连接池配置过大,或者程序没有正确释放数据库连接。
8. 统计不同状态的连接数量
可以执行:
SELECT
COMMAND,
COUNT(*) AS connections
FROM information_schema.PROCESSLIST
GROUP BY COMMAND
ORDER BY connections DESC;
可能看到:
+---------+-------------+
| COMMAND | connections |
+---------+-------------+
| Sleep | 132 |
| Query | 11 |
| Connect | 3 |
+---------+-------------+
如果绝大多数都是 Sleep,应优先检查应用连接池和空闲连接超时。
如果大量连接都是 Query,则应该继续排查慢查询、锁等待和数据库性能。
9. 查看连接主要来自哪个用户和主机
可以执行:
SELECT
USER,
SUBSTRING_INDEX(HOST, ':', 1) AS client_host,
COMMAND,
COUNT(*) AS connections
FROM information_schema.PROCESSLIST
GROUP BY USER, client_host, COMMAND
ORDER BY connections DESC;
通过这个结果可以判断:
- 哪个 MySQL 用户连接最多
- 哪台应用服务器建立的连接最多
- 是网站、接口还是其他服务造成连接堆积
- 是否存在异常来源地址
如果大部分连接都来自同一个应用主机,就应该优先检查该应用的数据库连接池。
10. 查找长时间 Sleep 的连接
可以执行:
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE
FROM information_schema.PROCESSLIST
WHERE COMMAND = 'Sleep'
ORDER BY TIME DESC;
这里的 TIME 通常表示连接已经在当前 Sleep 状态保持了多少秒。
如果同一个应用用户存在大量持续几千秒的 Sleep 连接,就需要继续检查:
- 应用是否启用了持久连接
- 连接池最大值是否过大
- 连接归还是否正常
wait_timeout是否过长- 程序异常退出后是否留下连接
11. 查找运行时间较长的 SQL
执行:
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME,
STATE,
INFO
FROM information_schema.PROCESSLIST
WHERE COMMAND <> 'Sleep'
ORDER BY TIME DESC;
如果某些查询长时间停留在:
Sending data
Locked
Waiting for table metadata lock
或者其他等待状态,可能导致连接迟迟无法释放,后续请求不断堆积。
这时不应该只增加 max_connections。
还需要继续排查:
- 慢查询
- 表锁和行锁
- 缺少索引
- 大表扫描
- 数据库 I/O
- 长事务
- 应用重复执行 SQL
12. 可以直接 KILL 连接吗?
可以终止指定连接,但必须谨慎。
例如要终止连接 ID:
3842
可以执行:
KILL CONNECTION 3842;
也可以简写为:
KILL 3842;
执行前一定要确认该连接的:
- 用户
- 来源主机
- 当前 SQL
- 是否存在事务
- 是否正在执行备份或数据修改
不要批量终止不了解用途的连接。
误杀正在执行写入或事务的连接,可能导致业务失败或事务回滚。
13. 临时释放大量异常连接
如果已经确认某个应用产生大量异常空闲连接,可以先停止或限制对应应用,再处理数据库连接。
例如:
- 暂时停止异常应用。
- 使用
SHOW FULL PROCESSLIST确认连接来源。 - 终止明确异常的连接。
- 检查连接池配置。
- 修复应用后再恢复服务。
如果只在数据库中杀连接,但异常应用仍然不断重连,连接数很快就会再次升高。
14. 临时提高 max_connections

如果业务正在中断,并且服务器仍有足够内存,可以临时提高连接上限。
例如:
SET GLOBAL max_connections = 300;
再次检查:
SHOW VARIABLES LIKE 'max_connections';
需要注意:
这是运行时修改。
MySQL 服务重启以后,可能恢复成配置文件中的原值。
而且提高连接数只是临时缓解手段,不等于问题已经解决。
15. 不要把 max_connections 无限调大
每个 MySQL 连接都会消耗一定的服务器资源。
具体消耗取决于:
- 连接缓冲区
- 排序缓冲区
- Join Buffer
- 临时表
- 查询类型
- 线程栈
- 应用行为
如果把 max_connections 从几百直接提高到几千,但服务器内存没有同步增加,可能导致:
- MySQL 内存压力增加
- 系统开始大量使用 Swap
- 查询响应变慢
- MySQL 被 OOM Killer 终止
- 整台服务器失去响应
正确的思路应该是:
先找出连接为何堆积,再决定是否合理提高上限。
16. 永久修改 max_connections
不同系统的 MySQL 配置文件位置可能不同。
Debian、Ubuntu 常见位置:
/etc/mysql/mysql.conf.d/mysqld.cnf
部分系统可能使用:
/etc/my.cnf
或者:
/etc/mysql/my.cnf
在 [mysqld] 区块中加入:
[mysqld]
max_connections=300
保存以后,需要在合适的维护时间重启 MySQL。
Debian、Ubuntu 常见:
systemctl restart mysql
部分 MariaDB 环境可能使用:
systemctl restart mariadb
重启后再次检查:
SHOW VARIABLES LIKE 'max_connections';
修改配置前建议先备份原文件。
17. 检查 wait_timeout
执行:
SHOW VARIABLES LIKE 'wait_timeout';
wait_timeout 用于控制非交互连接空闲多长时间后被 MySQL 关闭。
如果值非常大,应用留下的空闲连接可能长期占用连接数。
可以临时调整:
SET GLOBAL wait_timeout = 300;
但需要注意:
全局值通常主要影响后续新建立的连接。
已经存在的连接可能仍然保留原来的会话值。
因此修改后不能只看现有连接是否立即消失。
18. 检查 interactive_timeout
执行:
SHOW VARIABLES LIKE 'interactive_timeout';
interactive_timeout 主要用于交互式客户端连接。
例如某些使用交互选项建立的 MySQL 客户端会话。
配置文件中可以根据实际情况加入:
[mysqld]
wait_timeout=300
interactive_timeout=300
不要机械地把超时时间设置得非常短。
如果时间过短,应用连接池中的连接可能被 MySQL 提前关闭,随后出现:
MySQL server has gone away
Lost connection to MySQL server
等问题。
19. Sleep 连接多就应该降低 wait_timeout 吗?
不一定。
如果应用使用连接池,保留一定数量的 Sleep 连接是正常的。
降低 wait_timeout 前,应该先检查:
- 连接池最小连接数
- 最大连接数
- 空闲连接回收时间
- 连接有效性检测
- 应用请求量
- MySQL 当前内存
如果连接池保留 100 个连接,而 wait_timeout 设置为 60 秒,MySQL 频繁关闭连接后,应用又不断重新建立连接,反而会增加连接创建开销。
所以超时时间应该和应用连接池策略配合设置。
20. PHP 网站为什么会占满连接?
PHP-FPM 通常会启动多个 Worker。
如果程序使用持久数据库连接,或者每个 Worker 都保留数据库连接,那么最大可能连接数会随着:
pm.max_children
增加。
例如:
多个网站;
多个 PHP-FPM Pool;
每个 Pool 大量 Worker;
再加上后台任务和 Cron;
就可能同时建立大量 MySQL 连接。
需要检查:
- PHP-FPM
pm.max_children - 是否使用持久连接
- 应用是否正确关闭连接
- WordPress 插件是否异常
- 是否有爬虫或高并发请求
- 慢查询是否造成请求堆积
不要只增加 MySQL 连接数,而完全忽略 PHP-FPM 并发。
21. Java 连接池怎么排查?
Java 应用通常使用数据库连接池,例如 HikariCP。
常见配置包括:
maximumPoolSize
minimumIdle
idleTimeout
maxLifetime
connectionTimeout
如果多个 Java 实例都配置:
maximumPoolSize=100
五个实例理论上可能建立数百个连接。
因此应该根据:
- 应用实例数量
- MySQL 最大连接数
- 正常并发量
- 查询执行时间
- 服务器资源
合理分配连接池。
不要给每个应用实例都设置一个很大的连接池。
22. Node.js 和其他应用也要检查连接池
Node.js、Python、Go 等应用也可能使用数据库连接池。
需要检查类似:
connectionLimit
pool_size
max_open_connections
等参数。
如果应用代码每次请求都创建新连接,却没有正常关闭,也会造成连接数持续上升。
排查时可以通过 MySQL 的:
HOST
和:
USER
确认连接来源,再回到对应应用检查连接池和代码。
23. 慢查询会导致连接数堆积吗?
会。
假设一个接口正常需要:
50ms
完成查询。
如果因为缺少索引,查询变成:
10 秒
那么同一时间会有更多请求连接停留在 MySQL 中。
随着新请求继续进入,连接数就会不断增加。
因此 Too many connections 有时只是表面现象,真正原因可能是:
- 慢查询
- 数据库锁
- 磁盘 I/O
- 大表扫描
- 应用突发流量
应该结合慢查询日志和 SHOW FULL PROCESSLIST 继续分析。
24. 查看 Threads_running
执行:
SHOW GLOBAL STATUS LIKE 'Threads_running';
如果:
Threads_connected 很高;
但 Threads_running 很低;
通常说明大量连接处于空闲或等待状态。
如果:
Threads_running 也长期很高;
则可能存在大量并发查询或数据库性能瓶颈。
需要进一步检查:
- 查询执行时间
- CPU
- 磁盘 I/O
- 锁等待
- InnoDB 状态
25. 检查 MySQL 内存和系统资源
查看服务器内存:
free -h
查看 MySQL 进程:
ps aux --sort=-%mem | head
查看 Swap:
swapon --show
如果 MySQL 已经占用大量内存,并且服务器正在频繁使用 Swap,不适合继续大幅提高连接数。
还可以检查 OOM:
dmesg -T | grep -Ei 'oom|out of memory|killed process'
如果 MySQL 曾被 OOM Killer 终止,应优先处理内存问题。
26. 查看 MySQL 错误日志
Debian、Ubuntu 可以查看:
journalctl -u mysql -n 100 --no-pager
MariaDB:
journalctl -u mariadb -n 100 --no-pager
常见错误日志位置还可能包括:
/var/log/mysql/error.log
如果数据库连接数达到上限、启动失败、内存不足或发生异常,日志通常会提供线索。
27. Docker 中的 MySQL 怎么排查?
首先查看容器:
docker ps -a
查看 MySQL 日志:
docker logs --tail 100 mysql
进入 MySQL:
docker exec -it mysql mysql -uroot -p
查看资源:
docker stats --no-stream mysql
如果 MySQL 容器存在内存限制,还需要检查:
docker inspect -f '{{.HostConfig.Memory}}' mysql
如果连接数调高,但 Docker 内存限制仍然很小,MySQL 可能因为内存不足变得更加不稳定。
28. Docker Compose 如何设置 max_connections?
可以通过 MySQL 启动参数设置。
例如:
services:
mysql:
image: mysql:8.4
restart: unless-stopped
command:
- --max-connections=300
- --wait-timeout=300
- --interactive-timeout=300
修改以后先检查:
docker compose config
然后重新创建:
docker compose up -d --force-recreate
最后进入数据库确认:
SHOW VARIABLES LIKE 'max_connections';
镜像版本和配置方式应根据实际项目调整。
29. 只有某个用户无法连接怎么办?
如果其他 MySQL 用户可以连接,但某个应用账户无法连接,还要检查用户级连接限制。
执行:
SHOW CREATE USER 'app'@'%';
查看输出中是否存在类似:
MAX_USER_CONNECTIONS
限制。
不同 Host 对应不同 MySQL 账户。
例如:
'app'@'localhost'
和:
'app'@'%'
属于不同账户。
所以应先确认应用实际使用的是哪一个账户。
30. 管理员还能连接说明什么?
MySQL 通常会保留一个额外的管理员连接,用于在普通连接已经达到上限时进行诊断。
但该连接需要使用具备相应管理权限的账户。
应用账户不应该拥有这种管理权限。
如果管理员仍能进入 MySQL,可以立即使用:
SHOW FULL PROCESSLIST;
查看连接来源,而不是先重启数据库。
31. 重启 MySQL 可以解决吗?
重启 MySQL 会断开所有现有连接,因此错误可能暂时消失。
但同时会中断:
- 网站
- 数据库事务
- API
- 后台任务
- 其他依赖数据库的服务
而且如果应用连接池或慢查询问题仍然存在,连接数还会再次升高。
因此正式服务器不应把:
systemctl restart mysql
作为第一步。
建议先收集进程列表、连接状态和日志,再决定是否安排维护重启。
32. 紧急恢复建议
如果业务已经中断,可以按照以下顺序处理:
- 使用管理员账户进入 MySQL。
- 查看
Threads_connected和max_connections。 - 执行
SHOW FULL PROCESSLIST。 - 找到异常连接来源。
- 暂停不断创建连接的应用。
- 终止明确异常的连接。
- 在内存允许的情况下适当临时提高连接上限。
- 修复应用连接池或慢查询。
- 持续监控连接数是否再次增长。
不要只执行第 7 步,而忽略连接为何堆积。
33. MySQL 连接数快速排查表
| 问题现象 | 优先检查 |
|---|---|
| 出现 Too many connections | max_connections、Threads_connected |
| 当前连接接近上限 | SHOW FULL PROCESSLIST |
| 大量 Sleep | 连接池、wait_timeout |
| 大量 Query | 慢查询、锁、数据库性能 |
| 连接都来自一个主机 | 对应应用连接池 |
| 连接数持续上涨 | 程序未释放连接 |
| 临时提高上限后恢复 | 仍需修复根本原因 |
| 调高后 MySQL 被杀 | 内存、OOM、容器限制 |
| 只有一个用户报错 | 用户级连接限制 |
| 重启后很快再次出现 | 应用或查询问题未解决 |
推荐按照:
连接上限 → 当前连接数 → 历史峰值 → 进程列表 → 连接来源 → 连接池 → 慢查询 → 内存
的顺序进行排查。
34. 如何长期监控连接数?
可以定期记录:
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Threads_running';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
如果已经部署 Beszel、Prometheus、Grafana 或其他监控系统,也可以增加 MySQL 连接数指标。
这样可以发现:
- 每天固定时间的连接峰值
- 发布新版本后连接数异常
- 某个接口造成连接暴增
- 连接池配置变更后的影响
不要等网站完全报错后才开始查看连接数。
35. 服务器配置建议
MySQL 连接数能够设置多大,和服务器资源密切相关。
需要综合考虑:
- CPU 核心
- 内存
- 磁盘 I/O
- 查询复杂度
- 数据库缓存
- 应用实例数量
- 连接池配置
如果需要部署 MySQL、WordPress、Docker 应用或其他数据库业务,可以根据实际访问量选择莱卡云 Linux 云服务器。
查看官网购买链接: https://www.lcayun.com
如果需要长期观察服务器和容器资源,可以参考:
相关阅读: 使用 Docker 搭建 Beszel 服务器监控面板
如果 MySQL 运行在 Docker Compose 中,也可以参考:
相关阅读: 使用 Docker 搭建 Dockge:可视化管理 Docker Compose 项目
36. 总结
MySQL 提示:
Too many connections
表示当前可用连接已经被占满。
首先检查:
SHOW VARIABLES LIKE 'max_connections';
然后查看:
SHOW GLOBAL STATUS LIKE 'Threads_connected';
以及:
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
再通过:
SHOW FULL PROCESSLIST;
确认连接主要来自哪个用户、主机和应用。
如果存在大量 Sleep 连接,应检查:
- 应用连接池
- 连接释放
wait_timeout- 实例数量
如果存在大量长时间 Query,应继续排查:
- 慢查询
- 数据库锁
- 磁盘 I/O
- 业务并发
可以临时使用:
SET GLOBAL max_connections = 300;
缓解故障,但不建议无限提高连接数。
正确的处理方式应该是:
先找到连接堆积原因,再合理调整连接上限、连接池和超时配置。








