MySQL报“Too many connections”错误,表明当前连接数已达max_connections上限;应立即查Threads_connected与max_connections值,禁用持久连接,显式释放资源,并调小wait_timeout与配置PHP-FPM重启策略。

“Too many connections” 不是 PHP 报的错,是 MySQL 拒绝新连接的明确信号——说明当前活跃连接数已触达 max_connections 上限,必须立刻查源头、控增长、清滞留。
查当前连接数和上限值
登录 MySQL 后执行这两条命令,5 秒内就能确认是否真卡在连接数上:
-
SHOW VARIABLES LIKE 'max_connections';—— 看数据库允许的最大并发连接数(默认通常 151 或 200) -
SHOW STATUS LIKE 'Threads_connected';—— 看此刻真实连着的连接数;若接近或等于max_connections,就是它了
注意:Threads_connected 不包含已断开但未回收的连接(比如脚本异常退出没走 $pdo = null),压测时实际堆积可能更高。
禁用 PDO 或 MySQLi 的持久连接
PHP-FPM 环境下,PDO::ATTR_PERSISTENT => true 或 mysqli_pconnect() 是连接数暴涨的头号推手:子进程退出时不真正关闭连接,而是“假装还活着”扔进池里,MySQL 以为还在用,就一直占着名额。
立即学习“PHP免费学习笔记(深入)”;
- PDO 实例化时务必显式关掉持久化:
new PDO($dsn, $user, $pass, [PDO::ATTR_PERSISTENT => false]); - MySQLi 避免用
mysqli_pconnect(),改用new mysqli()+ 显式$mysqli->close() - CLI 脚本(如定时任务)尤其危险——一个没关的持久连接会挂好几分钟甚至更久
显式释放连接对象,别等脚本自动收尾
PHP 脚本结束时,短连接一般会自动释放,但以下情况会让连接滞留:
- 循环中反复
new PDO()却没复用,每次创建都多占一个名额 - 异常抛出后跳过
mysqli_close()或$pdo = null,资源没清理 - 用了
try-finally却把$pdo = null写在finally外面
稳妥做法:在逻辑末尾或 finally 块中写 $pdo = null; 或 $mysqli->close();,不依赖自动回收。
调小 MySQL 的 wait_timeout 并配合 PHP-FPM 重启策略
空闲连接不主动断,就会越积越多。MySQL 默认 wait_timeout = 28800(8 小时),对 Web 场景太长。
- 在
my.cnf的[mysqld]段加:wait_timeout = 60和interactive_timeout = 60 - 重启 MySQL 生效
- 同时在 PHP-FPM 配置中设
pm.max_requests = 500,让每个 worker 处理一定请求数后强制重启,清掉可能残留的连接状态
这个组合拳比单纯调大 max_connections 更治本——后者只是把爆掉的时间点往后推,而前者让无效连接快速退场。



















