Hyperf 3.1 CLI 命令中使用协程 MySQL 需手动启用协程环境(Swoole/Swow)、通过 DI 获取 ConnectionInterface、配置数据库连接池,并在 co() 中执行查询或 transaction() 管理事务。

在 Hyperf 3.1 的命令行 Command 中使用协程 MySQL,核心是确保环境已协程化、连接走框架封装的协程客户端(非原生 PDO 或 mysqli),且不破坏 CLI 生命周期。直接用 sleep()、file_get_contents() 或原生 mysqli_connect() 会阻塞整个进程,必须规避。
确认协程运行环境已启用
CLI 模式下协程不会自动开启,需手动启用:
- 在 Command 类的
handle()方法开头调用Swoole\Runtime::enableCoroutine(true)(Swoole 引擎)或Swow\Runtime::enableCoroutine()(Swow 引擎) - 若使用 Swoole,还需确保
php --ri swoole输出中含support coroutines: enabled - Hyperf 默认未在 CLI 中自动启用协程,漏掉这步会导致后续所有数据库调用退化为同步阻塞
使用框架封装的协程数据库连接
不要手动 new PDO 或 mysqli,而是通过 DI 容器获取 Hyperf\Database\Connection 实例:
- 在 Command 构造函数中注入
ConnectionInterface $connection(推荐)或通过$this->container->get(Connection::class)获取 - 确保
config/autoload/databases.php已正确配置 MySQL 驱动和连接池参数(如min_connections、max_connections) - 连接池在 CLI 下仍有效,但注意:单次命令执行生命周期短,连接不会长期驻留,无需手动释放
在协程上下文中执行查询
Command 的 handle() 是同步方法,如需并发执行多个查询,需显式创建协程:
- 用
co(function () use ($connection) { ... })包裹异步操作(推荐,自动捕获异常+继承上下文) - 避免在协程外直接调用
$connection->select()等方法——它虽协程安全,但若外部无协程环境,会退化为同步 - 示例:
co(fn() => $connection->table('users')->where('id', 1)->first());
事务与连接状态管理
CLI 命令通常单次执行、无请求上下文,需特别注意事务边界:
- 用
$connection->transaction(fn() => { ... })包裹事务逻辑,框架会自动 commit/rollback - 切勿手动调用
beginTransaction()+commit(),易因异常未捕获导致连接残留或跨协程污染 - 若命令中多次调用 DB,连接由连接池复用,无需担心开销











