thinkphp本身无内置数据库连接池,仅在swoole协程环境下通过swoole\coroutine\mysql及deploy=>1配置实现连接复用;fpm模式下pool配置完全无效,连接数飙升主因是事务未提交、cli未close或debug开启导致复用失效。

ThinkPHP 本身没有内置数据库连接池,所谓“二级域名后连接池耗尽”,本质不是二级域名导致的,而是多子域名共用同一套数据库配置时,未意识到运行环境差异(FPM vs Swoole)、复用机制失效或泄漏叠加放大了问题。关键不在域名,而在部署模型和配置是否匹配真实运行态。
先确认你到底有没有连接池
很多人在 config/database.php 里写了 'pool' => ['max' => 20] 就以为开了池——其实 FPM 模式下这个配置完全被忽略。只有在以下两种情况才真正生效:
- 使用 think-swoole 或 Swoole CLI 模式 启动(如
php think swoole),且数据库驱动为mysql; - 手动集成 Swoole\Coroutine\MySQL 或第三方协程池组件(如
swoole/database)。
FPM 下每个请求都是独立进程,连接生命周期随 PHP 进程结束自动释放,不存在“池耗尽”,只可能因慢查询、事务卡住、CLI 未 close 导致连接堆积。
二级域名常见误操作:配置不一致触发新连接池
多个二级域名(如 user.example.com、api.example.com)若共用同一套 ThinkPHP 应用但通过不同入口或环境变量加载数据库配置,极易因细微差异破坏连接复用:
-
'hostname' 写成 'host',或大小写不统一(
localhostvs127.0.0.1),TP 视为不同配置,无法复用 PDO 实例; - 未显式配置 'deploy' => 1,默认关闭复用,每次 Db::connect() 都新建 PDO;
- 跨域名调用中混用 Db::connect('log_db') 或动态传参(如
Db::connect(['hostname' => $domain_host])),绕过配置缓存,强制新建连接。
真正起作用的连接数控制参数
在 Swoole 协程环境下,以下参数才实际参与连接管理(FPM 下无效):
- 'max_active' => 20:池中最多允许 20 个正在执行 SQL 的连接,超限会阻塞或报错,是防打爆数据库的核心闸门;
-
'min_idle' => 5:启动时预建 5 个空闲连接,避免首请求等待,但设太高可能一上来就触达 MySQL 的
wait_timeout限制; - 'max_wait_time' => 3000:获取连接超时毫秒数,低于 2000 容易在高并发下批量报 Wait timeout for connection;
-
'pool_size' => 20:仅在
deploy => 1开启时限制同配置 PDO 实例数量,防止反复创建对象,但不控制底层 TCP 连接数。
注意:idle_timeout 在 TP6.1+ 中未实际生效;timeout 是单条 SQL 执行超时,与连接池无关。
必须堵住的三个泄漏口
无论是否二级域名,只要连接数飙升,90% 出自以下三类代码问题:
-
事务未兜底:开启事务后抛异常没 catch,或漏写
$db->commit()/$db->rollback(),连接永久卡在Transaction状态; -
CLI/Swoole 长任务不关连接:命令行脚本或定时任务执行完
Db::table()->select()后,未调Db::close(),PDO 实例常驻内存; -
debug 模式开着跑线上:
'debug' => true会禁用所有连接复用逻辑,每次查询都新建连接,二级域名多入口更易暴露此问题。
验证方法:在查询前加 Log::info('conn: '.spl_object_id($connection));,两个快速请求若 ID 不同,说明复用未生效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











