mysql慢查询日志不记录明显超时sql,主因是未通过“开关+输出路径+阈值”三重校验:slow_query_log必须为on(非1/true)、log_output需设为file或table、long_query_time仅对新会话生效且不计锁等待时间。

MySQL 慢查询日志不记录某条明显超时的 SQL,大概率不是日志“坏了”,而是这条 SQL 在 MySQL 内部执行流中根本没被判定为“慢”——long_query_time 的生效时机和判定逻辑比表面看起来更苛刻。
为什么 SELECT SLEEP(5) 都不进日志?先确认三重开关是否全开
MySQL 对慢查询的判定是「开关 + 输出路径 + 阈值」三级联动,缺一不可:
-
slow_query_log = ON:总开关,必须是字符串'ON'(不是1或TRUE),SHOW VARIABLES LIKE 'slow_query_log'返回值必须是ON -
log_output = 'FILE'(或'TABLE'):默认是'NONE',设成'FILE'才会写入slow_query_log_file文件 -
long_query_time是浮点数,且只对新建立的连接生效;当前会话仍用旧值,需执行SELECT @@long_query_time确认实际生效值
long_query_time 判定发生在哪一刻?不包含锁等待时间
MySQL 实际用 my_micro_time() 记录语句开始时间,再与执行结束时间比对。但关键点在于:这个“执行结束时间”不包含锁等待耗时。比如:
- 一条
UPDATE语句本身逻辑只花 20ms,但因行锁被其他事务占着,排队等了 800ms 才真正执行 - 最终耗时显示为 820ms,但 MySQL 只把那 20ms 算进
long_query_time判定 - 若
long_query_time = 0.1(100ms),它就不会被记入慢日志
这种现象在高并发更新场景极常见,查 information_schema.processlist 能看到 State = 'Locked' 或 'Waiting for table metadata lock',但慢日志里完全消失。
哪些 SQL 天然逃过 long_query_time 判定?管理语句、未走索引、低扫描行数
即使执行时间远超阈值,以下几类语句默认不会触发慢日志记录:
-
log_slow_admin_statements = OFF(默认):ALTER TABLE、ANALYZE TABLE、OPTIMIZE TABLE等管理命令,哪怕跑 5 分钟也不记 -
log_queries_not_using_indexes = OFF(默认):未命中索引的查询,无论多慢都不进日志;开启后还要注意log_throttle_queries_not_using_indexes限制每分钟最多记录多少条 -
min_examined_row_limit > 0(如设为 1000):即使查询耗时达标,但EXPLAIN显示rows_examined ,照样跳过记录
最易忽略的精度陷阱:long_query_time = 0.1 不等于“≥100ms 就记”
MySQL 内部使用微秒级计时,但判定逻辑是「严格小于」而非「四舍五入」或「向上取整」:
- 设
long_query_time = 0.1,一条真实耗时0.099999秒(即 99999 微秒)的查询,不会被记录 - 它差的不是毫秒,是 1 微秒;而网络延迟、上下文切换、CPU 调度都可能吃掉这 1 微秒
- 生产环境建议设为
0.099或0.09,留出安全余量;测试时可用SLEEP(0.11)验证是否真能捕获
真正难调试的,往往不是配置没开,而是你以为它该进日志的那条 SQL,在 MySQL 执行引擎眼里,压根没达到那个“慢”的定义边界。











