需执行SHOW VARIABLES检查slow_query_log是否为ON、long_query_time是否合理(建议设为1或0.5)、log_output是否为FILE,并确认slow_query_log_file路径权限;再用pt-query-digest分析日志,重点关注Rows_examined/Rows_sent比值、Using filesort/temporary、大偏移分页及函数索引失效等问题,结合EXPLAIN验证索引使用情况,同时避免日志IO影响性能并同步更新监控告警。

怎么确认慢查询日志是否真的在记录
很多情况下你以为开启了慢查询,其实 slow_query_log 是 OFF 状态,或者 long_query_time 被设得太高(比如 10 秒),导致日常耗时 300ms 的查询根本不会被捕获。
执行这条命令看真实状态:
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
SHOW VARIABLES LIKE 'log_output';
log_output 值要是 FILE 才会写入文件;如果是 TABLE,就得查 mysql.slow_log 表——但默认该表是 CSV 引擎,不支持索引,查起来反而慢,不推荐生产环境用。
- 线上建议设
long_query_time = 1(秒),高并发场景可压到0.5 - 确保
slow_query_log = ON且log_output = FILE - 检查
slow_query_log_file路径是否有写权限,MySQL 进程能否触达
用 pt-query-digest 快速定位瓶颈 SQL
原生日志文本杂乱,直接 grep 或 awk 效率低、易漏关键信息。Percona Toolkit 的 pt-query-digest 是事实标准工具,它能聚合、排序、统计,并标出锁等待、全表扫描、临时表等风险点。
基本用法:
pt-query-digest /var/lib/mysql/slow.log --limit 10
常用关键参数:
-
--filter:过滤掉特定用户或库,比如'$event->{db} =~ m/^test/' -
--since和--until:按时间范围切片分析 -
--review+--review-history:把结果存进数据库做趋势对比 - 加
--no-report可跳过汇总报告,只导出可疑语句供人工复核
注意:pt-query-digest 默认按响应时间排序,但真正拖垮系统的往往不是“最慢那条”,而是“执行频次最高+平均耗时中等”的 SQL,记得看 Count 和 Exec time 的乘积列(即总耗时占比)。
哪些 SQL 特征必须人工介入优化
pt-query-digest 能标出问题,但不会自动改 SQL 或建索引。以下特征出现时,必须立刻人工跟进:
-
Rows_examined远大于Rows_sent(比如扫 10 万行只返回 1 行),大概率缺索引或索引失效 - 语句含
Using filesort或Using temporary(在EXPLAIN结果里),说明排序/分组没走索引 - 出现
SELECT *+LIMIT大偏移(如LIMIT 10000,20),分页深度越大越慢 - WHERE 条件用了函数(如
WHERE DATE(create_time) = '2024-01-01'),导致索引无法下推
验证索引是否生效,别只看 EXPLAIN 的 type 字段,重点看 key(实际用了哪个索引)、rows(预估扫描行数)、Extra(有没有 Using index 覆盖索引)。
日志本身也会成为性能负担
开启慢查询日志不是“一劳永逸”,尤其在高 QPS 场景下,频繁写磁盘可能拖慢 MySQL 吞吐。几个容易被忽略的细节:
- 日志文件不要放在系统盘或和
datadir同一物理磁盘,避免 IO 冲突 - 定期轮转(用
mysqladmin flush-logs或 logrotate),否则单个文件过大,pt-query-digest解析会卡住 - 如果只是临时排查,用
SET GLOBAL slow_query_log = ON动态开启,完事后关掉,比永久配置更安全 - MySQL 8.0+ 支持
log_slow_extra,能记录更多上下文(如客户端 IP、SQL 模板 hash),但会加重日志体积,按需开启
最常被跳过的一步:分析完慢日志后,没同步更新监控项。比如发现某类 UPDATE ... WHERE status=0 很慢,就该在 Prometheus + Grafana 里加一条告警:当该语句平均耗时 >500ms 持续 3 分钟就通知。










