mysqldumpslow不是查单条慢sql,而是通过抽象参数(如id=123→id=n)归类sql模板,再按总耗时、次数、锁等待等维度排序,快速识别高频/高耗时/高锁等待的瓶颈模式;默认抽象会掩盖具体参数,需加-a查看原始语句,但丧失聚合价值。

直接说结论:mysqldumpslow 不是用来“查单条慢 SQL”的,而是用来快速识别高频、高耗时、高锁等待的 SQL 模板——它靠抽象(比如把 WHERE id=123 变成 WHERE id=N)归类,再按维度排序。不理解这点,就容易误读输出、漏掉真瓶颈。
为什么 mysqldumpslow 输出里看不到具体参数
默认行为就是抽象数字为 N、字符串为 'S',例如 SELECT * FROM users WHERE name='alice' 和 SELECT * FROM users WHERE name='bob' 会被合并成一条模板:SELECT * FROM users WHERE name='S'。这是为了聚合相似查询,避免被大量仅参数不同的语句刷屏。
- 想看原始 SQL?加
-a参数,但会失去聚合效果,日志一多根本没法扫 - 抽象后仍想保留部分数字特征?可用
-n 3表示“至少 3 位数才抽象”,但实际极少用,兼容性差且易误导 - 真正需要定位某次具体执行?别依赖
mysqldumpslow,直接grep原始 slow log 文件更可靠
排序参数 -s 的真实含义和常见误用
-s 决定的是“按哪一列汇总值排序”,不是按单次执行时间或行数。比如 -s t 是按该 SQL 模板的**总耗时(Time=xxs(yy s))** 排序,括号里是累计时间;-s at 才是平均时间。
-
-s c:按出现次数(Count)降序 → 找高频查询,适合发现缓存穿透、未加 limit 的列表页 -
-s t:按总耗时降序 → 找“最烧 CPU”的模板,但可能被一次极端慢查询拉高,掩盖日常问题 -
-s ar:按平均返回行数降序 → 配合Rows字段,能揪出SELECT *或没走索引的大范围扫描 - 别用
-s r(总行数)代替-s ar:前者容易被单次大批量导出扭曲,参考价值低
必须配合 -t 和 -g 的实战组合
不加 -t 默认只输出前 10 条,但这个“前 10”是按默认排序(-s at)来的,未必是你关心的。而 -g 虽然功能弱(只支持简单子串匹配,不支持正则),但在初期过滤时很实用。
- 查所有写操作:用
mysqldumpslow -s t -t 20 -g "UPDATE\|INSERT\|DELETE" slow.log - 聚焦某个表:用
mysqldumpslow -s c -t 10 -g "orders" slow.log(注意空格和大小写不敏感) - 排除系统账号干扰:原始输出里有
root[root]@localhost这类,但mysqldumpslow不支持按 user 过滤,得靠后续grep -v "root\|admin" - 路径必须写对:如果日志是
/var/log/mysql/mysql-slow.log,别漏掉.log后缀,否则报错Can't read /var/log/mysql/mysql-slow: No such file
容易被忽略的三个硬限制
mysqldumpslow 是 Perl 脚本,解析逻辑简单粗暴,遇到格式异常或新版 MySQL 日志结构变化时会静默跳过甚至崩掉。
- MySQL 8.0.21+ 默认启用
log_slow_extra,日志多了Query_time_microsec等字段,老版本mysqldumpslow会解析失败 → 检查脚本版本,或临时关掉该选项 - 日志若被轮转(如
slow.log.1.gz),它不支持自动解压,必须先zcat slow.log.1.gz > slow.log.1再分析 - 输出里的
Lock=0.00s(s)中括号内是累计锁等待时间,但mysqldumpslow默认从总时间里减去锁时间(即真实执行时间),如需看含锁总耗时,务必加-l











