TP5连接数过高主因是“连上了不放”或“不该连的连太多”,需通过SHOW PROCESSLIST定位Sleep连接、慢查询及异常用户,禁用持久连接、显式关闭CLI/循环连接,并调小wait_timeout而非盲目增大max_connections。

ThinkPHP5 默认用短连接,连接数高基本不是“连不上”,而是“连上了不放”或者“不该连的连了太多”。直接调大 max_connections 是掩耳盗铃,得先定位是哪类连接在占坑。
查清楚到底是哪些连接在堆积
别只看总数。登录 MySQL 执行:SHOW PROCESSLIST,重点关注三列:
-
Command是Sleep且Time超过 60 秒的——大概率是 PHP 请求结束后没释放连接,或 FPM 进程卡住没退出 -
Info字段为空但Time很长的——可能是事务没提交、锁没释放,或查询被阻塞 -
User和Host能帮你确认是不是某台应用服务器集中打爆了连接
同时打开 MySQL 慢日志:slow_query_log = ON,long_query_time = 1,把慢查和堆积的 Sleep 连接对照着看,才能分清是代码问题还是 SQL 问题。
TP5 配置里禁用持久连接(尤其 FPM 环境)
ThinkPHP5 的数据库配置支持 'persistent' => true,但这个在 PHP-FPM 下非常危险:
- PHP 7.0+ 已移除
mysql_pconnect,而 TP5 底层用的是 PDO 或 MySQLi,persistent实际触发的是PDO::ATTR_PERSISTENT - FPM worker 进程复用时,持久连接不会真正关闭,残留事务、临时表、会话变量都可能污染后续请求
- 连接数不降反升,且
SHOW PROCESSLIST里大量Sleep连接长期不回收
✅ 正确做法:配置中显式关掉——'persistent' => false(TP5 默认就是 false,但检查下 config/database.php 别被手动改过);如果用了 params 手动传 PDO 属性,确保里面没写 PDO::ATTR_PERSISTENT => true。
立即学习“PHP免费学习笔记(深入)”;
循环/命令行/长任务里必须显式关闭连接
TP5 不会在脚本中途自动关连接,只在请求结束时由框架回收。但以下场景它管不了:
- CLI 模式跑的定时任务,比如用
php think command:run,执行完不退出进程,连接一直挂着 - 大循环里反复调用
Db::table()->select(),每次都会新建连接(除非你复用 Query 对象) - try/catch 中发生异常,
Db::close()没被执行
✅ 解决方式:
- 循环外建好
$db = Db::name('user'),循环内只调方法,别反复 new - CLI 任务末尾加
Db::close();更稳妥的是用unset($db)或$db = null - 关键路径用 try-finally 包裹,finally 里强制
Db::close()
别信“TP5 原生支持连接池”这种说法
TP5 本身没有连接池实现。你在文档或社区看到的 'pool' => [...] 配置,只在配合 think-swoole 或自定义协程扩展时才生效。FPM 下配了也白配,连接照样一个请求一个新连。
- 如果你还在用 Apache/FPM,就老老实实优化单次连接生命周期:合并查询、加索引、开缓存、减
wait_timeout - 真要上连接池,得切到 Swoole 协程环境,并用
Swoole\Coroutine\MySQL或hyperf/database这类真正管理连接生命周期的组件 - ProxySQL 这类代理层可以做连接池,但它是数据库侧的事,和 TP5 配置无关,别指望改个数组就能池化
最常被忽略的一点:连接数高 ≠ 性能差。很多是空闲连接(Sleep)堆在那里,根源其实是 wait_timeout 太大(默认 8 小时),而不是 PHP 写错了。先调小它,再观察 —— 往往比改代码见效更快。



















