“too many connections”是mysql明确拒绝新连接的信号,源于应用层连接泄漏或误配,需先查threads_connected与max_connections差值判断真耗尽或假性卡死,再通过kill空闲连接、临时扩容、启用deploy=1、配全pdo::attr_timeout和init_command、统一连接工厂、合并in查询、cli/swoole手动close等措施止血并根治。

ThinkPHP 5.1 应用突然报错“SQLSTATE[HY000] [1040] Too many connections”,页面白屏、接口超时,日志里反复出现 MySQL 连接拒绝,这不是数据库扛不住,而是连接池被无效占满后新请求彻底拿不到连接——必须立刻切断泄漏源头、释放闲置连接、压住 SQL 负载。
确认是否真耗尽,还是假性卡死
进服务器执行:mysql -h 127.0.0.1 -u root -p -e "SHOW STATUS LIKE 'Threads_connected';",对比输出值与 max_connections(查 SHOW VARIABLES LIKE 'max_connections';)。
若 Threads_connected 接近上限(比如 148/150),是真耗尽;若只有 30 却持续报错,大概率是 PDO 连不上,不是池子满了。
再看 runtime/log 下最近 20 行日志:tail -n 20 runtime/log/*.log | grep -i "gone\|1040\|refused"。高频出现 【MySQL server has gone away】,说明是 wait_timeout 导致的假性耗尽,连接空闲太久被 MySQL 主动断开,TP 却没感知,下次调用还试图复用已失效句柄。
立刻止血:杀掉空闲连接并临时扩容
登录 MySQL 执行:SELECT id, user, host, db, time FROM information_schema.processlist WHERE command = 'Sleep' AND time > 60;
把返回的 ID 拼成 KILL 语句,例如 KILL 12345;,一条条执行——只杀 Sleep 超 60 秒的,别碰 Command 是 Query 的连接,否则可能干掉正在跑的转账事务。
如果杀完仍接近上限,执行:SET GLOBAL max_connections = 300;。注意:【每增加 100 连接约多占 200MB 内存,调前务必确认剩余内存 ≥1GB】。
堵住泄漏口:统一配置 + 强制复用
打开 config/database.php,找到 mysql 配置块,检查以下三项是否全部存在且值正确:
① 'deploy' => 1 —— 必须是整数 1,不能写 true 或 '1',否则复用不生效;
② 'hostname' => 'mysql' —— 如果用 Docker,必须填容器名,不能写 localhost 或 127.0.0.1,后者在容器内指向自己;
③ 'params' => [PDO::ATTR_TIMEOUT => 5, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"] —— 缺一不可,否则 PDO 建连卡死或字符集错乱。
所有 Db::connect() 调用必须收口到一个工厂函数,禁止在中间件、模型、命令行脚本里硬编码不同 charset(如 utf8 vs utf8mb4)或不同 host(127.0.0.1 vs localhost),哪怕只差一个字母,TP 就视为全新配置,新建连接永不归还。
优化 SQL 并释放连接资源
方法一:把循环里反复查同表的操作合并成一次 IN 查询
错误写法:foreach ($ids as $id) { Db::name('user')->where('id', $id)->find(); }
正确写法:Db::name('user')->where('id', 'in', $ids)->select(); —— 1 次连接完成全部查询,避免 N+1 连接风暴。
方法二:CLI 和 Swoole 任务末尾必须手动 close
在命令行脚本结尾加:Db::close();;在 Swoole 任务中,go(function () { ... Db::close(); }); —— FPM 自动释放,但 CLI/Swoole 不关,连接对象常驻内存,越积越多。
方法三:事务内严禁跨协程调用Db::transaction(function () { ... }); 必须在同一个协程上下文执行,如果在 go(function () { Db::transaction(...) }) 里启动事务,连接会在协程结束时被销毁,事务回滚失败,连接卡死不归还。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











