我们来说一下 MySQL 的慢查询日志

一、什么是慢查询日志

慢查询日志(Slow Query Log) 是 MySQL 内置的一种日志功能,用于记录执行时间超过指定阈值的 SQL 语句。这是优化数据库性能的重要工具。

二、核心作用

  1. 性能诊断:找出执行效率低的 SQL 语句
  2. 瓶颈定位:分析查询为什么慢(全表扫描、索引缺失等)
  3. 优化依据:为 SQL 优化和索引调整提供数据支持

三、配置参数详解

ini 复制代码
-- 查看所有慢查询相关参数
SHOW VARIABLES LIKE '%slow%';
SHOW VARIABLES LIKE '%long_query_time%';

-- 主要配置参数:
-- slow_query_log = OFF/ON          # 是否开启慢查询日志
-- slow_query_log_file = /path/name # 日志文件路径
-- long_query_time = 10             # 阈值(秒),默认10秒
-- min_examined_row_limit = 0       # 最少检查行数阈值
-- log_queries_not_using_indexes = OFF # 是否记录未使用索引的查询
-- log_slow_admin_statements = OFF  # 是否记录管理语句
-- log_output = FILE/TABLE/NONE     # 输出方式

四、开启和配置

1. 临时开启(重启失效)

ini 复制代码
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 2;      -- 设为2秒
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL log_queries_not_using_indexes = 'ON';

2. 永久开启(修改配置文件)

ini 复制代码
# my.cnf 或 my.ini
[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 1
log_output = FILE

五、慢查询日志格式分析

典型日志条目:

sql 复制代码
# Time: 2024-01-01T10:00:00.123456Z
# User@Host: root[root] @ localhost []  Id:     5
# Query_time: 5.123456  Lock_time: 0.001000  Rows_sent: 10  Rows_examined: 1000000
SET timestamp=1672560000;
SELECT * FROM users WHERE last_name LIKE '%smith%' ORDER BY create_time DESC;

关键字段解释:

  • Query_time:查询执行总时间
  • Lock_time:锁定时间
  • Rows_sent:返回给客户端的行数
  • Rows_examined:扫描的行数
  • Rows_affected:影响的行数(UPDATE/DELETE/INSERT)

六、慢查询分析工具

1. mysqldumpslow(MySQL 自带)

bash 复制代码
# 按查询时间排序
mysqldumpslow -s t /var/log/mysql/slow.log

# 按锁时间排序
mysqldumpslow -s l /var/log/mysql/slow.log

# 按执行次数排序
mysqldumpslow -s c /var/log/mysql/slow.log

# 显示前10条最慢的查询
mysqldumpslow -t 10 /var/log/mysql/slow.log

# 分析特定用户的慢查询
mysqldumpslow -a -g "root" /var/log/mysql/slow.log

2. pt-query-digest(Percona Toolkit)

bash 复制代码
# 分析慢查询日志
pt-query-digest /var/log/mysql/slow.log

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

# 输出到文件
pt-query-digest /var/log/mysql/slow.log > slow_report.txt

3. mysqlslow(第三方工具)

c 复制代码
mysqlslow /var/log/mysql/slow.log

七、慢查询日志表模式

启用表模式存储:

ini 复制代码
SET GLOBAL log_output = 'TABLE';
SET GLOBAL slow_query_log = 'ON';

-- 查询慢查询日志
SELECT * FROM mysql.slow_log;

表结构:

sql 复制代码
SHOW CREATE TABLE mysql.slow_log;

-- 主要字段:
-- start_time: 查询开始时间
-- query_time: 查询耗时
-- lock_time: 锁定时间
-- rows_sent: 返回行数
-- rows_examined: 检查行数
-- sql_text: SQL语句
-- user_host: 用户和主机信息

八、最佳实践和优化建议

1. 阈值设置建议

sql 复制代码
-- 生产环境建议
SET GLOBAL long_query_time = 2;    -- 2秒阈值

-- 开发/测试环境可以更严格
SET GLOBAL long_query_time = 0.5;  -- 500毫秒

-- 微秒级精度(MySQL 5.7+)
SET GLOBAL long_query_time = 0.1;  -- 100毫秒

2. 日志轮转配置

lua 复制代码
# 使用 logrotate
/var/log/mysql/slow.log {
    daily
    rotate 30
    missingok
    compress
    delaycompress
    notifempty
    create 640 mysql mysql
    postrotate
        mysqladmin flush-logs
    endscript
}

3. 定期分析计划

bash 复制代码
# 每日分析脚本示例
#!/bin/bash
DATE=$(date +%Y%m%d)
pt-query-digest /var/log/mysql/slow.log > /var/log/mysql/slow_report_${DATE}.txt
# 清空日志文件(先备份)
cp /var/log/mysql/slow.log /var/log/mysql/slow.log.${DATE}
echo "" > /var/log/mysql/slow.log

九、性能监控和告警

1. 监控慢查询数量

sql 复制代码
-- 监控每分钟的慢查询数量
SHOW GLOBAL STATUS LIKE 'Slow_queries';

-- 查看当前慢查询
SHOW PROCESSLIST;

2. 慢查询告警脚本

bash 复制代码
#!/bin/bash
SLOW_COUNT=$(mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries'" | grep Slow_queries | awk '{print $2}')
THRESHOLD=100

if [ $SLOW_COUNT -gt $THRESHOLD ]; then
    echo "警告:慢查询数量异常!当前数量: $SLOW_COUNT" | mail -s "MySQL慢查询告警" admin@example.com
fi

十、注意事项

  1. 性能影响:开启慢查询日志会有约1-3%的性能开销
  2. 磁盘空间:定期清理,避免日志文件过大
  3. 敏感信息:日志可能包含敏感数据,需妥善保管
  4. 生产环境:建议设置合理的阈值,避免记录过多无关查询
  5. 版本差异:MySQL 5.7+ 支持微秒级精度,之前版本只到秒

面试回答

简单来说,慢查询日志就像是 MySQL 的一个'病历本'。它会自动记录下来所有执行时间超过某个阈值的 SQL 语句。这样我们开发或者 DBA 就能知道,哪些查询是'慢'的、有问题的,然后去针对性地优化。

在实际工作中,我主要会关注和操作这么几个方面:

第一,怎么开启和设置。

慢查询日志默认是关闭的,因为它会有一点磁盘 I/O 的开销。我们需要在 MySQL 配置文件(比如 my.cnf)里设置几个核心参数:

  1. slow_query_log = ON:打开开关。
  2. slow_query_log_file:指定这个'病历本'文件存哪里。
  3. long_query_time:这是最重要的一个阈值,单位是秒。比如设为 1,就意味着执行超过 1 秒的 SQL 才会被记录。这个值可以根据系统性能要求来调整。
  4. log_queries_not_using_indexes:这个我也经常会打开。它会记录那些没有使用索引的查询,即使它执行得很快。这能帮我们发现潜在的设计问题。

第二,怎么看这个日志。

日志是文本格式,可以直接看,但不太直观。我常用的方法是:

  1. 用 MySQL 自带的 mysqldumpslow 工具。这个命令行工具可以对日志进行汇总、排序,比如我们可以用 mysqldumpslow -t 10 -s t 来找出耗时最长的前 10 条 SQL,一目了然。
  2. 对于更复杂的分析,我会用 Percona 公司开的 ****pt-query-digest 工具。它功能更强大,能给出非常详细的报告,比如每个 SQL 的响应时间占比、执行次数、锁时间等,能帮我快速定位最需要优化的'瓶颈' SQL。

第三,也是最重要的,找到慢 SQL 后怎么办。

光找到没用,关键是要优化。我一般的排查思路是:

  1. 拿到这条慢 SQL,先 explain 命令去看它的执行计划。这是标准动作。我会重点看:
    • 有没有用到索引(key 字段)。
    • 扫描了多少行(rows 字段)。
    • 查询类型是不是全表扫描(type 字段,如果是 ALL 就不好了)。
  1. 根据 ****explain ****的结果,常见的优化手段就是:
    • 加索引 :这是最有效的办法之一,检查 WHEREORDER BYJOIN 的字段。
    • 优化 SQL 本身 :比如避免 SELECT *,检查是否有复杂的子查询能不能改写为 JOIN,或者分页查询在大偏移量时有没有优化空间。
    • 看看是不是数据库参数问题,比如缓冲池大小是不是不合理。

最后,我的一点实践经验是 :慢查询日志在测试环境和生产环境都很有用。在项目上线前,我们会开启它来提前发现一些性能问题。在生产环境,我们会长期开启,但会设置一个合理的 long_query_time(比如从 2 秒开始),并定期归档和分析日志,把它作为性能监控和容量规划的一个重要依据。

相关推荐
南囝coding2 小时前
《独立开发者精选工具》第 025 期
前端·后端
独自破碎E2 小时前
Java是怎么实现跨平台的?
java·开发语言
To Be Clean Coder2 小时前
【Spring源码】从源码倒看Spring用法(二)
java·后端·spring
xdpcxq10293 小时前
风控场景下超高并发频次计算服务
java·服务器·网络
想用offer打牌3 小时前
你真的懂Thread.currentThread().interrupt()吗?
java·后端·架构
橘色的狸花猫3 小时前
简历与岗位要求相似度分析系统
java·nlp
独自破碎E3 小时前
Leetcode1438绝对值不超过限制的最长连续子数组
java·开发语言·算法
用户91743965393 小时前
Elasticsearch Percolate Query使用优化案例-从2000到500ms
java·大数据·elasticsearch
程序员NEO3 小时前
LangChain4j 工具调用实战
后端