Hyperf 的 MySQL 协程不生效主因是驱动或配置未走协程路径:需确认 Swoole 支持协程、禁用 pdo_mysql、DB 配置 driver 设为 'mysql'、连接池参数正确,且避免手动 new PDO 或同步调用。

Hyperf 的 MySQL 协程不生效,通常不是“协程没开启”,而是底层驱动或配置没走协程路径——最常见原因是用了非协程版 PDO 或 Swoole 扩展,或连接池配置绕过了协程机制。
确认是否真在用协程驱动
Hyperf 默认优先使用 Swoole\Coroutine\MySQL(纯协程),其次 fallback 到 PDO。但若未正确安装/启用协程版扩展,就会退化为同步阻塞模式:
- 运行
php --ri swoole,检查输出中是否有 support coroutines: enabled;没有则说明加载的是旧版或非协程版 Swoole - 执行
php -m | grep pdo,确认pdo_mysql已启用;但注意:pdo_mysql 本身不支持协程,仅当配合 Swoole 协程 MySQL 驱动时才真正异步 - 查看日志或调试时打印
DB::connection()->getPdo()实例类型:如果是Swoole\Coroutine\MySQL对象,说明协程生效;若是PDO,说明降级了
检查数据库配置是否启用协程连接池
即使扩展就绪,Hyperf 仍可能因配置问题跳过协程连接池:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 确保
config/autoload/db.php中对应数据库的driver明确设为 'mysql'(不是 'pdo_mysql') - 确认
pool配置存在且未被覆盖,例如:'min_connections' => 1, 'max_connections' => 32;若max_connections为 0 或缺失,连接池可能被禁用,退化为每次新建连接 - 避免在代码中手动 new PDO() 或调用原生 mysql_connect() —— 这些会彻底脱离协程调度
验证协程是否实际切换
光有协程驱动还不够,得看执行时有没有真正让出控制权:
- 写个简单接口,在 DB 查询前后加
Co::stats()['coroutine_num']打印协程数,若查询前后数值不变,说明没发生协程切换(可能是慢查询卡死、或连接池返回了阻塞连接) - 用
SELECT /*+ MAX_EXECUTION_TIME(500) */ ...主动加语句级超时,防止单条 SQL 拖垮整个协程;若超时后服务仍无响应,大概率是底层未走协程路径 - 禁用所有中间件和装饰器临时测试,排除自定义逻辑中混入了
sleep()、file_get_contents()等同步调用
排查连接池空转或降级场景
有些情况下协程“看似启动”,实则连接池始终复用一个连接、未并发分发:
- 检查
pool.wait_timeout是否过小(如设成 0.1),导致协程频繁等待新连接,掩盖了并发能力 - 确认没有全局开启
DB::disableQueryLog()后又误用DB::enableQueryLog(),日志收集本身会引入同步开销 - 容器部署时注意:若 MySQL 地址写的是
localhost,部分 Swoole 版本会自动走 socket 连接(非协程),应改用127.0.0.1强制走 TCP










