deploy => 1是TP6连接复用的关键开关,启用后即使无从库也缓存PDO实例;它要求配置完全一致才复用,且必须为整数1,配合pool_size和MySQL max_connections调优。

ThinkPHP 6 的 deploy => 1 是连接复用的关键开关,不是“长连接”配置
TP6 根本不支持 PDO 原生持久化(PDO::ATTR_PERSISTENT => true),即使你写进 params 也基本无效——因为 Connection 类在析构时强制置空 $this->pdo,持久化标志被绕过。
真正起作用的是 deploy => 1:它启用框架内置的连接复用逻辑,哪怕你没配从库,也会缓存同配置的 PDO 实例。这个机制不依赖驱动层,而是靠 TP 自己管理连接生命周期。
-
deploy => 1必须设为整数1,设成true或字符串"1"会静默失效 - 该复用只对「完全一致」的连接配置生效:主机、端口、库名、用户名、密码、字符集全部相同才进同一个池
- 换一个库名(比如从
main_db切到log_db)就会新建池,不会复用 - 搭配
pool_size => 20可限制最大空闲连接数,避免 MySQL 端堆积(但注意:TP6 默认不自动清理空闲连接)
MySQL 侧的 max_connections 必须 ≥ TP 连接池预期上限
压测时出现 Too many connections,90% 不是 TP 配错了,而是 MySQL 服务端硬性拒绝了新连接请求。
TP6 的连接复用只在应用层做缓存,不改变 MySQL 对每个连接的计数。如果你设了 pool_size => 50,但 MySQL 的 max_connections = 151 被其他服务占掉 120 个,那只剩 31 个可用,池根本拉不满。
立即学习“PHP免费学习笔记(深入)”;
- 查当前值:
SHOW VARIABLES LIKE 'max_connections'; - 临时调高:
SET GLOBAL max_connections = 500;(需 SUPER 权限) - 永久生效:在 MySQL 配置文件(
my.cnf)中加max_connections = 500,并按内存估算(每连接约占 2–3MB) - 别只盯 TP 配置——先确认
SHOW PROCESSLIST里真实活跃连接数是否已逼近上限
TP8 的连接池必须走 think-swoole,database.php 加 pool 字段无效
TP8 原生不提供连接池能力。database.php 里硬加 pool_size、max_connections 等字段,运行时会被忽略,没有任何日志提示。
真要上连接池,必须用 think-swoole 扩展,并在 config/swoole.php 的 database 节点下配置:
return [
'database' => [
'enable' => true,
'min_connections' => 5,
'max_connections' => 50,
'wait_timeout' => 3.0,
'heartbeat' => 30,
],
];
-
enable => true是开关,缺省或设为false就走默认短连接 -
max_connections是池内总连接数(空闲 + 忙碌),不是并发查询数;它必须 ≤ MySQL 的max_connections -
wait_timeout是协程等待空闲连接的超时秒数,设太小(如0.1)会导致频繁抛ConnectionPoolTimeoutException - 验证是否生效:在控制器里调
Db::getPdo()多次,同一协程内返回的 PDO 实例应是同一个对象
心跳检测 keep_alive 在 PDO 下基本不工作
TP 官方文档里写的 keep_alive 配置项,仅对 mysqli 驱动有效。PDO 驱动下该参数被直接忽略,且没有 fallback 行为。
如果你用的是默认 PDO(绝大多数情况),想保活就得手动加 ping 检查,最稳妥的位置是在每次 HTTP 请求开始时:
public function handle($request, \Closure $next)
{
try {
Db::connect()->getPdo()->query("SELECT 1");
} catch (\Throwable $e) {
// 触发重连
Db::close();
Db::connect();
}
return $next($request);
}
- 别依赖
keep_alive,PDO 下它形同虚设 - 用
query("SELECT 1")替代ping(),因为 PDO 没这个方法 - Swoole 协程环境下,TP 的连接管理完全失能,必须自己控制连接生命周期
- 最容易漏的是:MySQL 的
wait_timeout设得太大(比如 28800 秒),而应用层又没主动检查,导致连接在池里“假死”



















