在Yii框架里做数据库访问时,默认每次请求都会新建一个数据库连接,高并发下容易产生大量 TIME_WAIT 和连接建立开销。虽然 PHP 的运行时模型决定了传统 FPM 模式下难以实现进程级常驻连接池,但我们依然可以通过长连接配置和外部中间件来优化。

一、Yii中如何开启数据库长连接
Yii的数据库组件基于 PDO,只要在配置数据库连接时给 PDO 属性加上 PDO::ATTR_PERSISTENT 就可以启用长连接。下面是一个典型的 Yii2 配置示例:
<?php
// config/db.php
return [
'class' => 'yiidbConnection',
'dsn' => 'mysql:host=127.0.0.1;dbname=test',
'username' => 'root',
'password' => '123456',
'charset' => 'utf8mb4',
'attributes' => [
// 开启PDO长连接
PDO::ATTR_PERSISTENT => true,
],
];
开启后,同一个 FPM 进程在多次请求中会复用同一个数据库连接,减少握手和认证消耗。但要注意,长连接会占用数据库端连接数,需要控制 PHP 进程总数。
二、使用连接池优化的几种思路
1. 结合Swoole实现协程连接池
如果项目使用了 Yii 配合 Swoole 运行,可以用 Swoole 提供的连接池管理 MySQL 连接。示例代码如下:
<?php
$pool = new SwooleConnectionPool(
function () {
$pdo = new PDO(
'mysql:host=127.0.0.1;dbname=test',
'root',
'123456',
[PDO::ATTR_PERSISTENT => false]
);
return $pdo;
},
64 // 最大连接数
);
// 获取连接
$conn = $pool->get();
$stmt = $conn->query('SELECT 1');
$row = $stmt->fetch();
$pool->put($conn);
2. 使用ProxySQL做中间层连接池
在不改动代码的情况下,可以把 Yii 的数据库 host 指向 ProxySQL,由 ProxySQL 维护后端 MySQL 的连接池,配置方式如下:
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'127.0.0.1',3306);
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('root','123456',1);
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
三、长连接与连接池的注意事项
- 长连接可能导致数据库端连接数堆积,需根据 FPM 或常驻进程数量合理设置 max_connections。
- 使用长连接时事务必须及时提交或回滚,避免连接复用时残留状态。
- 外部连接池方案需要额外维护中间件,适合明显存在连接瓶颈的服务。
| 方案 | 适用场景 | 改造成本 |
|---|---|---|
| PDO长连接 | FPM传统部署 | 低 |
| Swoole连接池 | 协程常驻服务 | 中 |
| ProxySQL | 多语言多服务共用 | 中高 |
四、小结
Yii框架本身没有独立连接池组件,但利用 PDO 的长连接属性就能缓解一部分连接创建开销;当并发进一步提升时,引入 Swoole 或 ProxySQL 等连接池方案是更彻底的优化手段。实际落地要结合部署架构与数据库承载能力做权衡。