需先执行show variables like 'slow_query_log'确认值为on,再检查slow_query_log_file路径权限;long_query_time建议线上从1.0秒起步,支持微秒精度但旧版本向下取整;慢日志不记录纯写操作,需结合performance_schema定位真实瓶颈。

如何确认慢查询日志是否真正开启
MySQL 的慢查询日志不是默认开启的,哪怕你改了 long_query_time,slow_query_log 这个开关没打开,日志压根不会写。常见错误是只改了时间阈值,结果查了半天 slow_query_log_file 路径下空空如也。
实操建议:
- 先执行
SHOW VARIABLES LIKE 'slow_query_log';,确认值是ON(不是1或TRUE) - 再检查
SHOW VARIABLES LIKE 'slow_query_log_file';,确保路径可写,且 MySQL 进程有权限(比如 SELinux 或 AppArmor 可能拦截) - 注意:动态设置
SET GLOBAL slow_query_log = ON;仅对新连接生效,已存在的连接不触发日志
long_query_time 设多少才合理
long_query_time 不是越小越好,设成 0 看似“全量捕获”,但会把所有查询都记进来,日志爆炸、IO 压力陡增,反而掩盖真问题。它本质是性能基线标尺,不是调试开关。
实操建议:
- 线上建议从
1.0开始(秒级),观察一周后看日志量和业务响应体感;若关键接口 RT 普遍在 300ms,可尝试调到0.3 - 注意:该参数支持微秒精度(如
0.15),但 MySQL 5.7+ 才真正按微秒截断;旧版本会向下取整到秒 -
long_query_time是会话级变量,如果用SET SESSION long_query_time = 0.1;测试某条 SQL,记得及时恢复,否则可能误伤其他查询逻辑
分析 slow log 文件时别被“假慢”骗了
日志里看到某条 SELECT 耗时 2.4s,不等于 SQL 本身慢——可能是锁等待、磁盘 IO 阻塞、或被 FLUSH TABLES WITH READ LOCK 卡住。慢日志只记录“执行完成耗时”,不区分 CPU 时间和等待时间。
实操建议:
- 重点看日志中是否带
# Query_time:后紧跟# Lock_time:,如果Lock_time接近总耗时,优先查锁(用SHOW ENGINE INNODB STATUS) - 用
mysqldumpslow -s t -t 10 /var/lib/mysql/slow.log快速聚合 TOP 耗时 SQL,但注意它默认忽略WHERE中的具体值,可能把不同参数的同模板 SQL 合并统计 - 避免直接用
cat或grep查日志:二进制日志格式(如启用了log_output = TABLE)会导致文本工具解析失败;确认log_output是FILE再操作
为什么开了 slow log 还看不到 INSERT/UPDATE 的慢记录
默认情况下,MySQL 只记录查询语句(SELECT),不记录写操作。很多业务的瓶颈其实在大事务提交或索引更新上,但日志里干干净净。
实操建议:
- 加上配置
log_queries_not_using_indexes = ON,它会让没走索引的INSERT ... SELECT、UPDATE等也被记录(但普通单行INSERT仍不录) - 真正想抓写入慢操作,得靠
performance_schema:启用events_statements_history_long表,结合TIMER_WAIT字段过滤,比慢日志更准但开销略高 - 注意:5.6 版本起,
long_query_time对写语句生效的前提是开启了log_slow_admin_statements(针对OPTIMIZE、ANALYZE等),但它不覆盖普通 DML
慢查询日志最常被低估的,是它的采样粒度和上下文缺失——它不告诉你执行计划变了没、是否走了预编译缓存、有没有被 query cache 干扰。真要定位,得配合 EXPLAIN FORMAT=JSON 和 performance_schema.events_statements_summary_by_digest 交叉验证。











