MySQL调优 一:慢SQL日志

目录

    • 一、什么是慢SQL日志?
    • 二、慢查询日志的开启与配置
        1. 配置文件方式(永久生效)
        1. 动态开启(不需重启,适合临时调试)
        1. MySQL 8.0+ 新特性
    • 三、慢查询日志的内容格式
    • 四、慢查询日志分析工具
        1. mysqldumpslow(MySQL内置)
        1. pt-query-digest
        1. 其他工具
    • 五、一些使用时需注意的
      • 1.日志无限扩增问题
        1. **性能开销**

在数据库性能优化中,慢SQL日志(Slow Query Log)是最基础、最重要的诊断工具之一。它能自动记录所有执行时间超过指定阈值的SQL语句,帮助开发者与DBA快速发现潜在的性能问题。本文以MySQL为例,详细讲解慢SQL日志的原理、配置、使用、分析以及最佳实践。

一、什么是慢SQL日志?

慢SQL日志是数据库内置的一种日志机制,用于记录执行时间较长的查询语句。

MySQL中默认阈值是10秒(long_query_time = 10),但在生产环境中通常会调低到1秒甚至0.5秒。

除了执行时间超长的查询,还可以选择记录:

  • 未使用索引的查询(即使执行很快)。
  • 不进入查询缓存的查询(旧版本MySQL)。

慢查询日志的用途:

  • 发现最耗时的SQL,优先优化。
  • 分析系统整体查询性能分布。
  • 作为性能基线,监控性能变化。

二、慢查询日志的开启与配置

1. 配置文件方式(永久生效)

编辑MySQL配置文件(通常是/etc/my.cnf/etc/mysql/my.cnf)的[mysqld]部分:

ini 复制代码
[mysqld]
slow_query_log = ON                          # 开启慢查询日志
slow_query_log_file = /var/log/mysql/slow.log # 日志文件路径
long_query_time = 1                          # 阈值1秒(支持小数,如0.5)
log_queries_not_using_indexes = ON           # 可选:记录未使用索引的查询
min_examined_row_limit = 100                 # 可选:扫描行数超过该值才记录(避免小表全扫)
log_slow_admin_statements = ON               # 可选:记录慢的管理员语句(如ALTER TABLE)
log_slow_slave_statements = ON               # 可选:从库记录慢查询(复制环境)

修改后重启MySQL服务生效。

2. 动态开启(不需重启,适合临时调试)

sql 复制代码
-- 开启慢查询日志
SET GLOBAL slow_query_log = ON;

-- 设置日志文件路径(需有权限)
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

-- 设置阈值(支持毫秒级,如0.1表示100ms)
SET GLOBAL long_query_time = 1;

-- 记录未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = ON;

注意:动态设置在MySQL重启后会失效。

3. MySQL 8.0+ 新特性

  • 支持微秒级精度阈值(long_query_time可设为0.000001)。
  • 默认日志格式为文本文件,也支持写入performance_schema或系统表。

三、慢查询日志的内容格式

一条典型的慢查询日志记录包含以下部分:

ini 复制代码
# Time: 2025-12-18T10:23:45.123456Z
# User@Host: app_user[app_user] @ 192.168.1.100 []
# Thread_id: 12345  Schema: mydb  QC_hit: 0
# Query_time: 2.345678  Lock_time: 0.000123  Rows_sent: 1000  Rows_examined: 1000000
# Rows_affected: 0
SET timestamp=1734517425;
SELECT * FROM orders WHERE create_time > '2025-01-01' ORDER BY id DESC;

关键字段解释:

  • Query_time:查询执行总耗时(最重要)。
  • Lock_time:获取锁等待时间。
  • Rows_sent:返回给客户端的行数。
  • Rows_examined:扫描的行数(越大越说明可能缺少索引)。
  • SET timestamp:查询开始执行的时间戳。
  • 最后是完整的SQL语句。

四、慢查询日志分析工具

手动查看日志效率低下,推荐使用专业工具:

1. mysqldumpslow(MySQL内置)

bash 复制代码
# 按执行时间排序,取前10条
mysqldumpslow -t 10 /var/log/mysql/slow.log

# 按平均执行时间排序
mysqldumpslow -s al -t 10 /var/log/mysql/slow.log

常用参数:

  • -s:排序方式(c:次数, t:时间, al:平均时间等)
  • -t:返回前N条
  • -g:配合正则过滤特定SQL

2. pt-query-digest

功能强大,支持详细统计报告。

bash 复制代码
pt-query-digest /var/log/mysql/slow.log > slow_report.txt

输出包括:

  • 排名前N的慢查询(按总时间、平均时间、执行次数)。
  • 每条SQL的摘要(指纹,去除常量)。
  • 执行计划统计(Rows examine、Lock time等)。
  • 查询时间分布图。

示例报告片段:

ini 复制代码
# Rank Query ID           Response time  Calls  R/Call  Item
# ==== ================== ============== ====== ======= ============
# 1    0xB7E4...          1234.5678 80%   500    2.469   SELECT orders

3. 其他工具

  • EverSQL Query Optimizer:在线分析。
  • MySQL Workbench / Navicat:图形化查看。
  • ELK栈或阿里云/腾讯云的日志服务:实时监控。

五、一些使用时需注意的

1.日志无限扩增问题

慢查询日志默认写入文件(如/var/log/mysql/slow.log),高并发或阈值设置过低时,日志会快速膨胀。核心解决思路是定期轮转(rotation)和归档,结合压缩和自动清理。

解决方案.:使用logrotate实现自动轮转

Linux系统自带的logrotate工具是最成熟的方案,能每天/每周自动切割日志、压缩旧文件、保留有限份数。

步骤:

创建或编辑/etc/logrotate.d/mysql-slow文件(路径可能因系统略有差异):

复制代码
/var/log/mysql/mysql-slow.log {  # 替换为你的实际日志路径
    daily                       # 每天轮转一次(可改weekly)
    rotate 14                   # 保留14份旧日志(约2周)
    compress                    # 压缩旧日志(gzip格式,节省空间)
    delaycompress               # 延迟压缩,上一份日志先不压
    missingok                   # 如果日志不存在,不报错
    notifempty                  # 空日志不轮转
    create 660 mysql mysql      # 新日志文件权限和属主
    sharedscripts
    postrotate
        # 安全刷新日志:临时关闭慢查询,等待缓冲flush,再恢复
        /usr/bin/mysql -e "
            SET @old = @@global.long_query_time;
            SET GLOBAL slow_query_log = OFF;
            SELECT SLEEP(5);  # 等待缓冲写入
            FLUSH SLOW LOGS;
            SET GLOBAL slow_query_time = @old;
            SET GLOBAL slow_query_log = ON;
        " > /dev/null 2>&1
    endscript
}

说明:

  • postrotate脚本中临时关闭慢查询日志,然后FLUSH SLOW LOGS让MySQL重新打开新文件,避免MySQL继续写旧文件(因为MySQL持有文件句柄),继续写旧文件可能会找不到文件,无法写入。
  • 更安全的变体:使用copytruncate选项(不需flush,但可能丢失少量日志)。
  • 测试配置:sudo logrotate -d /etc/logrotate.d/mysql-slow(调试模式)。
  • 强制执行:sudo logrotate -f /etc/logrotate.d/mysql-slow

这样配置后,日志每天切割,旧日志压缩保留14天,磁盘占用可控。

2. 性能开销

慢查询日志本身开销很小(仅记录超阈值查询),但如果阈值过低或开启log_queries_not_using_indexes,会记录大量语句,增加I/O负担,所以设置合理的阈值是很有必要的。

注:如果表内数据比较少也用不到慢查询日志,本文仅针对大表导致的慢sql问题。

相关推荐
疯狂踩坑人20 小时前
【Python版 2026 从零学Langchain 1.x】(二)结构化输出和工具调用
后端·python·langchain
玉梅小洋20 小时前
CentOS :yum源配置及验证指南
linux·运维·centos·yum
zxsz_com_cn20 小时前
设备预测性维护算法核心功能有哪些?六大模块拆解智能运维的“技术骨架”
运维·算法
自可乐20 小时前
n8n全面学习教程:从入门到精通的自动化工作流引擎实践指南
运维·人工智能·学习·自动化
春生野草20 小时前
Redis
数据库·redis·缓存
枷锁—sha20 小时前
【SRC】越权漏洞检测
运维·服务器·网络·安全·网络安全·系统安全
weixin_4997715520 小时前
Python上下文管理器(with语句)的原理与实践
jvm·数据库·python
weixin_4521595520 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python
策知道20 小时前
依托政府工作报告准备省考【经验贴】
大数据·数据库·人工智能·搜索引擎·政务
spencer_tseng20 小时前
MySQL table backup
mysql