mysql慢查询日志需合理配置才能有效捕获真实瓶颈:slow_query_log开启后,须验证long_query_time阈值是否适配业务(建议从1秒起步)、确认日志路径权限充足且磁盘空间足够、启用log_queries_not_using_indexes时必须同步设置min_examined_row_limit过滤噪音,并注意set global仅对新连接生效。

MySQL慢查询日志不是“开了就能用”,关键在于 slow_query_log 开启后,long_query_time 阈值是否合理、日志是否真正落盘、以及是否漏掉未走索引的隐性慢查询。生产环境常见问题不是日志没开,而是开了但没捕获到真实瓶颈。
确认 slow_query_log 是否真正生效
动态设置 SET GLOBAL slow_query_log = 'ON' 后,必须检查当前会话是否继承了全局配置——有些客户端(如某些 GUI 工具或连接池)默认使用会话级变量,而 slow_query_log 是只读全局变量,不作用于已有连接。
- 执行
SHOW VARIABLES LIKE 'slow_query_log',返回值必须是ON(不是1或空),且注意该变量对当前连接无效,仅影响新建立的连接 - 执行
SELECT @@global.slow_query_log和SELECT @@session.slow_query_log对比,确认两者一致;若 session 为OFF,说明当前连接不会记录慢查询 - 重启 MySQL 或新建命令行连接(如
mysql -u root -p)后再验证,避免误判
long_query_time 设置低于 1 秒时的陷阱
long_query_time 支持小数(如 0.5),但单位是秒,且精度受 MySQL 版本限制:5.7 及以前只保留 1 位小数,8.0+ 支持微秒级(需配合 log_slow_extra=ON)。更重要的是,它只统计 SQL 执行时间,不含网络传输、解析、排队等待等开销。
- 设为
0.1并不等于“捕获所有耗时 >100ms 的查询”,因为实际执行时间可能被四舍五入或截断(例如 0.098s 被记为 0.09s) - 在高并发下,
long_query_time = 0会强制记录所有查询(含SELECT 1),极易撑爆磁盘,仅限临时诊断 - 建议先设为
1,观察日志量和典型查询耗时分布,再逐步下调;避免直接设0.2导致日志暴增却无有效信息
log_queries_not_using_indexes 必须配合 min_examined_row_limit
开启 log_queries_not_using_indexes = ON 后,MySQL 会对每个未走索引的查询都打日志——哪怕只查 1 行。这会造成大量噪音,尤其在 WHERE 条件恒为假(如 WHERE id = -1)时仍会记录。
- 务必同步设置
min_examined_row_limit(如100),表示“未走索引且扫描行数 ≥ 100 才记录”,过滤掉低危害的全表扫描 - 该参数不能动态设置(MySQL 5.7+ 支持,但部分云厂商定制版禁用),必须写进
my.cnf并重启 - 检查是否生效:执行
SHOW VARIABLES LIKE 'min_examined_row_limit',确认值非 0
日志路径与权限问题常被忽略
slow_query_log_file 指定的路径,必须由 MySQL 进程用户(通常是 mysql)有写权限,且所在分区不能满。否则日志静默失败,slow_query_log 显示 ON 却无任何内容。
- 用
ls -ld /var/log/mysql/确认目录属主是mysql:mysql,权限至少为drwxr-xr-x - 手动创建日志文件并赋权:
sudo touch /var/log/mysql/slow.log && sudo chown mysql:mysql /var/log/mysql/slow.log - 检查磁盘剩余空间:
df -h /var/log,日志轮转前预留 ≥2GB,避免因满盘导致 MySQL 拒绝写入甚至崩溃
最易被跳过的环节是:以为 SET GLOBAL 后立刻生效,却没意识到新连接才受控;以及把 long_query_time 设得太低,结果日志里全是健康查询,真正的瓶颈反而被淹没。调参前先看 SHOW GLOBAL STATUS LIKE 'Slow_queries' 的增长速率,比盲目改阈值更可靠。











