网站突然提示数据库连接失败,应用日志出现以下错误,通常意味着MySQL实例的可用连接已被占满:
ERROR 1040 (HY000): Too many connections
常见原因包括应用连接未释放、连接池设置过大、慢查询导致请求积压,以及实际并发超过当前连接上限。建议按照下面的步骤排查。
1. 确认错误并登录目标数据库
先查看网站或应用日志,确认具体错误是 Too many connections。
如果提示密码错误、连接超时、账号连接数超限,或者应用连接池获取连接超时,需要分别排查,不能直接认定为实例连接数不足。
使用有权限的管理账号登录数据库。例如,采用本机密码认证时:
mysql -u root -p
按提示输入密码。远程数据库、自定义端口或容器部署环境,应使用实际的连接方式。
登录后确认当前实例:
SELECT VERSION(), @@hostname, @@port;
后续SQL语句均在MySQL客户端中执行,不是在Linux命令行直接执行。
如果已有可用的管理会话,排查期间建议保留,避免退出后无法重新连接。
2. 查看连接上限和当前使用情况
查询实例允许的最大连接数:
SHOW GLOBAL VARIABLES LIKE 'max_connections';
再查询连接相关指标:
SHOW GLOBAL STATUS
WHERE Variable_name IN (
'Threads_connected',
'Threads_running',
'Max_used_connections',
'Connection_errors_max_connections'
);
重点关注以下内容:
| 指标 | 含义 | 排查重点 |
|---|---|---|
| max_connections | 实例允许的最大连接数 | 当前配置是否适合业务规模 |
| Threads_connected | 当前打开的连接数 | 是否持续接近连接上限 |
| Threads_running | 当前未休眠的线程数 | 是否伴随执行、锁等待等积压 |
| Max_used_connections | 历史同时连接数峰值 | 是否曾接近或达到上限 |
| Connection_errors_max_connections | 因达到连接上限而被拒绝的累计连接次数 | 故障期间是否继续增加 |
例如,连接上限为151,当前连接数为150,说明可用余量已经较小。但这只是一次采样,仍需结合报错时间和拒绝计数判断。
Max_used_connections 是历史峰值,连接释放后不会立即下降;拒绝连接计数也应比较前后增量,不能仅凭数值非零判断故障仍在持续。

3. 找出连接来自哪个应用
执行:
SHOW FULL PROCESSLIST;
重点查看以下字段:
| 字段 | 含义 |
|---|---|
| Id | 连接编号 |
| User | 数据库账号 |
| Host | 客户端来源地址及端口 |
| db | 当前使用的数据库 |
| Command | 当前命令类型,例如Query或Sleep |
| Time | 处于当前状态的时长,单位为秒 |
| State | 当前执行或等待状态 |
| Info | 当前执行的SQL内容 |
拥有 PROCESS 权限的账号可以查看其他用户的连接;权限不足时,通常只能看到自身账号的连接,不能据此判断整个实例的情况。
如果大量连接集中在同一个账号或来源地址,应优先检查对应的网站、后台任务或应用服务。
Sleep表示连接当前空闲,不等于连接异常。 连接池正常运行时也会保留空闲连接,而且空闲连接可能仍存在未结束的事务。
需要进一步核对InnoDB事务时,可由有相应权限的管理员执行:
SELECT
trx_mysql_thread_id,
trx_started,
trx_state
FROM information_schema.innodb_trx;
其中 trx_mysql_thread_id 可以与连接列表中的 Id 对照,帮助定位长时间未结束的事务。
不要仅凭Sleep状态或空闲时长批量结束连接,应先确认连接用途、事务状态和业务影响。

4. 检查连接池、连接释放和慢查询
定位到连接来源后,重点检查以下几项。
检查连接是否正确释放
应用完成数据库操作后,应按照框架要求关闭连接或归还连接池。异常、超时、提前返回等代码路径,也需要执行连接释放逻辑。
如果访问量已经下降,连接数仍持续增长,应重点检查连接泄漏和后台任务积压。
计算全部应用的连接池总量
连接池上限通常作用于单个连接池,需要汇总所有进程、容器和应用实例。
例如,4个应用实例各使用一个最大连接数为30的连接池,理论上可能占用120个数据库连接。还需要计算后台任务、监控工具和管理连接,并预留余量。
如果每个进程都有独立连接池,还应继续乘以实际进程数量。
检查慢查询与长事务
查询执行缓慢、锁等待或事务迟迟不提交,都可能让连接长期无法归还,引发后续请求排队。
此时应结合慢查询日志、执行计划和事务信息定位原因。单纯增加连接上限,可能让更多请求同时进入数据库,进一步增加负载。
控制异常请求和重试
确认某个任务或服务正在异常创建连接后,可先暂停该任务或降低并发,并设置合理的重试间隔,缓解持续连接压力。
5. 资源允许时调整连接上限
确认业务确实需要更多连接,并评估内存、CPU和查询负载后,再调整 max_connections。
修改前记录原值。下面的200仅用于演示,不是通用推荐值。
临时调整运行中的连接上限:
SET GLOBAL max_connections = 200;
查询确认:
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SET GLOBAL 只修改当前运行实例,数据库重启后会重新按照启动配置加载。
对于支持 SET PERSIST 的MySQL 8.0、8.4等版本,验证调整效果后,可以持久化配置:
SET PERSIST max_connections = 200;
该语句会设置运行值,并将配置写入数据目录中的 mysqld-auto.cnf,供后续启动加载。执行需要相应管理权限,不建议手工编辑这个文件。
对于不支持此语法的版本,应修改实际生效的MySQL配置文件,在 [mysqld] 段中设置,例如:
[mysqld]
max_connections=200
配置文件变更通常需要在维护窗口重启服务后生效。容器部署还应确认配置和数据目录具备持久化存储。
如果调整后负载明显升高,应根据记录恢复原运行值,并同步恢复对应的持久化配置。

6. 验证业务是否恢复
调整完成后,重新执行第2节中的查询,并在实际业务访问期间持续观察:
-
网站、接口和后台任务能正常连接数据库。
-
当前连接数保留合理余量,没有持续顶满。
-
因连接上限产生的拒绝次数不再增加。
-
CPU、内存和查询响应时间保持稳定。
如果连接数很快再次达到上限,应继续检查连接泄漏、连接池总量和慢查询,而不是反复提高参数。
后续数据库正常重启后,也应再次核对 max_connections,确认持久化配置按预期生效。
常见问题
为什么连接数很多,CPU却不高?
部分连接可能处于空闲或等待状态。它们仍占用连接名额,但不一定持续消耗大量CPU,需要结合连接状态和事务情况判断。
直接重启MySQL能解决吗?
重启会中断现有连接,可能暂时恢复访问。如果应用连接泄漏或连接池设置不合理,故障仍可能再次出现。应先定位连接来源并处理根因。
连接满了,管理员还能登录吗?
MySQL为具备相应管理权限的账号保留了额外连接,但能否使用取决于账号权限及保留连接的占用情况。优先使用已有管理会话;不要为普通业务账号授予高权限来绕过限制。
注意事项
修改前记录参数原值及配置来源,避免回退时只恢复运行值而遗漏持久化设置。结束连接可能影响正在执行的业务及未提交事务,应确认用途后再处理。
本文以MySQL为例,MariaDB及其他兼容数据库的语法、权限和参数行为应以对应版本文档为准。
使用莱卡云服务器时,如需协助排查,可向莱卡云技术支持提供报错时间、MySQL版本、连接指标及脱敏后的连接列表。提交前请隐藏密码、业务SQL中的敏感数据和其他凭据信息。