tp8在swoole协程下需满足php think swoole启动、swoole≥5.1且enable_coroutine=1、tp≥8.0.12、禁用阻塞函数,方能启用db::table()底层的connectionpool实现协程安全连接复用。

TP8 在 Swoole 环境下对数据库连接管理做了实质性升级,核心是让连接真正可复用、可调度、可感知协程上下文——但这不是配置开关就能生效的“自动优化”,而是依赖运行环境、版本、驱动和调用方式四者严格匹配。
默认启用协程安全连接池(仅限 Swoole 协程模式)
TP8 的 Db::table('user')->where()->paginate(15) 表面写法与 TP6 一致,但底层已注入 think\db\ConnectionPool,在满足前提时会自动走协程感知路径:
- 必须运行在
php think swoole启动的 Swoole 协程服务器上(php think run是 FPM,无此机制) - Swoole 扩展需 ≥ 5.1 且启用
enable_coroutine=1 - TP 版本 ≥ 8.0.12(早期 8.0.x 存在连接不归还 bug)
- 不能混用阻塞函数(如
curl_exec、file_get_contents),否则协程挂起,连接池失效甚至变慢
连接复用逻辑彻底重构
TP6 的分页完全同步执行:COUNT 查询和主查询共用一个 PDO 连接,在同一线程中顺序完成;TP8 则允许二者被调度到不同协程任务中,由连接池统一供给:
- COUNT 和主 SQL 可能并发执行,连接被复用而非新建
-
Db::getLastSql()在 TP8 中只反映最后一次执行语句,无法还原完整分页链(调试时需改用think debug:query) - 开启 QueryLog 时,日志顺序可能错乱(先记主查、后记 COUNT),甚至漏记其中一个
配置项语义变化明显
TP8 的 'pool' => ['enable' => true] 不再是“开个开关就有效”的设置,它只在协程环境下参与连接池调度:
- FPM 下该配置被完全忽略,
Db::connect()仍每次新建 PDO 实例 - PDO 驱动下,持久连接必须显式通过
'params' => [PDO::ATTR_PERSISTENT => true]设置,'persistent' => true配置项无效 - mysqli 驱动支持
'pconnect' => true,但在 PHP 8+ 中风险升高,不建议生产使用 - 真实连接池需手动集成
thinkswoole\pool\DatabasePool,并绑定到容器,而非依赖 Db 门面
连接泄漏风险更隐蔽,排查方式也不同
TP8 在协程下若使用不当,Sleep 连接堆积更难定位:
- 用
SHOW PROCESSLIST查看 Command 列,大量 Sleep 表示连接空闲未释放,不是并发高,是脚本没走完或异常中断 - 循环中反复调用
Db::table()->find()会持续申请新连接,应改用whereIn批量拉取 - 禁止在构造函数、同步中间件、定时任务回调中提前执行 DB 操作——协程一旦切出,连接即丢失
- 连接必须显式归还(
$pool->put($mysql)),不能调close()











