直接改max_connections治标不治本,90%的“too many connections”源于连接未释放;应先用show variables和show status对比threads_connected与max_connections,再结合show processlist中大量超时sleep连接确认泄漏。

直接改 max_connections 能缓解,但大概率治标不治本——90% 的“Too many connections”不是连接数设太小,而是连接没关干净。
查清当前连接数和上限值
别急着调大,先确认是不是真到了瓶颈。用宝塔终端执行:
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections'; SHOW STATUS LIKE 'Threads_connected';"
返回类似 max_connections | 151 和 Threads_connected | 148 就说明快满了;如果 Threads_connected 长期稳定在 20–30,但报错仍频繁,基本可断定是连接泄漏。
-
Threads_connected是当前活跃连接数,不是历史峰值 - MySQL 给
root用户多留了 1 个“急救通道”,所以实际拒绝新连接的临界点是max_connections,不是max_connections + 1 - 若
Threads_connected接近上限,且SHOW PROCESSLIST里大量状态为Sleep、Time值超 300 秒,就是连接未释放的铁证
临时调高 max_connections(救火用)
只适合突发流量或验证是否配置瓶颈。进 MySQL 命令行后执行:
SET GLOBAL max_connections = 500;
立即生效,但服务器重启或 MySQL 服务重启后会还原。验证命令:
SHOW VARIABLES LIKE 'max_connections';
- 该操作不需要重启服务,适合快速验证:调高后错误消失 → 可能真是配置太低;调高后几小时又满 → 一定是代码或连接池没关连接
- 别设太高(比如 2000+),盲目拉高会挤占内存,尤其在低配机器上容易触发 OOM
- 宝塔面板里用 phpMyAdmin 执行这条语句也行,但注意 phpMyAdmin 自身也会占用 1–2 个连接
永久修改 max_connections(生产环境必须做)
进宝塔面板 → 数据库 → 配置修改,在 [mysqld] 区块下添加:
max_connections = 500 wait_timeout = 600 interactive_timeout = 600
保存后点击「重启 MySQL」。两个 timeout 参数关键:默认 28800 秒(8 小时),Sleep 连接挂太久,等于白占坑。
- 必须写在
[mysqld]段内,写到[client]或文件开头无效 - 路径优先级:宝塔配置修改页 >
/www/server/mysql/etc/my.cnf>/etc/my.cnf,改完记得重启 -
wait_timeout控制非交互式连接(如 PHP 脚本)空闲超时;interactive_timeout控制交互式连接(如终端登录)超时;两者建议设相同值
检查并修复应用层连接泄漏
这才是多数人忽略的核心环节。重点查以下位置:
- PHP 项目中所有
mysqli_connect()后是否配对mysqli_close($conn);PDO 实例是否显式置为null($pdo = null;),因为$pdo->close()不存在 - Laravel 的
DB::connection()->disconnect()、ThinkPHP 的Db::close()是否被遗漏,尤其在异常分支或定时任务中 - Python Flask/Django 中
connection.close()是否总被执行,有没有被try/except吞掉异常导致跳过 - 检查连接池配置(如 PDO 的
PDO::ATTR_PERSISTENT => false),误开持久连接会导致连接复用失效、长期滞留
最简单的验证方式:停掉所有业务流量,等 10 分钟,再看 SHOW PROCESSLIST 是否还有大量 Sleep 连接 —— 如果还有,就是代码没关。











