swoole 4.3+ 已彻底移除异步回调客户端,协程同步模式(如swoole\coroutine\mysql)是唯一可用方案,必须在go()或co::create()启动的协程中使用,否则报错。

别再拿“异步回调”当 Swoole 客户端的默认解法了——Swoole 4.3+ 已彻底移除异步 MySQL 回调客户端,协程同步模式才是当前生产环境的事实标准。
为什么 swoole_async_mysql 在新项目里根本不能用
官方早在 Swoole 4.3 就废弃并移除了基于回调的异步 MySQL 客户端(swoole_async_mysql),现在调用它会直接报 Class 'swoole_async_mysql' not found。这不是配置问题,是类本身被删了。
- 旧版(≤4.2)靠层层 callback 实现异步,比如
mysql_query($sql, $callback),嵌套深、错误难追踪、事务几乎没法写 - 新版(≥4.3)只保留协程 MySQL 客户端:
Swoole\Coroutine\MySQL,必须在co::create()或go()启动的协程中使用 - 强行复用老教程代码,第一行就会 fatal error,连启动都失败
Swoole\Client 同步 vs 异步:连接失败时行为完全不同
同步客户端(Swoole\Client 构造时传 SWOOLE_SOCK_TCP)调用 connect() 是阻塞的,返回布尔值;异步客户端(传 SWOOLE_SOCK_TCP | SWOOLE_SOCK_ASYNC)则立即返回 true,靠 on('connect') 事件通知结果。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 同步模式下,
if (!$client->connect(...)) { echo $client->errCode; }能立刻拿到错误码,适合调试和短连接场景 - 异步模式下,
$client->errCode在on('connect')触发前无意义,错误要从on('error')或on('close')的参数里取 - 异步客户端一旦
connect()返回 true,后续所有操作(send/recv)都必须走事件回调,不能混用同步收发
HTTP Server 中用 curl_exec 就是同步阻塞,但加个 go() 就不是了
很多人以为“用了 Swoole 就自动异步”,其实不然:curl_exec、file_get_contents、mysql_query 这些原生函数,在 Swoole Worker 进程里仍是同步阻塞的,会卡住整个进程。
- 正确做法是把耗时 IO 操作包进协程:
go(function () { $data = (new Swoole\Coroutine\Http\Client('api.example.com', 443))->get('/v1/user'); }); - 错误做法是直接在
on('request')里调curl_exec,哪怕只 sleep(1),QPS 也会断崖下跌 - 注意:
Swoole\Coroutine\Http\Client必须用go()启动,不能在普通函数里 new 了就 send —— 协程上下文缺失会导致send返回 false
协程客户端不是“语法糖”,它依赖底层调度器
协程同步写法看着像传统 PHP,但背后是 Swoole 的协程调度器在接管 IO 等待。你写 $mysql->query('SELECT ...'),实际执行时线程没阻塞,而是让出控制权给其他协程。
- 必须确保运行在
go()或co::create()内,否则Swoole\Coroutine\MySQL::connect()会抛出Co::sleep(): must be called in the coroutine类似错误 - 数据库连接池、Redis 连接复用等高级功能,也只在协程环境下生效;同步客户端无法共享连接,每次都要重连
- 别试图在协程里用
pcntl_fork或exec,协程上下文会丢失,大概率 segfault










