欢迎光临
我们一直在努力

MySQL Too many connections 怎么办?连接数排查教程

1. Too many connections 是什么意思?

网站或应用连接 MySQL 时,有时会出现:

Too many connections

这表示 MySQL 当前可用的客户端连接已经被占满,新的普通连接暂时无法建立。

比较常见的表现包括:

  • 网站突然提示数据库连接失败
  • WordPress 显示“建立数据库连接时出错”
  • Java、PHP、Node.js 应用无法连接数据库
  • MySQL 客户端登录时提示连接数过多
  • Nginx 后端出现 502 或 500
  • Docker 应用不断重试数据库连接
  • 数据库恢复正常一段时间后再次出现问题

出现这个错误时,不建议只重启 MySQL。

重启虽然可以临时清空连接,但如果真正原因没有解决,连接数还会再次达到上限。

2. 先确认是不是连接数达到上限

MySQL查看max_connections和当前连接数

进入 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 查看连接

MySQL使用SHOW 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. 临时释放大量异常连接

如果已经确认某个应用产生大量异常空闲连接,可以先停止或限制对应应用,再处理数据库连接。

例如:

  1. 暂时停止异常应用。
  2. 使用 SHOW FULL PROCESSLIST 确认连接来源。
  3. 终止明确异常的连接。
  4. 检查连接池配置。
  5. 修复应用后再恢复服务。

如果只在数据库中杀连接,但异常应用仍然不断重连,连接数很快就会再次升高。

14. 临时提高 max_connections

MySQL调整max_connections和wait_timeout

如果业务正在中断,并且服务器仍有足够内存,可以临时提高连接上限。

例如:

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. 紧急恢复建议

如果业务已经中断,可以按照以下顺序处理:

  1. 使用管理员账户进入 MySQL。
  2. 查看 Threads_connected 和 max_connections。
  3. 执行 SHOW FULL PROCESSLIST。
  4. 找到异常连接来源。
  5. 暂停不断创建连接的应用。
  6. 终止明确异常的连接。
  7. 在内存允许的情况下适当临时提高连接上限。
  8. 修复应用连接池或慢查询。
  9. 持续监控连接数是否再次增长。

不要只执行第 7 步,而忽略连接为何堆积。

33. MySQL 连接数快速排查表

问题现象优先检查
出现 Too many connectionsmax_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;

缓解故障,但不建议无限提高连接数。

正确的处理方式应该是:

先找到连接堆积原因,再合理调整连接上限、连接池和超时配置。

赞(0)
未经允许不得转载:莱卡云 » MySQL Too many connections 怎么办?连接数排查教程