mysql 8.0慢查询日志默认关闭且输出至系统表,新增log_slow_extra字段导致mysqldumpslow解析失败;推荐使用pt-query-digest(≥3.5.0)替代,并注意query_time单位为微秒及lock_time计入总耗时。

MySQL 8.0 慢查询日志默认不写文件,且格式结构变了
升级到 MySQL 8.0 后,slow_query_log 默认值从 ON 变为 OFF,且即使开启,日志也不再自动写入文件(如 /var/lib/mysql/hostname-slow.log),而是输出到系统表 mysql.slow_log(需 log_output = 'TABLE')。很多运维仍习惯用 tail -f 查看文件,结果发现日志“消失了”——其实是根本没往文件里写。
更关键的是:8.0 默认启用 log_slow_extra = ON(5.7 不支持该变量),导致每条日志头部新增多行键值对字段,例如:
# Rows_examined: 12345 # Lock_time: 0.000123 # Query_time: 0.045678 # Rows_sent: 10
这些字段在 5.7 日志中完全不存在,传统解析工具会直接跳过或报错。
mysqldumpslow 解析失败的直接原因:版本不匹配 + extra 字段
mysqldumpslow 是随 MySQL 安装包分发的命令行工具,但它的解析逻辑硬编码了 5.7 的日志格式。遇到 8.0 新增的 # Rows_examined、# Lock_time 等行时,它无法识别,直接忽略整条语句,甚至提前退出。
验证是否踩坑,执行:
head -n 20 /var/log/mysql/mysql-slow.log | grep -E '^(# Time|# Rows_examined|# Lock_time)'
如果输出含 Rows_examined 或 Lock_time,说明日志含 extra 字段,而你用的 mysqldumpslow 很可能来自 5.7 包(比如 CentOS 7 自带 mariadb-libs 附带的老版本)。
- 必须确认路径和版本:
/usr/bin/mysqldumpslow --version - MySQL 8.0 自带的版本 ≥ 8.0.22 才能正确解析 extra 字段
- 关闭
log_slow_extra虽可“兼容”,但会丢失关键性能上下文(如扫描行数、锁等待时间),不推荐
pt-query-digest 是当前最稳妥的替代方案
pt-query-digest(Percona Toolkit)原生支持 MySQL 8.0 日志格式,无需降级配置或改日志结构。它能正确提取 Query_time(微秒级)、Rows_examined、tmp_tables 等所有字段,并聚合 prepared statement 占位符(如 SELECT * FROM user WHERE id = ?),这对分析 ORM 场景至关重要。
使用示例:
pt-query-digest /var/log/mysql/mysql-slow.log --limit 10
注意点:
- 确保 Percona Toolkit 版本 ≥ 3.5.0(适配 8.0+ 时间精度和字段扩展)
- 若日志路径不可读,可用
--processlist直连采集实时慢查(需PROCESS权限) - 它不依赖
log_output设置,FILE 或 TABLE 输出均可处理
MySQL 8.0 的 Query_time 单位是微秒,别被 long_query_time 值误导
long_query_time 在 8.0 中仍显示为浮点秒(如 10.0),但内部以微秒存储和判断。这意味着:
- 一条执行时间为
9.999999秒的语句,实际可能被记为9999999微秒 → 不触发慢日志 - 但若客户端设置会话级
SET SESSION long_query_time = 0.1,这个 0.1 会被转成 100000 微秒,精度无损 - 务必用
SELECT @@long_query_time;查全局值,避免被会话覆盖干扰判断
真正容易被忽略的是:8.0 对锁等待时间(Lock_time)单独计时,且计入 Query_time 总耗时。而 5.7 的 Query_time 是纯执行时间,不含锁。这会导致同一条 SQL 在两个版本下是否进入慢日志的判定结果不同——尤其在高并发争抢场景下。











