需开启log_slow_verbosity=‘full’(8.0.26+)、log_slow_admin_statements、log_slow_slave_statements及log_queries_not_using_indexes,并配合pt-query-digest–explain或应用层主动explain,才能使slow query log包含锁等待、执行计划等完整诊断信息。

默认的 slow_query_log 只记执行时间超阈值的 SQL,不带锁等待、解析耗时、执行计划摘要等关键信息,查问题时经常要反复连上去 EXPLAIN,效率低。
必须打开几个配套配置,否则日志只是“慢了”,不是“为什么慢”:
-
long_query_time = 1(按需调低,但别设0,MySQL 5.7+ 对0有特殊行为) -
log_queries_not_using_indexes = ON(注意:只对明确走全表扫描的语句生效,加了索引但没用上不算) -
log_slow_admin_statements = ON(否则ALTER TABLE、ANALYZE TABLE这类管理语句不会进慢日志) -
log_slow_slave_statements = ON(主从架构下,从库执行慢的 SQL 也得记录)
MySQL 的 slow log 是服务端在语句执行完后写入的,它记录的是原始文本(query 字段),不是预处理后的绑定值;也不包含 EXPLAIN FORMAT=JSON 输出——因为执行计划生成和日志写入是两个独立阶段,且开销不可控。
想补全这部分,只能靠外部工具或中间件配合:
- 用
pt-query-digest解析日志时加–explain参数,它会尝试重放 SQL 并抓执行计划(注意权限和数据一致性风险) - 在应用层统一打点:比如用
MySQLi::get_warnings()或PDO::getAttribute(PDO::ATTR_SERVER_VERSION)判断版本后,对慢 SQL 主动补发EXPLAIN FORMAT=TREE - 避免直接依赖日志里的
Rows_examined做判断——它在JOIN场景下是各表扫描行数乘积,常被高估
选 FILE(默认)还是 TABLE(写入 mysql.slow_log)不是性能问题,而是运维路径问题。
FILE 看起来原始,但配合 pt-query-digest 或 mysqldumpslow 更快;TABLE 虽然能用 SQL 查,但实际中容易踩三个坑:
-
mysql.slow_log是CSV引擎,不支持索引,10 万行以上SELECT就卡 - 日志写入是同步的,写
TABLE比写文件多一次 SQL 解析 + 存储引擎调用,极端高并发下可能拖慢慢查询本身 -
TRUNCATE TABLE mysql.slow_log不清空磁盘文件,只是删 CSV 数据,残留内容仍占空间
最常被忽略的是 MySQL 的“慢”定义和实际执行路径不一致。比如:
- SQL 执行时间
,但锁等待(innodb_row_lock_time)很长——它不会进 slow log,得看information_schema.INNODB_TRX - 存储过程里调用的 SQL,日志只记
CALL proc_name,不记内部语句(除非开启log_output = FILE+log_slow_verbosity = ‘full’,仅 8.0.26+ 支持) - 客户端设置了
SET SESSION long_query_time = 0,但全局long_query_time是 2,这时以 session 值为准——而很多监控工具只读全局变量,误判配置未生效
真正要定位“用户感知卡顿”,不能只盯 slow log,得把 performance_schema.events_statements_history_long 和 events_waits_history_long 一起捞出来对齐时间戳。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/253747.html