90%的MySQL连接数耗尽源于PHP未释放连接或持久化失效,而非max_connections过小;应先用root本地执行三句命令确认是否真满,再同步修复PHP 8.4持久连接链路、对齐超时参数并绕过系统资源限制。

PHP 8.4 环境下 MySQL 连接数耗尽,不能只盯着 max_connections 硬扩——90% 的“爆满”其实是连接没释放、堆在 Sleep 状态占着坑。真正有效的扩容,是“应用层释放 + 数据库层兜底 + 连接复用加固”三步协同。
先确认是不是真连满了
哪怕网站全白屏、接口全报 ERROR 1040,MySQL 仍保留一个 SUPER 权限的紧急连接位(max_connections + 1),你还能用 socket 直连进去查真相:
-
看上限:
SHOW VARIABLES LIKE 'max_connections';(MySQL 5.7/8.0 默认仅 151) -
看实况:
SHOW STATUS LIKE 'Threads_connected';(当前已建连数) -
看干活的:
SHOW STATUS LIKE 'Threads_running';(正在执行 SQL 的线程数)
若 Threads_connected = 498 但 Threads_running = 2,说明近 500 个连接全卡在 Sleep,基本可断定是 PHP 侧未 close、连接池泄漏或持久化配置失效,不是数据库不够用。
PHP 8.4 必须修复的持久连接链路
PHP 8.4 默认禁用或弱化了持久连接机制,宝塔等面板环境尤其容易断链,导致每个请求都新建 TCP 连接,迅速堆满 MySQL。需五点同步生效:
立即学习“PHP免费学习笔记(深入)”;
- 确保启用
mysqlnd扩展,并在php.ini中设mysqli.allow_persistent = On - 代码中显式使用持久化:PDO 连接加
PDO::ATTR_PERSISTENT => true;mysqli 连接主机名前加p:(如"p:127.0.0.1") - Nginx 配置开启长连接:
fastcgi_keep_conn on; - PHP-FPM 改用 Unix socket 监听(如
listen = /tmp/php-fpm.sock),并调高pm.max_children与连接池匹配 - 验证是否复用成功:执行
SHOW PROCESSLIST;,同一 PHP-FPM worker 的连接应复用相同 ID,而非持续新增
临时扩容要绕过三道硬坎
执行 SET GLOBAL max_connections = 1000; 常失败,不是命令不对,而是被系统卡住:
-
文件描述符限制:Linux 默认
ulimit -n是 1024,设 1000 就可能溢出;Docker 容器必须加--ulimit nofile=65536:65536 - 内存扛不住:每个连接平均吃 512KB~2MB,2000 连接 ≈ 1~4GB 内存,易触发 OOM Kill
-
根本连不进:若已完全失连,该命令无法执行;此时需用
mysqladmin -u root -p shutdown或kill -TERM $(pgrep mysqld)安全重启
连接池与超时必须对齐
PHP 应用层的连接池(如 Laravel 的 PDO 配置、自研连接管理)和 MySQL 参数必须严格对齐,否则必然产生“假连接”:
- idleTimeout(PHP 池) ≤ wait_timeout(MySQL),建议统一设为 300 秒(5 分钟)起手
- 检查
wait_timeout和interactive_timeout当前值:SHOW VARIABLES LIKE '%timeout%'; - 临时调整(新连接生效):
SET GLOBAL wait_timeout = 300; SET GLOBAL interactive_timeout = 300; - 永久生效需写入
my.cnf的[mysqld]段并重启
不复杂但容易忽略



















