一、什么是慢查询日志
慢查询日志(Slow Query Log) 是 MySQL 内置的一种日志功能,用于记录执行时间超过指定阈值的 SQL 语句。这是优化数据库性能的重要工具。
二、核心作用
- 性能诊断 :找出执行效率低的 SQL 语句
- 瓶颈定位 :分析查询为什么慢(全表扫描、索引缺失等)
- 优化依据 :为 SQL 优化和索引调整提供数据支持
三、配置参数详解
--SHOW VARIABLES LIKE '%slow%'; SHOW VARIABLES LIKE '%long_query_time%'; #后端 #Java #每天一个知识点---- 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. 临时开启(重启失效)
SET GLOBAL slow_query_log = 'ON';SET GLOBAL long_query_time = 2; --SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log'; SET GLOBAL log_queries_not_using_indexes = 'ON';2. 永久开启(修改配置文件)
# 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五、慢查询日志格式分析
典型日志条目:
# 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: 1000000SET 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 自带)
# 按查询时间排序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.log2. pt-query-digest (Percona Toolkit)
# 分析慢查询日志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.txt3. mysqlslow (第三方工具)
mysqlslow /var/log/mysql/slow.log七、慢查询日志表模式
启用表模式存储:
SET GLOBAL log_output = 'TABLE';SET GLOBAL slow_query_log = 'ON';--SELECT * FROM mysql.slow_log;表结构:
SHOW CREATE TABLE mysql.slow_log;---------------- user_host: 用户和主机信息八、最佳实践和优化建议
1. 阈值设置建议
--SET GLOBAL long_query_time = 2; -- 2秒阈值--SET GLOBAL long_query_time = 0.5; -- 500毫秒--SET GLOBAL long_query_time = 0.1; -- 100毫秒2. 日志轮转配置
# 使用 logrotate/var/log/mysql/slow.log { daily rotate 30 missingok compress delaycompress notifempty create 640 mysql mysql postrotate mysqladmin flush-logs endscript }3. 定期分析计划
# 每日分析脚本示例# !/bin/bashDATE=$(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. 监控慢查询数量
--SHOW GLOBAL STATUS LIKE 'Slow_queries';--SHOW PROCESSLIST;2. 慢查询告警脚本
#!/bin/bashSLOW_COUNT=$(mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries'" | grep Slow_queries | awk '{print $2}')THRESHOLD=100if [ $SLOW_COUNT -gt $THRESHOLD ]; then echo "警告:慢查询数量异常!当前数量: $SLOW_COUNT" | mail -s "MySQL 慢查询告警" admin@example.com fi十、注意事项
- 性能影响 :开启慢查询日志会有约1-3%的性能开销
- 磁盘空间 :定期清理,避免日志文件过大
- 敏感信息 :日志可能包含敏感数据,需妥善保管
- 生产环境 :建议设置合理的阈值,避免记录过多无关查询
- 版本差异 :MySQL 5.7+ 支持微秒级精度,之前版本只到秒
面试回答
简单来说,慢查询日志就像是 MySQL 的一个‘病历本’ 。它会自动记录下来所有执行时间超过某个阈值的 SQL 语句。这样我们开发或者 DBA 就能知道,哪些查询是‘慢’的、有问题的,然后去针对性地优化。
在实际工作中,我主要会关注和操作这么几个方面:
第一,怎么开启和设置。 慢查询日志默认是关闭的,因为它会有一点磁盘 I/O 的开销。我们需要在 MySQL 配置文件(比如 my.cnf )里设置几个核心参数:
- slow_query_log = ON :打开开关。
- slow_query_log_file :指定这个‘病历本’文件存哪里。
- long_query_time :这是最重要的一个阈值,单位是秒。比如设为 1,就意味着执行超过 1 秒的 SQL 才会被记录。这个值可以根据系统性能要求来调整。
- log_queries_not_using_indexes :这个我也经常会打开。它会记录那些没有使用索引的查询,即使它执行得很快。这能帮我们发现潜在的设计问题。
第二,怎么看这个日志。 日志是文本格式,可以直接看,但不太直观。我常用的方法是:
- 用 MySQL 自带的 mysqldumpslow 工具。这个命令行工具可以对日志进行汇总、排序,比如我们可以用 mysqldumpslow -t 10 -s t 来找出耗时最长的前 10 条 SQL,一目了然。
- 对于更复杂的分析,我会用 Percona 公司开的 **** pt-query-digest 工具。它功能更强大,能给出非常详细的报告,比如每个 SQL 的响应时间占比、执行次数、锁时间等,能帮我快速定位最需要优化的‘瓶颈’ SQL。
第三,也是最重要的,找到慢 SQL 后怎么办。 光找到没用,关键是要优化。我一般的排查思路是:
- 拿到这条慢 SQL,先 用 explain 命令去看它的执行计划 。这是标准动作。我会重点看:
- 有没有用到索引( key 字段)。
- 扫描了多少行( rows 字段)。
- 查询类型是不是全表扫描( type 字段,如果是 ALL 就不好了)。
- 根据 * explain *的结果,常见的优化手段就是:
- 加索引 :这是最有效的办法之一,检查 WHERe 、 ORDER BY 、 JOIN 的字段。
- 优化 SQL 本身 :比如避免 SELECT * ,检查是否有复杂的子查询能不能改写为 JOIN ,或者分页查询在大偏移量时有没有优化空间。
- 看看是不是数据库参数问题 ,比如缓冲池大小是不是不合理。
--- 最后,我的一点实践经验是 :慢查询日志在测试环境和生产环境都很有用。在项目上线前,我们会开启它来提前发现一些性能问题。在生产环境,我们会长期开启,但会设置一个合理的 long_query_time (比如从 2 秒开始),并定期归档和分析日志,把它作为性能监控和容量规划的一个重要依据。
