必须确认slow_query_log为ON且slow_query_log_file路径MySQL进程有写权限,再用SELECT SLEEP(3)实测日志是否生成;常见错误是配置未生效、路径无权限或log_output被设为TABLE却未查表。

如何确认慢查询日志是否真正开启并写入
很多问题其实卡在第一步:你以为日志开着,其实没生效。关键看两个地方:slow_query_log 必须为 ON,且 slow_query_log_file 指向的路径 MySQL 进程有写权限。用 SHOW VARIABLES LIKE 'slow%'; 查,别只信配置文件里写了就完事。
常见错误现象:配置改了但没重启(或没 SET PERSIST),或者日志路径是 /var/log/mysql/slow.log 但 mysqld 是以 mysql 用户跑的,而该目录属主是 root,导致写失败——此时日志文件大小永远是 0。
- 检查日志文件最后修改时间:
stat /var/lib/mysql/hostname-slow.log - 手动触发一条慢 SQL 测试:
SELECT SLEEP(3);(前提是long_query_time=2) - 如果仍无记录,加一句
SET GLOBAL log_output = 'FILE';,避免被设成TABLE写进mysql.slow_log表却忘了查
为什么 mysqldumpslow 解析结果常不准甚至漏掉 TOP SQL
mysqldumpslow 默认按“抽象后”的 SQL 归类(比如把 WHERE id=123 和 WHERE id=456 合成一条),但它对子查询、UNION、多行注释、引号嵌套等处理很脆弱,容易把本该合并的拆成多条,或把不同逻辑的强行合并。
更实际的问题是:它不统计执行次数以外的指标,比如单次扫描行数(Rows_examined)、临时表使用量、排序次数——这些才是高负载的真正元凶。
- 用
mysqldumpslow -s at -t 10 /var/lib/mysql/hostname-slow.log只能看平均响应时间,但可能掩盖“99% 请求快、1% 极慢”的毛刺型 SQL - 真正要定位资源消耗大户,得直接解析原始日志,提取
# Rows_examined:、# Rows_sent:、# Temp_tables:等字段 - 推荐用 Python 脚本或
awk做二次聚合,例如:awk '/^# Time:/ {time=$3" "$4} /Rows_examined:/ {if($2>10000) print time, $0}' slow.log | sort -k2nr | head -20
如何从慢日志里提取带绑定参数的真实执行 SQL
MySQL 8.0+ 开启 log_slow_extra=ON 后,日志里会出现 # Query_time: ... Rows_examined: ... Rows_affected: ... 下方紧跟着的 use db_name; 和真实语句。但注意:如果应用用了预编译(Prepared Statement),日志里显示的是带 ? 占位符的语句,不是最终执行的值。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
这意味着你看到 SELECT * FROM orders WHERE user_id = ? AND status = ?,但无法知道具体是哪个 user_id 导致扫描了 50 万行——除非开启 log_slow_verbosity=full(MySQL 8.0.26+)并配合 log_slow_filter=full_scan,full_join 等定向过滤。
- 低版本 MySQL 想看实际参数?只能靠应用层打点(如 MyBatis 的
org.apache.ibatis.logging.stdout.StdOutImpl)或代理层(如 ProxySQL)日志 - 不要依赖
mysqldumpslow -v,它不还原参数,只做语法归一化 - 检查日志中是否有
# Schema: xxx行,没有说明log_slow_extra未启用,很多关键上下文就丢了
为什么按执行时间排序的 TOP10 不等于资源消耗 TOP10
一条 SQL 执行 3 秒但只查 10 行,和另一条执行 0.8 秒但扫了 200 万行——后者对 I/O 和缓冲池压力大得多,更容易引发雪崩。慢日志里 Rows_examined 比 Query_time 更反映真实代价,尤其在 SSD 随机读性能远高于 HDD 的今天。
另一个盲区是并发影响:Query_time 是单次耗时,但若某 SQL 每秒被执行 200 次,哪怕每次只有 100ms,也会吃光连接线程和 CPU 时间片。
- 优先筛出
Rows_examined > 100000且Rows_sent 的语句——典型的“全表扫描取少量数据”,索引缺失或失效的强信号 - 关注
Using filesort或Using temporary出现场景,它们不出现在慢日志正文,但在EXPLAIN中可见;需结合pt-query-digest --explain补充分析 - 别忽略
Lock_time高的语句,尤其是UPDATE或DELETE,可能正阻塞其他事务,日志里未必标为“慢”,但它是锁等待链的源头
最麻烦的情况是:慢日志里看不到问题 SQL,因为 long_query_time 设太高,或 SQL 被优化器短路(如命中 query cache)、或走的是存储过程内部逻辑——这时候得切到 Performance Schema 查 events_statements_summary_by_digest 表。










