hyperf 项目连接 mysql 失败通常源于配置、权限或网络问题,而非携程 mysql-client 本身 bug;需确认是否显式引入、配置 driver 为 'mysql-client' 并注册连接器,再排查 error 2003(网络监听)、error 1045(用户 host 不匹配)、连接池参数及 per-worker 连接数超限。

Hyperf 项目里用携程开源的 mysql-client(即 ctripcorp/apollo-mysql-client 或其衍生版)连接 MySQL 失败,大概率不是客户端本身 bug,而是配置、权限或网络链路没对齐。直接改代码前,先确认它是否真在用——Hyperf 默认用的是 pdo_mysql 或 hyperf/database 封装的 PDO,携程客户端需显式引入和注册,否则报错跟它无关。
确认是否真在用携程 MySQL 客户端
很多人以为“Hyperf + MySQL”就等于用了携程客户端,其实不是。携程的 mysql-client 是独立于 Hyperf 生态的异步纯 PHP 实现,需手动安装、配置并替换默认 DB 组件。如果没显式执行以下操作,那报错跟它完全无关:
- 执行过
composer require ctripcorp/mysql-client - 在
config/autoload/db.php中把driver改成'mysql-client'(而非'pdo') - 注册了对应连接器,比如通过
MySqlConnectionProvider替换默认PdoConnectionProvider
若没做这三步,却看到类似 Class 'CtripCorp\MySQL\Client' not found 或 Unknown driver mysql-client,说明只是依赖没装或配置写错,不是连接逻辑问题。
ERROR 2003 / Connection refused:网络与监听层卡死
这是最常被误判为“客户端问题”的错误,实际 90% 出在服务端绑定或中间链路。Hyperf 应用报 Can't connect to MySQL server on 'x.x.x.x' (111),优先检查:
- MySQL 是否监听在
0.0.0.0:3306而非仅127.0.0.1:3306:运行ss -tlnp | grep :3306,看LISTEN行的地址是不是*:3306或0.0.0.0:3306 - Hyperf 容器是否能直连 MySQL IP:进容器执行
telnet your-mysql-ip 3306,不通就不是 PHP 代码问题,是 Docker 网络、K8s Service 或宿主机防火墙拦住了 - 云服务器安全组是否放行了入方向 3306(源 IP 填 Hyperf 所在机器的公网或内网 IP,不是 0.0.0.0/0)
注意:携程客户端不走 Unix socket,只支持 TCP,所以 localhost 在配置里等价于 127.0.0.1,别指望它自动 fallback 到 sock 文件。
ERROR 1045 / Access denied:用户 Host 匹配失败
Hyperf 配置里写的是 'user' => 'app_user',但 MySQL 里只建了 'app_user'@'localhost',而 Hyperf 运行在容器或远程机器,实际连接来源 IP 是 'app_user'@'172.18.0.5' 或 'app_user'@'10.10.20.33',权限不匹配就直接拒掉。验证方式:
- 登录 MySQL 执行
SELECT User, Host FROM mysql.user WHERE User = 'app_user';,确认有对应 Host 的记录 - 不要图省事全用
'app_user'@'%',尤其生产环境;如必须,确保密码强度够,且 MySQL 的skip-name-resolve已开启,避免 DNS 反查拖慢连接 - MySQL 8.0+ 默认密码插件是
caching_sha2_password,而老版本携程客户端可能只支持mysql_native_password,建用户时得显式指定:CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123';
连接池耗尽或超时:携程客户端参数没调对
携程客户端自带连接池,但不像 Hyperf 自带的 hyperf/database 那样开箱即用。如果并发稍高就报 Too many connections 或长时间卡住,重点看这几个配置项(通常在 config/autoload/db.php 的 pool 下):
-
min_connections:别设 0,至少 2~3,冷启动时不等建连 -
max_connections:不能只看 PHP 进程数,要结合 MySQL 的max_connections(SHOW VARIABLES LIKE 'max_connections';),建议设为后者的 60%~70% -
connect_timeout和wait_timeout:携程客户端默认值偏保守,设成3.0和5.0更稳,避免网络抖动时频繁重试压垮服务 -
max_idle_time:设太长(如 60s)会导致空闲连接堆积,MySQL 端先断,下次用时报MySQL server has gone away;建议 20~30 秒
真正容易被忽略的是:携程客户端的连接池是 per-process 的,不是 per-worker。Hyperf 多 worker 模式下,每个 worker 进程都持有一套独立连接池,总连接数 = worker 数 × max_connections。没算准这个,MySQL 很快就爆 Too many connections。











