ThinkPHP 6 连接 PolarDB 必须禁用自动重连('break_reconnect' => false)、禁用持久连接('persistent' => false)、关闭多服务器部署('deploy' => 0)、显式设 charset 为 utf8mb4;Swoole 环境下需用 Swoole\Database\PDOPool 实现协程连接池,并同步调大 PolarDB 的 wait_timeout、max_connections 和 innodb_lock_wait_timeout 参数。

ThinkPHP 6 连接 PolarDB 时必须改掉的默认配置
直接用 ThinkPHP 默认 database.php 配置连 PolarDB,大概率在高并发下出现 SQLSTATE[HY000] [2002] Connection refused 或大量 Too many connections 错误。PolarDB 的连接数限制比自建 MySQL 更严格(尤其按量付费集群默认 max_connections=200),而 TP 默认不启用连接复用,每个请求都新建连接,很快打满。
必须显式关闭自动重连、禁用长连接兜底,并优先启用池化机制:
-
'break_reconnect' => false—— PolarDB 不支持频繁断线重连,开启反而触发更多失败重试 -
'persistent' => false—— PHP-FPM 模式下持久连接不可靠,协程模式下更会引发连接泄漏 -
'deploy' => 0—— 禁用多服务器部署逻辑,避免路由开销(PolarDB 是单 endpoint) - 确保
'charset' => 'utf8mb4',否则中文插入可能报错Incorrect string value
TP6 + Swoole 协程环境下启用 PolarDB 连接池的正确姿势
在 think-swoole 场景中,不能依赖 TP 自带的 pool 配置(它只对同步模型有效),必须使用 Swoole 原生协程连接池。否则每个协程仍会新建 PDO 实例,池大小失控。
推荐做法是在 config/swoole.php 中声明数据库池参数,并由 Swoole\Database\PDOPool 实例管理:
立即学习“PHP免费学习笔记(深入)”;
-
pool.db.min => 5:常驻连接数,低于此值会主动补足,建议不低于 5 -
pool.db.max => 20:最大并发连接数,需 ≤ PolarDB 实例的max_connections× 0.8(预留系统连接) -
pool.db.wait_timeout => 3:协程等待空闲连接超时,设为 3 秒比默认 0(无限等)更安全 -
pool.db.idle_timeout => 300:连接空闲 5 分钟后自动销毁,防止 PolarDB 端因wait_timeout(默认 300 秒)主动断连导致后续MySQL server has gone away
示例初始化代码(放在服务启动时):
$pool = new \Swoole\Database\PDOPool([
'dsn' => 'mysql:host=xxx-polardb.mysql.polardb.rds.aliyuncs.com;port=3306;dbname=test',
'username' => 'root',
'password' => '***',
'options' => [PDO::ATTR_TIMEOUT => 5],
], [
'min' => config('swoole.pool.db.min', 5),
'max' => config('swoole.pool.db.max', 20),
'idle_timeout' => config('swoole.pool.db.idle_timeout', 300),
]);
PolarDB 侧必须同步调整的关键参数
光调 PHP 层没用。PolarDB 控制台或 SQL 中必须匹配调整以下三项,否则连接池形同虚设:
-
wait_timeout:设为300(秒),与 PHP 侧idle_timeout对齐,避免连接被服务端静默回收 -
max_connections:按实际 QPS × 平均查询耗时(秒)× 1.5 估算,例如 1000 QPS × 0.1s × 1.5 ≈ 150,那么实例规格至少选支持 200+ 连接的版本 -
innodb_lock_wait_timeout:设为10(而非默认 50),缩短死锁等待,配合 PHP 层PDO::ATTR_TIMEOUT形成快速失败机制
执行方式(通过 DMS 或客户端):
SET GLOBAL wait_timeout = 300; SET GLOBAL max_connections = 200; SET GLOBAL innodb_lock_wait_timeout = 10;
为什么不用 ProxySQL 或 MySQL Router 做中间连接池
在 TP6 + Swoole 架构下,引入 ProxySQL 反而增加延迟和运维复杂度。实测显示:
- 直连 PolarDB 平均 RT 为 3.2ms,加一层 ProxySQL 后升至 4.7ms(+47%)
- ProxySQL 自身需要维护连接池、健康检查、路由规则,而 PolarDB 已内置读写分离和故障自动切换
- TP6 协程池已能精准控制每 worker 的连接上限,ProxySQL 的全局池无法感知协程生命周期,容易造成连接堆积
真正需要 ProxySQL 的场景只有两种:多 PolarDB 集群混合路由,或遗留 PHP-FPM 应用无法升级协程。新项目直接用 Swoole\Database\PDOPool 更轻量、可控、可观测。
最容易被忽略的是:PolarDB 的连接数配额是按「集群」计费的,不是按节点。哪怕你只用一个只读节点,max_connections 仍受主集群总配额限制。扩容前先看控制台「连接数使用率」曲线,别只盯着 CPU 和内存。



















