【Java 开发日记】我们来说一下 MySQL 的慢查询日志

【Java 开发日记】MySQL 慢查询日志(Slow Query Log)完全梳理

慢查询日志是 MySQL 性能优化的最重要入口之一,几乎所有线上问题、SQL 优化、索引缺失、超时排查,都会第一时间打开慢查询日志来看。

下面从零到实战,一次把慢查询日志相关的核心知识点全部讲清楚。

1. 什么是慢查询日志?

简单说:
MySQL 把执行时间超过某个阈值的 SQL 记录到日志文件里,这个阈值叫 long_query_time

记录的内容通常包括:

  • 执行时间
  • 锁等待时间
  • 返回的行数
  • 扫描的行数
  • 执行的完整 SQL
  • 执行用户、IP、数据库名
  • 是否使用了索引(using index / using filesort / using temporary)

2. 核心参数(必须记住的几个)

参数名作用默认值推荐线上值修改方式
slow_query_log是否开启慢查询日志OFFON全局动态
slow_query_log_file慢查询日志文件路径主机名-slow.log自定义路径全局动态
long_query_time超过多少秒算慢查询10秒0.5~2秒(视业务)全局动态
log_queries_not_using_indexes是否记录未使用索引的查询(即使没超阈值)OFF建议开(排查利器)全局动态
min_examined_row_limit扫描行数少于此值的不记录0一般不动全局动态
log_output日志输出方式(FILE / TABLE)FILEFILE 或 TABLE全局动态

推荐线上配置组合(最常用):

SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;                -- 1秒以上算慢
SET GLOBAL log_queries_not_using_indexes = ON; -- 没走索引的都记
SET GLOBAL slow_query_log_file = '/data/mysql/slow/slow.log';

3. 怎么查看慢查询日志?

方式一:直接看文件(最原始)

tail -f /data/mysql/slow/slow.log

典型日志样子:

# Time: 2025-02-07T12:34:56.123456Z
# User@Host: app_user[app_user] @  [192.168.1.100]  Id: 12345
# Query_time: 2.345  Lock_time: 0.000123 Rows_sent: 100  Rows_examined: 1000000
# Rows_affected: 0  Bytes_received: 0
SET timestamp=1738922096;
SELECT * FROM orders WHERE user_id = 123456 ORDER BY create_time DESC LIMIT 10;

关键字段解读

  • Query_time:执行总耗时
  • Lock_time:等待锁的时间
  • Rows_examined:扫描了多少行(越大越危险)
  • Rows_sent:返回给客户端多少行

方式二:写入 mysql.slow_log 表(推荐)

SET GLOBAL log_output = 'TABLE';

然后就能用 SQL 查了:

SELECT 
    sql_text,
    query_time,
    lock_time,
    rows_examined,
    rows_sent,
    user_host,
    db,
    last_seen
FROM mysql.slow_log
ORDER BY start_time DESC
LIMIT 100;

4. 生产环境中如何高效分析慢查询?

步骤推荐(最常用流程):

  1. 打开慢查询 + 设置合理阈值(1s 或 0.5s)
  2. 运行一段时间后,使用 mysqldumpslow 工具汇总分析(最经典)
# 汇总显示前 20 条最慢的 SQL(按执行次数、耗时排序)
mysqldumpslow -s t -t 20 /data/mysql/slow/slow.log
mysqldumpslow -s c -t 20 /data/mysql/slow/slow.log   # 按执行次数排序
  1. pt-query-digest(Percona Toolkit)更强大分析(强烈推荐)
pt-query-digest /data/mysql/slow/slow.log > digest.txt

它会给你:

  • 总耗时占比
  • 执行次数
  • 平均/最大/最小耗时
  • 95% 响应时间
  • 指纹化的 SQL(自动参数化)
  1. 快速定位 SQL 问题
  • Rows_examined 很大 → 全表扫描、缺少索引
  • Lock_time 很高 → 行锁、表锁、事务长时间未提交
  • Using filesort / Using temporary → 排序或临时表开销大
  • Query_time 远大于 Lock_time → 可能是 IO 慢、数据量大

5. 常见误区 & 注意事项

  • long_query_time = 0 会记录所有查询(慎用,日志会爆炸)
  • 慢查询日志默认不记录 SELECT SLEEP(10) 这种主动慢查询
  • log_queries_not_using_indexes = ON 非常有用,但会增加少量开销
  • 慢查询日志是异步写的,日志里时间可能比实际执行晚一点
  • 高并发下日志文件可能非常大,建议设置 expire_logs_days 或定期清理
  • 5.7 和 8.0 之后,慢查询日志对复制线程的 SQL 也可以记录(log_slow_replica_statements)

6. 终极建议(Java 开发视角)

  • 开发阶段:本地 / 测试环境把 long_query_time 设成 0.1~0.5 秒,养成看慢查询的习惯
  • 上线前:用 pt-query-digest 过一遍主要接口的 SQL
  • 线上:每天定时分析慢查询(可以结合 ELK、Prometheus + Grafana 做监控)
  • 最常见的优化方向(优先级):
  1. 加索引(最有效)
  2. 避免 select *
  3. 优化 order by / group by
  4. 拆分大事务
  5. 减少扫描行数

一句话总结:

慢查询日志不是用来“看日志”的,而是用来“找到最该优化的 SQL”的。

有想深入的点吗?
比如:

  • 怎么设置慢查询告警
  • pt-query-digest 详细用法
  • 8.0 慢查询日志的新特性
  • 结合 MySQL Workbench / Navicat 看慢查询

欢迎继续聊~

文章已创建 4455

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部