欧菲 發表於 2026-1-3 09:24:59

一文带大家深入了解下MySQL中的慢查询日志

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">一、什么是慢查询日志</a></li><li><a href="#_label1">二、核心作用</a></li><li><a href="#_label2">三、配置参数详解</a></li><li><a href="#_label3">四、开启和配置</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_0">1. 临时开启(重启失效)</a></li><li><a href="#_lab2_3_1">2. 永久开启(修改配置文件)</a></li></ul><li><a href="#_label4">五、慢查询日志格式分析</a></li><ul class="second_class_ul"><li><a href="#_lab2_4_2">典型日志条目</a></li><li><a href="#_lab2_4_3">关键字段解释</a></li></ul><li><a href="#_label5">六、慢查询分析工具</a></li><ul class="second_class_ul"><li><a href="#_lab2_5_4">1.mysqldumpslow(MySQL 自带)</a></li><li><a href="#_lab2_5_5">2.pt-query-digest(Percona Toolkit)</a></li><li><a href="#_lab2_5_6">3.mysqlslow(第三方工具)</a></li></ul><li><a href="#_label6">七、慢查询日志表模式</a></li><ul class="second_class_ul"><li><a href="#_lab2_6_7">启用表模式存储</a></li><li><a href="#_lab2_6_8">表结构</a></li></ul><li><a href="#_label7">八、最佳实践和优化建议</a></li><ul class="second_class_ul"><li><a href="#_lab2_7_9">1.阈值设置建议</a></li><li><a href="#_lab2_7_10">2.日志轮转配置</a></li><li><a href="#_lab2_7_11">3.定期分析计划</a></li></ul><li><a href="#_label8">九、性能监控和告警</a></li><ul class="second_class_ul"><li><a href="#_lab2_8_12">1. 监控慢查询数量</a></li><li><a href="#_lab2_8_13">2. 慢查询告警脚本</a></li></ul><li><a href="#_label9">十、注意事项</a></li><ul class="second_class_ul"></ul><li><a href="#_label10">面试回答</a></li><ul class="second_class_ul"></ul></ul></div><p class="maodian"><a name="_label0"></a></p><h2>一、什么是慢查询日志</h2>
<p><strong>慢查询日志(Slow Query Log)</strong> 是 MySQL 内置的一种日志功能,用于记录执行时间超过指定阈值的 SQL 语句。这是优化数据库性能的重要工具。</p>
<p class="maodian"><a name="_label1"></a></p><h2>二、核心作用</h2>
<ul><li><strong>性能诊断</strong>:找出执行效率低的 SQL 语句</li><li><strong>瓶颈定位</strong>:分析查询为什么慢(全表扫描、索引缺失等)</li><li><strong>优化依据</strong>:为 SQL 优化和索引调整提供数据支持</li></ul>
<p class="maodian"><a name="_label2"></a></p><h2>三、配置参数详解</h2>
<div class="jb51code"><pre class="brush:sql;">-- 查看所有慢查询相关参数
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   # 输出方式
</pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>四、开启和配置</h2>
<p class="maodian"><a name="_lab2_3_0"></a></p><h3>1. 临时开启(重启失效)</h3>
<div class="jb51code"><pre class="brush:sql;">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';
</pre></div>
<p class="maodian"><a name="_lab2_3_1"></a></p><h3>2. 永久开启(修改配置文件)</h3>
<div class="jb51code"><pre class="brush:plain;"># my.cnf 或 my.ini

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
</pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>五、慢查询日志格式分析</h2>
<p class="maodian"><a name="_lab2_4_2"></a></p><h3>典型日志条目</h3>
<div class="jb51code"><pre class="brush:sql;"># Time: 2024-01-01T10:00:00.123456Z
# User@Host: root @ localhost []Id:   5
# Query_time: 5.123456Lock_time: 0.001000Rows_sent: 10Rows_examined: 1000000
SET timestamp=1672560000;
SELECT * FROM users WHERE last_name LIKE '%smith%' ORDER BY create_time DESC;
</pre></div>
<p class="maodian"><a name="_lab2_4_3"></a></p><h3>关键字段解释</h3>
<ul><li><strong>Query_time</strong>:查询执行总时间</li><li><strong>Lock_time</strong>:锁定时间</li><li><strong>Rows_sent</strong>:返回给客户端的行数</li><li><strong>Rows_examined</strong>:扫描的行数</li><li><strong>Rows_affected</strong>:影响的行数(UPDATE/DELETE/INSERT)</li></ul>
<p class="maodian"><a name="_label5"></a></p><h2>六、慢查询分析工具</h2>
<p class="maodian"><a name="_lab2_5_4"></a></p><h3>1.mysqldumpslow(MySQL 自带)</h3>
<div class="jb51code"><pre class="brush: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
</pre></div>
<p class="maodian"><a name="_lab2_5_5"></a></p><h3>2.pt-query-digest(Percona Toolkit)</h3>
<div class="jb51code"><pre class="brush: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 &gt; slow_report.txt
</pre></div>
<p class="maodian"><a name="_lab2_5_6"></a></p><h3>3.mysqlslow(第三方工具)</h3>
<div class="jb51code"><pre class="brush:bash;">mysqlslow /var/log/mysql/slow.log
</pre></div>
<p class="maodian"><a name="_label6"></a></p><h2>七、慢查询日志表模式</h2>
<p class="maodian"><a name="_lab2_6_7"></a></p><h3>启用表模式存储</h3>
<div class="jb51code"><pre class="brush:sql;">SET GLOBAL log_output = 'TABLE';
SET GLOBAL slow_query_log = 'ON';

-- 查询慢查询日志
SELECT * FROM mysql.slow_log;
</pre></div>
<p class="maodian"><a name="_lab2_6_8"></a></p><h3>表结构</h3>
<div class="jb51code"><pre class="brush:sql;">SHOW CREATE TABLE mysql.slow_log;

-- 主要字段:
-- start_time: 查询开始时间
-- query_time: 查询耗时
-- lock_time: 锁定时间
-- rows_sent: 返回行数
-- rows_examined: 检查行数
-- sql_text: SQL语句
-- user_host: 用户和主机信息
</pre></div>
<p class="maodian"><a name="_label7"></a></p><h2>八、最佳实践和优化建议</h2>
<p class="maodian"><a name="_lab2_7_9"></a></p><h3>1.阈值设置建议</h3>
<div class="jb51code"><pre class="brush: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毫秒
</pre></div>
<p class="maodian"><a name="_lab2_7_10"></a></p><h3>2.日志轮转配置</h3>
<div class="jb51code"><pre class="brush:plain;"># 使用 logrotate
/var/log/mysql/slow.log {
    daily
    rotate 30
    missingok
    compress
    delaycompress
    notifempty
    create 640 mysql mysql
    postrotate
      mysqladmin flush-logs
    endscript
}
</pre></div>
<p class="maodian"><a name="_lab2_7_11"></a></p><h3>3.定期分析计划</h3>
<div class="jb51code"><pre class="brush:bash;"># 每日分析脚本示例
#!/bin/bash
DATE=$(date +%Y%m%d)
pt-query-digest /var/log/mysql/slow.log &gt; /var/log/mysql/slow_report_${DATE}.txt
# 清空日志文件(先备份)
cp /var/log/mysql/slow.log /var/log/mysql/slow.log.${DATE}
echo "" &gt; /var/log/mysql/slow.log
</pre></div>
<p class="maodian"><a name="_label8"></a></p><h2>九、性能监控和告警</h2>
<p class="maodian"><a name="_lab2_8_12"></a></p><h3>1. 监控慢查询数量</h3>
<div class="jb51code"><pre class="brush:sql;">-- 监控每分钟的慢查询数量
SHOW GLOBAL STATUS LIKE 'Slow_queries';

-- 查看当前慢查询
SHOW PROCESSLIST;
</pre></div>
<p class="maodian"><a name="_lab2_8_13"></a></p><h3>2. 慢查询告警脚本</h3>
<div class="jb51code"><pre class="brush: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
</pre></div>
<p class="maodian"><a name="_label9"></a></p><h2>十、注意事项</h2>
<p><strong>性能影响</strong>:开启慢查询日志会有约1-3%的性能开销</p>
<p><strong>磁盘空间</strong>:定期清理,避免日志文件过大</p>
<p><strong>敏感信息</strong>:日志可能包含敏感数据,需妥善保管</p>
<p><strong>生产环境</strong>:建议设置合理的阈值,避免记录过多无关查询</p>
<p><strong>版本差异</strong>:MySQL 5.7+ 支持微秒级精度,之前版本只到秒</p>
<p class="maodian"><a name="_label10"></a></p><h2>面试回答</h2>
<p>简单来说,<strong>慢查询日志就像是 MySQL 的一个&lsquo;病历本&rsquo;</strong>。它会自动记录下来所有执行时间超过某个阈值的 SQL 语句。这样我们开发或者 DBA 就能知道,哪些查询是&lsquo;慢&rsquo;的、有问题的,然后去针对性地优化。</p>
<p>在实际工作中,我主要会关注和操作这么几个方面:</p>
<p><strong>第一,怎么开启和设置。</strong></p>
<p>慢查询日志默认是关闭的,因为它会有一点磁盘 I/O 的开销。我们需要在 MySQL 配置文件(比如 <code>my.cnf</code>)里设置几个核心参数:</p>
<ul><li><code>slow_query_log = ON</code>:打开开关。</li><li><code>slow_query_log_file</code>:指定这个&lsquo;病历本&rsquo;文件存哪里。</li><li><code>long_query_time</code>:这是最重要的一个阈值,单位是秒。比如设为 1,就意味着执行超过 1 秒的 SQL 才会被记录。这个值可以根据系统性能要求来调整。</li><li><code>log_queries_not_using_indexes</code>:这个我也经常会打开。它会记录那些没有使用索引的查询,即使它执行得很快。这能帮我们发现潜在的设计问题。</li></ul>
<p><strong>第二,怎么看这个日志。</strong></p>
<p>日志是文本格式,可以直接看,但不太直观。我常用的方法是:</p>
<ul><li>用 MySQL 自带的 <code>mysqldumpslow</code> 工具。这个命令行工具可以对日志进行汇总、排序,比如我们可以用 <code>mysqldumpslow -t 10 -s t</code> 来找出耗时最长的前 10 条 SQL,一目了然。</li><li>对于更复杂的分析,我会用 <strong>Percona 公司开的</strong> ****<code>pt-query-digest</code> 工具。它功能更强大,能给出非常详细的报告,比如每个 SQL 的响应时间占比、执行次数、锁时间等,能帮我快速定位最需要优化的&lsquo;瓶颈&rsquo; SQL。</li></ul>
<p><strong>第三,也是最重要的,找到慢 SQL 后怎么办。</strong></p>
<p>光找到没用,关键是要优化。我一般的排查思路是:</p>
<p>1、拿到这条慢 SQL,先<strong>用</strong> <code>explain</code> <strong>命令去看它的执行计划</strong>。这是标准动作。我会重点看:</p>
<ul><li>有没有用到索引(<code>key</code> 字段)。</li><li>扫描了多少行(<code>rows</code> 字段)。</li><li>查询类型是不是全表扫描(<code>type</code> 字段,如果是 <code>ALL</code> 就不好了)。</li></ul>
<p>2、根据 ****<code>explain</code> ****的结果,常见的优化手段就是:</p>
<ul><li><strong>加索引</strong>:这是最有效的办法之一,检查 <code>WHERE</code>、<code>ORDER BY</code>、<code>JOIN</code> 的字段。</li><li><strong>优化 SQL 本身</strong>:比如避免 <code>SELECT *</code>,检查是否有复杂的子查询能不能改写为 <code>JOIN</code>,或者分页查询在大偏移量时有没有优化空间。</li><li><strong>看看是不是数据库参数问题</strong>,比如缓冲池大小是不是不合理。</li></ul>
<p><strong>最后,我的一点实践经验是</strong>:慢查询日志在测试环境和生产环境都很有用。在项目上线前,我们会开启它来提前发现一些性能问题。在生产环境,我们会长期开启,但会设置一个合理的 <code>long_query_time</code>(比如从 2 秒开始),并定期归档和分析日志,把它作为性能监控和容量规划的一个重要依据。</p>
<p>以上就是一文带大家深入了解下MySQL中的慢查询日志的详细内容,更多关于MySQL慢查询日志的资料请关注琼殿技术社区其它相关文章!</p>
頁: [1]
查看完整版本: 一文带大家深入了解下MySQL中的慢查询日志