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问题。

相关推荐
GetcharZp5 小时前
玩转 Linux 机器视觉:手把手带你搞定 Ubuntu 下海康工业相机 C++ SDK
后端
星星在线8 小时前
MusicFree:一个「All in One」的个人音乐服务器,让听歌回归简单
前端·后端
IT_陈寒9 小时前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x9 小时前
Docling 文档转换以及技术架构分析
前端·后端·程序员
袋鱼不重11 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
大树8811 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
用户83562907805111 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还11 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
摇滚侠11 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
Hommy8811 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api