先确认slow_query_log为on且slow_query_log_file路径可写,再检查long_query_time(建议设为1或0.5)和min_examined_row_limit等影响记录的参数,最后用mysqldumpslow分析日志并结合explain优化。

怎么确认慢查询日志是否真的在记录
MySQL 5.7 默认不开启慢查询日志,即使你改过配置,也可能没生效。先检查两个关键变量:slow_query_log 必须是 ON,slow_query_log_file 指向的路径必须可写且存在(MySQL 进程有权限写入)。常见错误是只改了 my.cnf 但没重启服务,或改了全局变量却没用 SET PERSIST(5.7.8+)或 SET GLOBAL 持久化。
执行以下命令验证:
SHOW VARIABLES LIKE 'slow_query_log';<br>SHOW VARIABLES LIKE 'slow_query_log_file';<br>SHOW VARIABLES LIKE 'long_query_time';
注意:long_query_time 默认是 10 秒,对排查实际业务慢查基本没用,建议临时调低到 1 或 0.5(支持小数),但别设为 0——那样会记录所有查询,包括 SELECT 1 这类,日志体积爆炸。
为什么设置了 long_query_time 却没看到预期的慢查询
MySQL 5.7 对“慢”的判定不仅看执行时间,还受 min_examined_row_limit 影响:默认为 0,但如果设为非零值(比如 1000),只有扫描行数 ≥ 该值的查询才可能被记录,哪怕执行时间超了 long_query_time。另一个关键是 log_queries_not_using_indexes:如果开启,哪怕执行很快,只要没走索引也会进慢日志——这容易误判,建议排查期关闭它,避免噪音。
-
long_query_time是按查询实际执行时间(wall time)判断,不是 CPU 时间 - 事务中多个语句,每个独立判断,不是整个事务算总时长
- 存储过程内的语句会被记录,但函数内联执行可能不单独出现
- 从库上开启慢日志,只会记录从库重放的 SQL,和主库日志无关
如何安全地读取和分析 slow.log 文件
直接 tail -f 看原始日志效率低,且格式难解析。MySQL 自带 mysqldumpslow 工具更实用,比如:
mysqldumpslow -s at -t 10 /var/lib/mysql/slow.log
其中 -s at 表示按平均查询时间排序,-t 10 取前 10 条。注意路径必须和 slow_query_log_file 值一致,且 MySQL 用户(通常是 mysql)需有读权限。别用 root 直接 cat,容易因权限问题看不到内容;也别在生产环境长期用 SET GLOBAL long_query_time = 0.1,高并发下日志写入本身会成为性能瓶颈。
真正要定位根因时,单看慢日志不够。得结合 EXPLAIN 分析对应 SQL 的执行计划,重点看 type(是否 ALL)、key(是否用了预期索引)、rows(预估扫描行数)——这些才是优化依据。
为什么重启后慢日志配置又失效了
因为只执行了 SET GLOBAL slow_query_log = ON,这个操作不会写入配置文件,MySQL 重启就还原。5.7.8+ 支持 SET PERSIST slow_query_log = ON,会自动写入 mysqld-auto.cnf;低于该版本,必须手动编辑 my.cnf 的 [mysqld] 段,加上:
slow_query_log = ON<br>slow_query_log_file = /var/lib/mysql/slow.log<br>long_query_time = 1
然后 service mysql restart。漏掉 slow_query_log = ON 这一行,其他配置全对也白搭。另外,有些云数据库(如阿里云 RDS)禁用该参数,只能通过控制台开关,不能靠 SQL 设置。
最常被忽略的是日志文件磁盘空间和轮转机制:MySQL 不自动切割 slow.log,得靠外部工具(如 logrotate)配合,否则某天发现磁盘爆满,第一反应不是慢查太多,而是日志没清理。











