开启MySQL慢查询日志需设slow_query_log=ON、long_query_time≥1.0、log_queries_not_using_indexes=OFF,日志路径独立,8.0+启用log_slow_extra;用pt-query-digest加过滤分析,重点关注高均值高频次查询及Rows_examined激增;结合Prometheus监控表级扫描行数与业务状态告警。

MySQL慢查询日志怎么开,又不拖垮线上性能
慢查询日志是监控关键表最直接的入口,但默认关闭,且开错参数会吃光磁盘IO或撑爆磁盘空间。
-
slow_query_log必须设为ON,但仅此不够;long_query_time建议从1.0开始调,别一上来就设0.1—— 高频小表查询全打进来,日志量翻10倍不止 -
log_queries_not_using_indexes先关掉,除非你真在做索引治理;它会把没走索引的SELECT全记下,连SHOW TABLES都可能被录 - 日志路径用
slow_query_log_file指向独立磁盘(比如/data/mysql-slow.log),别和datadir混一起;否则慢查暴增时,可能卡住整个实例的刷盘 - MySQL 8.0+ 可配
log_slow_extra,能多记query_plan和user_host,排查谁查了orders表超时特别有用
用pt-query-digest分析慢日志,避开常见误读
原生日志没法直接看出哪张表被拖慢,pt-query-digest 是事实标准工具,但很多人跑完只看“最慢那条”,漏掉真正要命的“平均慢但频次极高”的查询。
- 执行命令别只写
pt-query-digest /var/log/mysql-slow.log,加--filter '$event->{db} && $event->{db} =~ m/^prod_/i'过滤库名,避免测试库噪音干扰 - 重点盯
Rank列里# Query 2这类——它代表“平均响应时间高 + 执行次数多”的组合,比# Query 1(单次极慢但一年才跑一次)危险得多 - 输出里的
Rows_examined比Rows_sent更关键:如果前者是后者的百倍,说明WHERE条件没走对索引,正在扫全表查user_profiles - 别信
pt-query-digest --report默认的“最慢TOP10”,加--limit 50%看累计占比,常发现前3条就占了慢查总耗时的68%
用Prometheus+mysqld_exporter配阈值告警,不是只看QPS
只监控 Queries 或 Threads_running 容易误报;关键表的异常必须绑定具体SQL特征和资源消耗。
-
mysqld_exporter默认不暴露慢查询明细,得打开--collect.global_status --collect.info_schema.innodb_tablespaces,才能拿到mysql_global_status_slow_queries和mysql_info_schema_innodb_table_rows - Prometheus告警规则别只写
rate(mysql_global_status_slow_queries[5m]) > 10,要结合表级指标:比如rate(mysql_info_schema_innodb_table_rows{table="orders"}[5m]) > 1e6意味着这表最近5分钟被扫了超百万行,大概率出事了 - 告警阈值按业务节奏设:凌晨批量作业期间,
slow_query_time可临时放宽到5.0;但白天交易时段必须压回0.8,这个切换靠prometheus-rule的time() >= 07:00 && time() 控制 - 推送通知里必须带上下文:Alertmanager的
annotations至少填query_sample(从pt-query-digest --review导出的样本SQL)和affected_table(正则从SQL里提取FROM orders|JOIN payments)
为什么ALTER TABLE没报警,但业务却卡死了
DDL操作不进慢查询日志,pt-query-digest 看不到,Prometheus也抓不到——这是监控盲区里最常出事的点。
- MySQL 5.7+ 要开
performance_schema,并启用events_statements_history_long和events_waits_history_long,才能捕获ALTER TABLE orders ENGINE=InnoDB这类长事务等待 - 查阻塞用
SELECT * FROM performance_schema.events_statements_history_long WHERE SQL_TEXT LIKE '%ALTER%TABLE%orders%',配合timer_wait字段看耗时 - 更实用的是监控
information_schema.INNODB_TRX:当TRX_STATE = 'RUNNING'且TRX_STARTED超过300秒,再查TRX_QUERY,90%是DDL或大事务没提交 - 别依赖
SHOW PROCESSLIST,它只显示当前连接;而performance_schema能回溯过去15分钟的完整执行链,包括被锁住的SELECT是被哪个ALTER拖住的
监控关键表真正的难点不在配置,而在区分“技术指标异常”和“业务影响发生”。比如 slow_query_time 没超阈值,但某条查 inventory 的SQL在库存归零时突然变慢10倍——这种场景必须把业务状态(如 stock_quantity = 0)作为告警条件之一,而不是只盯着数据库自身指标。











