MySQL慢查询日志详细使用指南
一、慢查询日志简介
慢查询日志是MySQL记录执行时间超过指定阈值的SQL语句的日志文件。用于帮助开发者和DBA找出性能瓶颈。
二、开启慢查询日志
1. 临时开启(重启失效)
sql
-- 查看当前慢查询配置
SHOW VARIABLES LIKE '%slow_query%';
SHOW VARIABLES LIKE '%long_query%';
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
-- 设置慢查询阈值(单位:秒)
SET GLOBAL long_query_time = 1; -- 执行超过1秒的SQL
-- 设置慢查询日志文件路径
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- 记录未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 记录管理语句(ALTER TABLE等)
SET GLOBAL log_slow_admin_statements = 'ON';
-- 记录慢的从库查询
SET GLOBAL log_slow_slave_statements = 'ON';
2. 永久开启(修改配置文件)
ini
# 编辑MySQL配置文件 my.cnf / my.ini
[mysqld]
# 开启慢查询日志
slow_query_log = ON
# 指定日志文件路径
slow_query_log_file = /var/log/mysql/slow.log
# 慢查询阈值(秒)
long_query_time = 1
# 记录未使用索引的查询
log_queries_not_using_indexes = ON
# 记录管理语句
log_slow_admin_statements = ON
# 最小扫描行数阈值
min_examined_row_limit = 100 # 扫描行数超过100才记录
# 重启MySQL服务
service mysql restart
# 或
systemctl restart mysqld
3. Docker环境开启
bash
# docker-compose.yml
version: '3'
services:
mysql:
image: mysql:8.0
command:
- --slow_query_log=ON
- --slow_query_log_file=/var/log/mysql/slow.log
- --long_query_time=1
volumes:
- ./mysql-slow-logs:/var/log/mysql
三、慢查询日志分析工具
1. 原生mysqldumpslow工具(MySQL自带)
bash
# 查看帮助
mysqldumpslow --help
# 常用命令示例
# 1. 按照平均执行时间排序,显示前10条
mysqldumpslow -s at -t 10 /var/log/mysql/slow.log
# 2. 按照总执行时间排序
mysqldumpslow -s t /var/log/mysql/slow.log
# 3. 按照执行次数排序
mysqldumpslow -s c /var/log/mysql/slow.log
# 4. 只显示包含特定字符串的查询
mysqldumpslow -g "SELECT" /var/log/mysql/slow.log
# 5. 详细信息格式
mysqldumpslow -a /var/log/mysql/slow.log
# 6. 分析多个日志文件
mysqldumpslow /var/log/mysql/slow*.log
# 7. 输出到文件
mysqldumpslow -s at -t 20 /var/log/mysql/slow.log > slow_report.txt
# 参数说明:
# -s 排序方式:c(次数) t(时间) l(锁时间) r(返回行数) at(平均时间)
# -t 显示前N条
# -g 正则匹配
# -a 显示完整的SQL语句(不抽象化)
# -n 抽象化时至少显示多少位数字
# -r 反转排序顺序
2. pt-query-digest(Percona Toolkit)
bash
# 安装
# Ubuntu/Debian
apt-get install percona-toolkit
# CentOS/RHEL
yum install percona-toolkit
# 使用示例
# 1. 基本分析
pt-query-digest /var/log/mysql/slow.log
# 2. 分析并输出报告
pt-query-digest /var/log/mysql/slow.log --output slow_report.txt
# 3. 分析指定时间段的日志
pt-query-digest /var/log/mysql/slow.log --since '2024-01-01' --until '2024-01-31'
# 4. 只分析特定数据库
pt-query-digest /var/log/mysql/slow.log --filter '($event->{db} || "") =~ m/test_db/'
# 5. 分析并发送邮件报告
pt-query-digest /var/log/mysql/slow.log --output sendmail --mail-to=dba@example.com
# 6. 持续监控(每30秒分析一次)
pt-query-digest /var/log/mysql/slow.log --interval 30
# 7. 分析binlog中的慢查询
mysqlbinlog mysql-bin.000001 | pt-query-digest --type=binlog
# 8. 分析TCP流量
tcpdump -s 65535 -x -nn -q -tttt -i any port 3306 > mysql.tcp.txt
pt-query-digest --type=tcpdump mysql.tcp.txt
# 9. 详细分析报告(JSON格式)
pt-query-digest /var/log/mysql/slow.log --output json --no-report | python -m json.tool
3. MySQL内置分析
sql
-- 1. 使用performance_schema分析(MySQL 5.6+)
SELECT * FROM performance_schema.events_statements_summary_by_digest
WHERE SUM_TIMER_WAIT > 1000000000 -- 大于1秒
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
-- 2. 解析慢查询日志到表
SET GLOBAL slow_query_log = OFF;
-- 使用mysqlslowlog工具或自己解析
-- 安装mysql-utilities
mysqlslowlog --slow /var/log/mysql/slow.log --log-output table --create-table --execute
-- 3. 查询慢查询统计
SELECT
db,
query_time_avg,
rows_examined_avg,
last_seen,
ts_cnt as execution_count
FROM mysql.slow_log
GROUP BY db, query
ORDER BY query_time_sum DESC
LIMIT 10;
四、慢查询日志格式解析
日志示例:
# Time: 2024-01-26T10:30:45.123456Z
# User@Host: root[root] @ localhost [] Id: 12345
# Query_time: 2.345678 Lock_time: 0.000123 Rows_sent: 10 Rows_examined: 1000000
SET timestamp=1706257845;
SELECT * FROM users WHERE age > 30 ORDER BY create_time DESC LIMIT 10;
字段说明:
- Time:查询执行时间(UTC)
- User@Host:执行查询的用户和主机
- Query_time:查询执行总时间(秒)
- Lock_time:锁等待时间(秒)
- Rows_sent:返回给客户端的行数
- Rows_examined:扫描的行数
- SET timestamp:查询开始的时间戳
- 最后一行:实际的SQL语句
五、实战分析案例
案例1:找出最耗时的查询
bash
# 使用pt-query-digest找出Top 10慢查询
pt-query-digest /var/log/mysql/slow.log --limit 10 --report-format=query_report --filter='($event->{fingerprint}) =~ m/^SELECT/'
# 输出结果示例:
# Rank 1: 0.42 QPS, 12.23 concurrency, 29.1s time, 2.34M rows
# Exec time: 29.1s Lock time: 12ms Rows sent: 100 Rows examined: 2.34M
# Query: SELECT * FROM orders WHERE user_id=? AND status=?
案例2:分析特定时间段的慢查询
bash
# 分析今天9:00-18:00的慢查询
pt-query-digest /var/log/mysql/slow.log \
--since '2024-01-26 09:00:00' \
--until '2024-01-26 18:00:00' \
--output slow_analysis.html
# 生成HTML报告
open slow_analysis.html
案例3:实时监控慢查询
bash
# 监控最近1分钟的慢查询
watch -n 10 "pt-query-digest /var/log/mysql/slow.log --since '1m ago' --limit 5"
# 或使用tail实时查看
tail -f /var/log/mysql/slow.log | grep --line-buffered "Query_time" | while read line; do
echo "[$(date)] Slow query detected: $line"
done
六、慢查询日志管理
1. 日志轮转(避免日志文件过大)
bash
# 方法1:使用logrotate
# /etc/logrotate.d/mysql-slow
/var/log/mysql/slow.log {
daily
rotate 30
missingok
compress
delaycompress
notifempty
create 640 mysql mysql
postrotate
mysql -e "FLUSH SLOW LOGS;"
endscript
}
# 方法2:手动轮转
mv /var/log/mysql/slow.log /var/log/mysql/slow.log.$(date +%Y%m%d)
mysql -e "FLUSH SLOW LOGS;"
gzip /var/log/mysql/slow.log.$(date +%Y%m%d)
2. 清理旧日志
bash
# 删除30天前的慢查询日志
find /var/log/mysql/ -name "slow.log.*" -mtime +30 -delete
# 或使用pt-query-digest归档
pt-query-digest /var/log/mysql/slow.log --output slow_report_$(date +%Y%m%d).txt
> /var/log/mysql/slow.log # 清空日志文件
3. 调整日志记录策略
sql
-- 只在业务高峰期间记录
-- 使用事件调度器
CREATE EVENT adjust_slow_log
ON SCHEDULE EVERY 1 DAY
STARTS '2024-01-26 09:00:00'
DO
BEGIN
-- 工作日9:00-18:00开启慢查询
IF DAYOFWEEK(NOW()) BETWEEN 2 AND 6
AND HOUR(NOW()) BETWEEN 9 AND 18 THEN
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
ELSE
SET GLOBAL slow_query_log = 'OFF';
END IF;
END;
七、自动化慢查询分析脚本
bash
#!/bin/bash
# slow_query_analyzer.sh
LOGFILE="/var/log/mysql/slow.log"
REPORT_DIR="/var/log/mysql/reports"
THRESHOLD=5 # 只分析超过5秒的查询
DAYS_TO_KEEP=30
# 创建报告目录
mkdir -p $REPORT_DIR
# 生成每日报告
DATE=$(date +%Y%m%d)
REPORT_FILE="$REPORT_DIR/slow_report_$DATE.html"
# 使用pt-query-digest生成HTML报告
pt-query-digest $LOGFILE \
--filter "\$event->{Query_time} > $THRESHOLD" \
--output html \
> $REPORT_FILE
# 发送邮件通知(如果有超过10秒的查询)
LONG_QUERIES=$(pt-query-digest $LOGFILE --filter "\$event->{Query_time} > 10" --limit 1 | wc -l)
if [ $LONG_QUERIES -gt 0 ]; then
echo "发现超过10秒的慢查询,请查看附件" | mail -s "MySQL慢查询警报 $(date)" \
-a $REPORT_FILE \
dba@example.com
fi
# 轮转日志文件
mv $LOGFILE "${LOGFILE}.${DATE}"
mysql -e "FLUSH SLOW LOGS;"
# 清理旧报告
find $REPORT_DIR -name "slow_report_*" -mtime +$DAYS_TO_KEEP -delete
find /var/log/mysql -name "slow.log.*" -mtime +$DAYS_TO_KEEP -delete
八、慢查询优化流程
标准优化流程:
- 发现慢查询:通过慢查询日志定位
- 分析原因:使用EXPLAIN分析执行计划
- 优化方案:添加索引、重写SQL、调整架构
- 验证效果:对比优化前后性能
- 监控跟进:持续监控避免回归
优化示例:
sql
-- 原始慢查询
SELECT * FROM orders
WHERE DATE(create_time) = '2024-01-01'
AND user_id = 123
AND status = 1;
-- 优化后
SELECT * FROM orders
WHERE create_time >= '2024-01-01 00:00:00'
AND create_time < '2024-01-02 00:00:00'
AND user_id = 123
AND status = 1;
-- 添加索引
CREATE INDEX idx_user_status_time ON orders(user_id, status, create_time);
九、注意事项
- 性能影响:开启慢查询日志对I/O有轻微影响
- 磁盘空间:定期清理日志文件
- 敏感信息:日志可能包含敏感数据,注意权限管理
- 生产环境:建议阈值设为1-2秒,开发环境可设为0.1秒
- 版本差异:MySQL 5.6+支持微秒级精度,之前只支持秒
十、可视化工具推荐
- Percona Monitoring and Management (PMM) - 免费
- MySQL Enterprise Monitor - 商业
- VividCortex - SaaS服务
- pt-query-digest + Grafana - 自定义仪表板
通过合理使用慢查询日志,可以系统性地发现和解决数据库性能问题,是MySQL性能优化的重要工具。