mysql慢查询日志如何分析_mysql日志优化方法

3次阅读

需执行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影响性能并同步更新监控告警。

mysql慢查询日志如何分析_mysql日志优化方法

怎么确认慢查询日志是否真的在记录

很多情况下你以为开启了慢查询,其实 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 = ONlog_output = FILE
  • 检查 slow_query_log_file 路径是否有写权限,MySQL 进程能否触达

用 pt-query-digest 快速定位瓶颈 SQL

原生日志文本杂乱,直接 grepawk 效率低、易漏关键信息。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,记得看 countExec time 的乘积列(即总耗时占比)。

哪些 SQL 特征必须人工介入优化

pt-query-digest 能标出问题,但不会自动改 SQL 或建索引。以下特征出现时,必须立刻人工跟进:

  • Rows_examined 远大于 Rows_sent(比如扫 10 万行只返回 1 行),大概率缺索引或索引失效
  • 语句含 Using filesortUsing temporary(在 EXPLAIN 结果里),说明排序/分组没走索引
  • 出现 select * + LIMIT 大偏移(如 LIMIT 10000,20),分页深度越大越慢
  • WHERE 条件用了函数(如 WHERE date(create_time) = '2024-01-01'),导致索引无法下推

验证索引是否生效,别只看 EXPLAINtype 字段,重点看 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 分钟就通知。

text=ZqhQzanResources