开启 slow_query_log 后无日志的最常见原因是未设置 slow_query_log_file,导致日志未落地;需手动指定路径并确保 MySQL 进程有写权限,再用 SHOW VARIABLES 验证配置。

slow_query_log 开启后为什么没日志?
最常见原因是 slow_query_log 虽设为 ON,但没指定日志文件路径,MySQL 会默认写入错误日志(error_log)或直接丢弃——尤其在 5.7+ 版本中,若未显式设置 slow_query_log_file,日志可能根本不会落地。
- 务必手动配置
slow_query_log_file,例如:/var/log/mysql/mysql-slow.log - 确认 MySQL 进程对目标路径有写权限(常被忽略,尤其是 systemd 管理的服务,SELinux 或 AppArmor 可能拦截)
- 执行
SET GLOBAL slow_query_log = ON后,需用SHOW VARIABLES LIKE 'slow_query_log'和SHOW VARIABLES LIKE 'slow_query_log_file'双重验证
long_query_time 设多少才合理?
没有通用“推荐值”,取决于你的业务响应预期和数据库负载特征。设得太低(如 0.1s)会导致日志爆炸,设得太高(如 5s)则漏掉大量拖慢用户体验的查询。
- 线上 OLTP 系统建议从
1.0开始:覆盖明显慢查询,又不至于淹没日志 - 高并发小事务场景(如电商下单)可收紧到
0.5;报表类从库可放宽至2.0–5.0 -
long_query_time是浮点数,支持小数(如0.3),但注意:MySQL 5.6 及以前只支持秒级整数,升级前先查版本 - 该阈值仅判断「执行时间」,不包含锁等待、网络传输等,真正卡顿的查询可能因锁争用未达阈值却实际阻塞业务
配合 log_queries_not_using_indexes 用不用?
这个开关会让所有未走索引的 SELECT 都记入慢日志,哪怕执行只花了 0.001s。它对索引治理很有价值,但生产环境要谨慎开启。
- 只在诊断阶段临时启用(比如上线新表后快速发现缺失索引),避免长期开启——全表扫描的统计类查询、初始化脚本等会大量刷屏
- 它不记录
INSERT/UPDATE/DELETE的索引使用情况,只针对SELECT - 即使开了,也要结合
EXPLAIN看实际执行计划,因为有些查询看似没走索引,实则是index_merge或覆盖索引优化过的
日志轮转和磁盘空间怎么防崩?
MySQL 自身不提供慢日志轮转(logrotate 也不能直接 kill -USR1,因 MySQL 不响应该信号),靠外部工具或定时脚本管理。
- 不要依赖
FLUSH LOGS频繁切换文件——它会触发所有日志刷新,可能引发短暂性能抖动 - 推荐方案:用
logrotate配合copytruncate(安全但有极小丢失风险),或用mv + mysqladmin flush-logs组合(更可靠,需确保 mv 原子性) - 监控
slow_query_log_file所在分区剩余空间,低于 20% 时告警;单个日志文件超过 500MB 就该介入分析了
long_query_time 的取值必须和你的应用 P95 响应时间对标,而日志本身只是线索入口——真正关键的是后续用 mysqldumpslow 或 pt-query-digest 抓出 Top SQL,再结合 EXPLAIN ANALYZE 看执行细节。漏掉这步,配置再“合理”也只是摆设。










