【Java 开发日记】我们来说一下 MySQL 的慢查询日志
慢查询日志(Slow Query Log)是 MySQL 性能优化的最重要入口之一。
它能帮你快速定位“拖慢整个系统”的 SQL,是排查线上卡顿、CPU/IO 高、连接堆积的第一把钥匙。
今天我们从为什么用 → 怎么开 → 怎么配 → 怎么分析 → 生产注意事项 全流程走一遍(基于 MySQL 8.x / 5.7+,2025–2026 主流实践)。
1. 为什么一定要用慢查询日志?
- 业务代码里看不到执行时间分布
EXPLAIN只能单条分析,生产里成千上万条 SQL 不可能一条条 explain- 慢查询日志自动记录超过阈值的 SQL + 执行信息(耗时、扫描行数、锁时间等)
- 结合
pt-query-digest/mysqldumpslow一键聚合出 Top 慢 SQL
一句话:没有慢查询日志,你就是在盲人摸象调优。
2. 核心参数一览(2025 推荐配置)
| 参数 | 作用 | 默认值 | 生产推荐值(常见场景) | 说明 |
|---|---|---|---|---|
| slow_query_log | 是否开启慢查询日志 | OFF | ON(临时开启 / 间歇采集) | 核心开关 |
| slow_query_log_file | 日志文件路径 | 主机名-slow.log | /var/log/mysql/slow.log 或自定义 | 确保目录 mysql 用户可写 |
| long_query_time | 超过多少秒算慢(单位:秒,可小数) | 10 | 1~3(甚至 0.5~1) | 越小日志越多,建议从 2 开始调 |
| log_queries_not_using_indexes | 未走索引的查询也记录(即使没超时间) | OFF | ON(排查阶段开,生产慎开) | 非常有用,但会让日志暴增 |
| log_output | 日志输出位置 | FILE | FILE 或 TABLE(mysql.slow_log) | FILE 更常见,TABLE 便于查询 |
| min_examined_row_limit | 扫描行数少于此值的不记录 | 0 | 1000 或 5000(过滤小表全扫) | 减少噪音 |
| log_slow_admin_statements | 慢的管理语句(ALTER 等)也记录 | OFF | 根据需要 | 一般不开 |
3. 怎么开启?(三种方式对比)
方式一:临时开启(推荐排查时用,重启失效)
-- 开启慢查询
SET GLOBAL slow_query_log = 1;
-- 设置阈值(建议从 2 秒开始,逐步降低)
SET GLOBAL long_query_time = 2;
-- 强烈建议:记录未走索引的查询(排查神器)
SET GLOBAL log_queries_not_using_indexes = 1;
-- 查看当前配置(立即生效)
SHOW VARIABLES LIKE '%slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
方式二:永久开启(修改配置文件,推荐生产间歇采集)
在 /etc/my.cnf 或 /etc/mysql/my.cnf(或容器里的对应路径)中添加:
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1 # 排查期开启,平时关闭
min_examined_row_limit = 1000
log_output = FILE
# log_slow_admin_statements = 1 # 可选
然后重启 MySQL(或容器重启)。
生产建议:不要一直开,尤其是 log_queries_not_using_indexes=1 会导致日志文件快速膨胀。
推荐做法:平时关闭 → 问题出现时开启 1-2 小时采集 → 分析完关闭。
方式三:输出到表(方便 SQL 查询)
SET GLOBAL log_output = 'TABLE';
慢 SQL 会写入 mysql.slow_log 表,可直接查询:
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 50;
4. 慢查询日志长什么样?(典型格式)
# Time: 2026-01-26T18:45:12.345678Z
# User@Host: app_user[app_user] @ 192.168.1.50 []
# Query_time: 4.567 Lock_time: 0.000123 Rows_sent: 1 Rows_examined: 8500000
# Rows_affected: 0
SET timestamp=1706291112;
SELECT * FROM orders
WHERE status = 'pending'
AND created_at > '2025-12-01'
ORDER BY id DESC LIMIT 10;
关键字段:
- Query_time:实际执行时间(最重要)
- Lock_time:等待行锁 / 表锁 时间
- Rows_examined:扫描了多少行(越大越可疑)
- Rows_sent:返回多少行
5. 怎么分析慢查询日志?(生产常用工具)
工具 1:官方 mysqldumpslow(最轻量)
# 汇总前 10 条最慢的(自动按总耗时排序)
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
# 按扫描行数排序
mysqldumpslow -s r -t 10 /var/log/mysql/slow.log
# 只看某个用户的
mysqldumpslow -s t -t 10 -u app_user /var/log/mysql/slow.log
输出示例:
Count: 128 Time=5.2s (665s) Lock=0.00s (0s) Rows=1 (128), app_user[app_user]@192.168.1.%
SELECT * FROM orders WHERE status = ? AND created_at > ?
工具 2:pt-query-digest(Percona 工具,推荐!)
pt-query-digest /var/log/mysql/slow.log > digest.txt
它会给你:
- 按照执行次数、总耗时、平均耗时、95% 耗时 等多种维度排名
- 自动合并参数化后的相同 SQL
- 显示执行计划摘要
生产必备:几乎所有 DBA 都用这个。
6. 生产最佳实践 & 注意事项(2025–2026 版)
- 阈值设置:线上从 1~3 秒开始,逐步调到业务能接受的 95 分位线(用监控看)。
- 不要常开:开启会增加少量 IO 和 CPU 开销,尤其是
log_queries_not_using_indexes=1。 - 日志轮转:用 logrotate 每天/每周轮转,避免单文件过大。
/var/log/mysql/slow.log {
daily
rotate 7
compress
missingok
create 640 mysql mysql
}
- 结合监控:Prometheus + mysqld_exporter 监控
slow_queries指标,超过阈值告警。 - 下一步动作:找到 Top 慢 SQL 后,立刻
EXPLAIN ANALYZE(MySQL 8.0+)或EXPLAIN FORMAT=JSON。 - 常见优化方向:
- 加/改索引(联合索引、覆盖索引)
- 避免
SELECT *、函数(列)、OR、!=、LIKE '%xx%' - 大表分页用延迟关联
- 拆分复杂 JOIN
小结 & 下一步想聊什么?
慢查询日志是 “发现问题” 的神器,接下来才是真正的优化战场(索引、SQL 重写、分库分表、读写分离…)。
你现在最想深入哪个部分?
A. pt-query-digest 的详细用法 + 真实案例解析
B. 结合 EXPLAIN ANALYZE 如何读懂执行计划
C. 线上如何安全“限时开启”慢查询(不重启、不影响业务)
D. 慢 SQL 优化实战:从日志到加索引 / 重写 SQL 的完整流程
E. Percona Toolkit 全家桶简介(pt-query-digest / pt-index-usage 等)
告诉我字母,继续写!