1. 慢查询日志的开启方式:参数不是改完就结束
先把结论放这:慢查询日志是MySQL排查性能问题最直接的入口,适合所有用了MySQL但还没系统看过慢查询日志的团队。很多人以为只要把 slow_query_log 打开,慢SQL就会自动出现在日志里,但真正配置过的人都知道,这里面的门道比你想象的多。
1.1 我见过的大多数默认配置,几乎等于没开
MySQL安装完默认情况下,slow_query_log 是关闭的,long_query_time 默认是10秒。10秒意味着什么?一个页面查询超过10秒,用户早就刷新页面或者关掉浏览器了,你等慢日志捞出来黄花菜都凉了。
所以在生产上,我一般建议把阈值调到1秒以内。不是说所有超过1秒的SQL都必须优化,而是先记录下来,再去分辨哪些值得处理。低于1秒的SQL一般不至于产生严重的线上故障,但业务流量上来之后,单次几十毫秒的SQL在并发下也会拖垮数据库,那是另一个层面的问题。
推荐的开启配置如下(以MySQL 8.0为例):
ini复制[mysqld]
slow_query_log = 1
slow_query_log_file = /data/mysql/logs/slow-query.log
long_query_time = 1
log_queries_not_using_indexes = 0
log_throttle_queries_not_using_indexes = 10
log_output = FILE
动态修改可以执行:
sql复制SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = 'OFF';
注意,long_query_time 的修改只对新建立的连接生效,已经存在的连接池连接会一直沿用旧值。所以我通常会建议修改完配置文件之后,再重启MySQL或至少观察一下当前连接是否已经拿到新变量值。
1.2 log_query_not_using_indexes到底要不要开
这个参数一开,所有没走索引的查询都会写进慢日志,它的初衷是帮你找出漏网之鱼。但在实际生产中,我强烈建议先不要贸然打开。
原因很简单:很多业务表本身数据量极小,几百行甚至几十行,这种表MySQL优化器认为全表扫描比走索引更快,你偏偏要求它“必须使用索引”,结果就是满屏都是这种SQL的慢日志记录,真正需要关注的慢查询反而被淹没在里面。
如果非要开,请把 log_throttle_queries_not_using_indexes 也配上,这个参数限制每分钟最多记录多少条“未使用索引”的查询,避免慢日志文件瞬间暴涨打满磁盘。
1.3 慢日志格式里最容易忽略的三个时间字段
一条典型的慢日志记录长这样:
code复制# Query_time: 2.543521 Lock_time: 0.000331 Rows_sent: 28 Rows_examined: 409690
# Thread_id: 2897033 Schema: shopdb Errno: 0
# Rows_examined: 409690 Rows_sent: 28
SET timestamp=1718611200;
SELECT user_id, order_id, amount FROM order_info WHERE status = 1 ORDER BY create_time DESC LIMIT 28;
一般人会直接看 Query_time,觉得这一项大就该优化。但有个细节:Query_time 包含了 Lock_time,如果你发现某条慢日志的 Query_time 很长而实际执行时间很短,问题大概率出在锁等待上,而不是SQL本身。后面我会专门用一个章节展开讲这种情况。
还有一个容易忽略的点是 Rows_examined 和 Rows_sent 的比例。刚才这条日志扫描了40万行,最后只返回28行,这种扫描行数与返回行数差距巨大的SQL,是典型的索引设计不合理。如果一条慢查询的 Rows_examined 只有几百行,那就算执行时间到了1秒,也未必单纯是SQL问题,可能是服务器CPU负载、磁盘IO或者其他外部因素导致的,处理思路并不一样。
1.4 分析慢日志:mysqldumpslow和pt-query-digest怎么配合
日志是文本,直接打开看会很痛苦。MySQL自带的 mysqldumpslow 工具能帮你按不同的维度汇总:
bash复制# 按照平均查询时间排序,取前10条
mysqldumpslow -s at -t 10 /data/mysql/logs/slow-query.log
# 按查询次数排序,看哪些SQL经常出现
mysqldumpslow -s c -t 20 /data/mysql/logs/slow-query.log
这个工具会把SQL中的具体数字参数替换成N或S,这样同一条SQL的不同参数值能汇总成一条记录。比如 WHERE user_id = 123 和 WHERE user_id = 456 在汇总后会合并成 WHERE user_id = N,你可以一眼看出哪类SQL模式是慢查询中的大头。
Percona Toolkit里的 pt-query-digest 更专业,它会按“查询指纹”把
