首页 > 数据库 >MySQL慢查询日志的实现原理与配置

MySQL慢查询日志的实现原理与配置

来源:互联网 2026-07-04 08:52:19

MySQL慢查询日志:从入门到线上排障,这一篇就够了 要说数据库调优里最常用的工具,慢查询日志绝对是排得上号的。无论你是刚入门的开发,还是需要在生产环境扛雷的运维,都绕不开它。今天这篇文章,咱们就把慢查询日志掰开揉碎了讲清楚——它是什么、怎么配、上线怎么用、遇到问题怎么看,以及那些面试官最爱挖坑的细

MySQL慢查询日志:从入门到线上排障,这一篇就够了

要说数据库调优里最常用的工具,慢查询日志绝对是排得上号的。无论你是刚入门的开发,还是需要在生产环境扛雷的运维,都绕不开它。今天这篇文章,咱们就把慢查询日志掰开揉碎了讲清楚——它是什么、怎么配、上线怎么用、遇到问题怎么看,以及那些面试官最爱挖坑的细节到底是怎么回事。

我先抛个核心判断:慢查询日志是 MySQL 的 SQL 性能记录仪,专门自动记录那些执行慢、性能差的 SQL。线上项目 CPU 飙升了?接口超时了?页面加载变慢了?别慌,第一件事就是打开慢日志,找到问题 SQL。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

MySQL慢查询日志的实现原理与配置

注意:它是被动记录的——它不会阻止 SQL 的执行,也不会影响业务的正常运行。慢日志只是“记录”,不是“拦截”。

对于运维和开发来说,这个工具的定位很简单:问题排查的第一把钥匙。线上出了故障,没有慢日志,就等于没有线索。

一、慢日志的记录机制:到底什么时候会记录?

别看网上各种说法满天飞,其实默认的记录条件只有一个:执行时间超过 long_query_time 这个阈值。

那个 log_queries_not_using_indexes 参数,是额外的附加开关。把它打开后,即使 SQL 执行时间没超过阈值,但只要没用索引(走全表扫描),也会被记录下来。

这两个条件是什么关系?简单说,“或”的关系——满足任何一个,就会被记录:

条件是否记录
执行时间 > 阈值 记录
执行时间 ≤ 阈值,但无索引 + 开启了无索引记录 记录
执行时间 ≤ 阈值,且无索引记录未开启 不记录

这里有个关键认知必须建立起来:全表扫描 ≠ 慢查询。一张 4000 行的小表,全表扫描可能只要 0.01 秒,远低于阈值,自然不会触发慢日志(除非你专门开启无索引记录)。

二、最大的坑:线上慢日志到底要不要关?

这是一道经典的面试题,也是很多新手容易漏掉的地方。直接说结论:线上慢日志总开关必须永久开启,绝对不能关闭!

有些同学担心开启慢日志会占用性能。其实完全多虑了:慢日志的写入是追加式 IO,对整体性能影响极小(通常 < 1%)。真正影响性能的,是那些问题 SQL 本身,而不是记录问题 SQL 的日志。

关闭慢日志的后果是什么?线上出故障时没有日志可查,你连问题 SQL 都找不到,更别提定位根源了。所以,线上正确的做法是:开关不关,只调优参数——调高耗时阈值、关闭无索引 SQL 记录,防止日志爆炸。

三、核心配置参数:零基础也能懂

要查看所有慢日志参数,直接执行 SHOW VARIABLES LIKE 'slow_query%'; 就行。下面这三项是必配的:

三大必配参数

参数含义推荐值
slow_query_log慢日志总开关线上永久 ON
long_query_time慢查询判定阈值(单位:秒)开发:0.1秒 / 线上:1~2秒
log_queries_not_using_indexes是否记录无索引全表扫描SQL开发:ON / 线上:OFF

阈值的设定也有讲究:

  • 开发环境设 0.1 秒,严格排查,提前揪隐患。极端场景甚至可以设 0 秒,记录所有 SQL。
  • 线上环境设 1~2 秒,只记录真正卡顿的 SQL。

进阶参数:线上必配

参数含义推荐值
slow_query_log_file日志文件存储路径确保有磁盘空间,路径可访问
min_examined_row_limit最少扫描行数阈值100~1000,过滤小表噪音
log_output日志输出方式FILE(默认)/ TABLE

这个 min_examined_row_limit 配合无索引记录使用效果特别好:即使开了 log_queries_not_using_indexes,扫描行数低于这个值的 SQL 也不会被记录,可以大幅减少小表产生的无效日志。

动态修改参数:不停机生效

线上不想重启 MySQL 时,直接用动态命令即可:

-- 临时开启慢日志(重启后失效)
SET GLOBAL slow_query_log = ON;

-- 临时调整阈值
SET GLOBAL long_query_time = 2;

不过要注意:long_query_time 修改后,需要新连接才生效,已有连接仍然使用旧值。要永久生效,还得同时改 my.cnf 配置文件。

四、实操中的疑难问题全解

问题1:同样是全表扫描,为什么有的进慢日志,有的不进?

核心规则再强调一遍:慢日志默认只看耗时,不看是否全表扫描

你的 4000 行小表,全表扫描只需 0.03 秒,低于阈值,所以不记录;等到数据量超过 10 万行,全表扫描耗时暴涨超过阈值,立刻被记录。

如果开了 log_queries_not_using_indexes,无索引 SQL 即使不超时也会被记录——但小表可以用 min_examined_row_limit 过滤掉。

问题2:LIKE '王%' 前缀模糊查询,到底进不进慢日志?

答案完全取决于列上是否有索引,不存在什么“隐性优化规则”。直接看表:

场景执行方式是否被记录
列有索引 + LIKE '王%'索引范围扫描(不是全表扫描)不触发无索引记录;超时才记录
列无索引 + LIKE '王%'全表扫描开了无索引记录就记录,超时也记录
LIKE '%王' 左模糊无论有无索引,都无法走索引范围扫描全表扫描,开了无索引记录就记录

记住这个对比:LIKE '王%' 在有索引时能走范围扫描,不是全表扫描;而 LIKE '%王' 这种左模糊,无法利用 B+ 树索引的有序性,一定全表扫描。

问题3:为什么 xuesheng_yizizhu > 100 全表扫描会被记录?

这条 SQL 扫描全表 4400 行、返回 4300+ 行,被记录有两个可能原因:

  1. 如果开了 log_queries_not_using_indexes:没有索引,直接满足无索引记录条件,跟扫描行数多少无关。
  2. 如果没开无索引记录:那就是执行耗时超过了 long_query_time 阈值。

判断:扫描行数远大于返回行数,这是索引缺失的信号。但注意,这不是慢日志记录的原因,而是需要优化的原因

五、慢日志核心字段:小白也能秒懂

拿到慢日志,不用看杂乱的内容,只看这 4 个字段就能定位问题:

字段含义问题判断
Query_timeSQL总执行耗时核心依据,数值大 = SQL本身慢
Lock_time锁等待耗时数值高是锁竞争问题
Rows_examined实际扫描行数风险核心,数值大 = 可能在全表扫描
Rows_sent最终返回的行数用于和扫描行数对比

记住一个万能判断口诀:Rows_examined Rows_sent(扫描行数远大于返回行数)= 索引缺失或索引失效,必须优化。

几个典型场景速判:

现象诊断
Query_time大,Lock_time小SQL本身慢,需要优化索引或改写SQL
Query_time大,Lock_time大锁竞争严重,需要优化事务/锁粒度
Rows_examined >> Rows_sent索引缺失或失效,补索引或改写SQL
Rows_examined ≈ Rows_sent扫描行都是需要的,考虑业务需求是否合理

六、三种环境查看慢日志的方法

本地 PHPStudy 环境

直接找到 slow.log 文件,用编辑器打开,直观查看原始日志,适合本地调试。

线上 Linux 服务器(企业常用)

线上环境有两种主流分析工具:

方法一:mysqldumpslow(MySQL 自带,简单快捷)

它能自动合并重复 SQL、排序统计,解决日志杂乱的问题。常用命令:

# 查耗时最长Top10
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# 查执行次数最多Top10
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log

# 查平均耗时最长Top10
mysqldumpslow -s at -t 10 /var/log/mysql/slow.log

注意:mysqldumpslow 只能分析 FILE 格式的日志。如果 log_output=TABLE,就需要用 SELECT * FROM mysql.slow_log 来查询。

方法二:pt-query-digest(Percona Toolkit,企业主流)

这个工具比 mysqldumpslow 强大得多,是实际运维中最常用的:

# 分析慢日志,输出完整报告
pt-query-digest /var/log/mysql/slow.log

# 只分析最近1小时的慢查询
pt-query-digest --since '1h' /var/log/mysql/slow.log

# 将结果保存到数据库
pt-query-digest --review h=host,D=db,t=review /var/log/mysql/slow.log

阿里云/火山RDS云数据库

没有服务器权限,直接在控制台操作:实例详情 → 日志管理 → 慢查询日志,支持筛选、导出、一键分析。

七、日志自动切割方案:线上必配

线上慢日志会持续增长,如果不配置自动切割,单文件过大可能会占满磁盘。

方案一:logrotate(Linux 系统自带)

创建配置文件 /etc/logrotate.d/mysql-slow

/var/log/mysql/slow.log {
    daily
    rotate 30
    missingok
    compress
    delaycompress
    notifempty
    create 640 mysql mysql
    postrotate
        mysql -e "SELECT 1" >/dev/null 2>&1 || true
    endscript
}

方案二:手动 mv + flush(简单直接)

# 1. 重命名当前日志
mv /var/log/mysql/slow.log /var/log/mysql/slow.log.bak

# 2. 刷新MySQL日志句柄(MySQL自动创建新文件)
mysql -e "FLUSH SLOW LOGS;"

八、开发 + 线上落地规范

开发环境规范

  • 开启慢日志 + 低耗时阈值(0.1秒)+ 记录无索引 SQL
  • 上线前清零所有全表扫描、慢查询 SQL,提前规避线上风险
  • 极端排查场景可设 long_query_time=0,记录所有 SQL

线上生产环境规范

  1. 慢日志总开关永久开启,禁止关闭
  2. 关闭无索引 SQL 记录,防止海量日志占满磁盘
  3. 配置 min_examined_row_limit,即使临时开启无索引记录也能过滤小表噪音
  4. 配置日志自动切割,避免单文件过大
  5. 避免无条件全表查询,避免左模糊/全模糊查询 %xxx,业务需要时用 ES/搜索引擎替代
  6. 设置合理的 long_query_time(1~2秒),太低日志爆炸,太高漏掉问题

九、企业标准 SQL 优化流程

接下来就是一套标准打法了:慢日志抓取问题 SQL → EXPLAIN 分析执行计划 → 补索引/改写 SQL → 复测性能

这是业界通用的数据库性能排查流程,适用于绝大多数卡顿问题的定位和解决:

发现问题 → 慢日志抓SQL → EXPLAIN分析 → 优化方案 → 上线复测
   ↑                                                    |
   └────────────── 未解决则循环 ←───────────────────────┘

十、面试速记卡

#核心要点一句话记忆
1慢日志记录条件耗时超阈值 或 无索引(需开启),两者是"或"关系
2线上核心规范慢日志永久开启,关闭无索引记录,调高耗时阈值
3全表扫描 ≠ 慢查询小表全表扫描可能很快,不会触发耗时记录
4模糊查询索引问题LIKE '王%' 有索引走范围扫描,LIKE '%王' 一定全表扫描
5问题判断核心扫描行数远大于返回行数 = 需要优化索引
6优化固定流程抓慢SQL → EXPLAIN分析 → 优化SQL/索引 → 复测
7动态修改SET GLOBAL 可不停机修改,但 long_query_time 需新连接才生效

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。