mysql 慢查询日志需在 mysql 服务端开启,hyperf 不控制该开关;执行 show variables like 'slow_query_log' 确认是否为 on,配合 set global slow_query_log = 'on' 和 long_query_time = 1,并注意连接池复用导致延迟生效。

Hyperf 项目里 MySQL 慢查询日志不是框架自动开的,得从 MySQL 服务本身入手——Hyperf 只负责发 SQL,不控制日志开关。
确认 MySQL 的 slow_query_log 实际是否开启
很多人以为在 Hyperf 配置里加了 slow_query_log = 1 就生效了,其实那是无效的。MySQL 慢查日志开关只认自己的配置或运行时变量:
- 登录 MySQL 执行
SHOW VARIABLES LIKE 'slow_query_log';,返回ON才算真开了 - 如果返回
OFF,哪怕 Hyperf 的数据库配置写了options或attributes,也完全不影响 - 检查
slow_query_log_file路径是否存在、MySQL 进程(如mysql用户)是否有写权限,常见路径如/var/log/mysql/slow.log -
long_query_time默认是10.000000,业务里多数慢 SQL 在 1–3 秒,设成1更实用
临时开启适合调试,但要注意连接生效范围
Hyperf 应用重启后,SET GLOBAL 设置会丢失,但它对「新建立的连接」立即有效——而 Hyperf 的连接池复用旧连接,所以你可能看不到日志立刻变多:
- 执行
SET GLOBAL slow_query_log = 'ON';(必须用字符串,部分版本不认数字1) - 执行
SET GLOBAL long_query_time = 1;,注意这个值对当前会话不生效,只影响后续新连接 - Hyperf 连接池里的空闲连接不会重连,要等连接被回收重建,或手动清空连接池(如重启 Hyperf 进程)
- 验证是否真起效:在 Hyperf 里执行一条明显慢的 SQL,比如
SELECT SLEEP(2);,再查日志文件有没有新增记录
用 mysqldumpslow 快速定位高频慢 SQL
Hyperf 日志里看不出 SQL 执行耗时,但 MySQL 慢日志里每条记录都带时间戳和实际执行时间,mysqldumpslow 是最轻量的分析工具:
-
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log:按耗时倒序取前 10 条 -
mysqldumpslow -s c -t 5 /var/log/mysql/slow.log:按出现次数排序,找被高频调用的慢 SQL -
mysqldumpslow -g 'JOIN' /var/log/mysql/slow.log:过滤含 JOIN 的语句,这类容易缺索引 - 注意:Hyperf 自动生成的 SQL(如 Eloquent 查询、DTO 绑定生成的
WHERE IN)常出现在日志里,别直接优化框架代码,先看EXPLAIN结果
log_queries_not_using_indexes 开关要谨慎开
这个选项会让所有没走索引的查询都进慢日志,看起来“排查更全”,但在 Hyperf 场景下极易误伤:
- Hyperf 的批量操作(如
whereIn传空数组、关联预加载未加with条件)可能生成无条件全表扫描 - 日志量爆炸,
slow.log几分钟就几百 MB,IO 压力陡增,线上环境基本不可用 - 真正该关注的是“本该走索引却没走”的 SQL,而不是“压根没设计索引”的场景——后者该补索引,不是靠日志抓
- 建议仅在问题复现阶段临时打开,确认后关掉,用
EXPLAIN配合具体 SQL 分析更准
Hyperf 本身不干预 MySQL 日志行为,所有开关、阈值、路径都在 MySQL 侧;最容易忽略的是连接复用导致的“开了日志却没记录”,别急着改框架配置,先盯住 SHOW GLOBAL STATUS LIKE 'Slow_queries'; 看计数是否增长。











