必须结合Hyperf连接池指标(如hyperf_db_pool_active_connections)与MySQL原生指标(如mysql_global_status_threads_connected、threads_running)关联分析,才能准确定位连接池饱和、连接泄漏或MySQL端锁等待等真实瓶颈,单看hyperf_db_query_duration_ms会遗漏排队、建连、锁竞争等关键问题。

Hyperf 的 MySQL 协程连接监控不能只看框架层的耗时指标,必须把应用侧连接池状态和数据库底层运行状态结合起来看,否则容易误判。
看 Hyperf 连接池自身使用情况
Hyperf 通过 hyperf/metric 上报连接池关键指标,比如:
- hyperf_db_pool_active_connections:当前已借出、正在被使用的连接数
- hyperf_db_pool_idle_connections:当前空闲、可立即复用的连接数
- hyperf_db_pool_wait_duration_seconds_count:因连接池满而排队等待的次数(注意不是耗时)
- hyperf_db_query_duration_ms:仅记录 PDO 执行 SQL 的耗时,不含排队、建连、锁等待
这些指标可通过 Prometheus 抓取,默认路径为 /metrics。重点观察 active / (min + max) 比值是否长期高于 80%,以及 wait_duration 是否突增——这说明连接池配置偏小或存在泄漏。
查 MySQL 实例真实连接状态
Hyperf 层看到的是“池子里有没有连接”,而 MySQL 层告诉你“这些连接到底在干什么”。需依赖 mysqld_exporter 暴露的原生指标:
- mysql_global_status_threads_connected:当前所有客户端连接总数(含 Sleep)
- mysql_global_status_threads_running:真正执行 SQL 的活跃线程数
- mysql_global_status_threads_created:累计创建线程数,增长快说明连接复用差
- mysql_global_status_aborted_connects:失败连接数,突然上升可能意味着账号权限/网络/密码错误
特别注意:Threads_connected 和 hyperf_db_pool_active_connections 数值通常不一致——前者包含应用未释放的连接、命令行调试连接、监控采集连接等;后者只反映 Hyperf 当前借出的连接。两者差异大,就该查 SHOW PROCESSLIST 找异常连接。
配好 mysqld_exporter 权限与抓取方式
mysqld_exporter 必须用最小权限账号运行,推荐授权语句:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
CREATE USER 'exporter'@'%' IDENTIFIED BY 'strong_password'; GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'%'; FLUSH PRIVILEGES;
Prometheus 抓取配置要匹配部署方式:
- Hyperf 和 mysqld_exporter 同容器网络:target 填
mysqld-exporter:9104,启动参数加--mysqld.address=host.docker.internal:3306 - mysqld_exporter 装在宿主机:target 填
宿主机IP:9104,--mysqld.address必须写 MySQL 真实 IP(不能是 127.0.0.1)
如果 exporter 启动报错 SELECT command denied to user ... for table 'processlist',就是权限没给够,需回退检查。
结合 processlist 定位具体问题连接
当发现 Threads_connected 高但 Threads_running 很低,大概率是大量 Sleep 连接堆积。执行:
SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO FROM information_schema.PROCESSLIST WHERE TIME > 60 ORDER BY TIME DESC LIMIT 20;
重点关注:
- 同一
USER+HOST出现几十个连接 → 应用端未正确复用连接池 -
COMMAND = Sleep且TIME超过wait_timeout(默认 28800 秒)→ 连接被 MySQL 主动断开,但应用没感知,仍留在池中 -
STATE = Sending data或Locked且TIME长 → 慢查询或锁竞争,需结合慢日志和innodb_row_lock_time_avg判断
Hyperf 侧可配合开启 max_idle_time(建议设为略小于 MySQL 的 wait_timeout),让空闲连接主动归还,避免僵尸连接堆积。










