需依次检查performance_schema是否启用、语句相关instruments和consumers是否开启;未生效需更新setup_instruments与setup_consumers并重连;实时捕获应优先用events_statements_summary_by_digest加时间过滤,避免直查无索引的history_long表。

如何确认 performance_schema 是否已启用并支持语句监控
MySQL 默认可能未开启完整的语句事件采集,performance_schema 虽常默认启动,但关键的语句表(如 events_statements_history_long、events_statements_current)是否记录,取决于对应消费者(consumer)和仪器(instrument)是否启用。
执行以下检查:
- 确认
performance_schema已启用:SHOW VARIABLES LIKE 'performance_schema';—— 返回ON才有效 - 检查语句相关 instruments 是否开启:
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE 'statement/%' AND ENABLED = 'NO' LIMIT 5;—— 若大量为NO,需手动开启 - 确认 consumers 开启:
SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%statements%' AND ENABLED = 'NO';
若发现关闭项,用 UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'statement/%'; 启用;再更新 setup_consumers 中 events_statements_history_long 和 events_statements_current 为 YES。注意:修改后仅对新连接生效,已有连接不会自动补采。
如何实时捕获高负载时段的慢/高频 SQL
系统负载突增时,往往伴随短时大量执行或单条长耗时语句。靠 slow_query_log 往往滞后且漏掉“快但高频”的语句(如毫秒级但每秒上千次),而 performance_schema 的 events_statements_history_long 是更准的“飞行记录仪”。
推荐查询方式(带时间过滤,避免全表扫):
SELECT DIGEST_TEXT, COUNT_STAR, SUM_TIMER_WAIT, AVG_TIMER_WAIT, FIRST_SEEN, LAST_SEEN FROM performance_schema.events_statements_summary_by_digest WHERE LAST_SEEN > DATE_SUB(NOW(), INTERVAL 5 MINUTE) AND SUM_TIMER_WAIT > 1000000000000 -- 耗时超 1 秒(单位皮秒) ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;
关键点:
-
DIGEST_TEXT是归一化后的语句(如SELECT * FROM users WHERE id = ?),比原始 SQL 更利于聚合分析 -
COUNT_STAR高说明高频调用,SUM_TIMER_WAIT高说明总耗时大,两者都要看 - 直接查
events_statements_history_long效率低且无索引,不建议用于线上实时排查;优先用events_statements_summary_by_digest+ 时间条件 - 该汇总表默认保留 10000 条 digest,若业务 SQL 变种多(如未参数化、含大量字面量),会快速挤占空间,导致旧 digest 被淘汰
为什么开了 performance_schema 还看不到某些 SQL
常见原因不是配置没开,而是语句根本没走到采集点:
- 连接在
performance_schema相关 instruments 启用前就已建立 —— 重启连接或使用KILL后重连 - 语句被优化器在解析前就拒绝(如语法错误、权限不足),不会进入 statement instrument 流程;这类错误只记在
error_log或客户端报错,performance_schema不捕获 - 使用了存储过程或 PREPARE/EXECUTE,其内部语句默认不展开采集,需额外开启
instrumentation for stored programs(设置setup_instruments中sp/%类型) - 客户端使用了 query cache(MySQL 5.7 及以前),缓存命中的查询不执行引擎层,自然不触发 statement 采集 —— 建议关闭 query cache(
query_cache_type=0)以保证监控完整性
验证是否真漏采:临时在测试库执行一条明确的 SELECT SLEEP(2);,再查 events_statements_current 看能否命中,可快速定位是配置问题还是逻辑绕过。
如何安全开启 long history 并避免性能反噬
events_statements_history_long 表虽能查到原始语句文本和绑定变量,但默认大小仅 10000 行,且写入是全局互斥锁,高并发下可能成瓶颈。
调整前务必评估:
- 增大
performance_schema_events_statements_history_long_size(动态变量)会增加内存占用,每行约 2–3KB,设为 100000 就要 200MB+;线上不建议超过 50000 - 该表无索引,
SELECT * FROM events_statements_history_long WHERE ...是全表扫描,只能用于事后离线分析,绝不能放进监控脚本里轮询 - 真正可用的轻量方案是:用
sys.statement_analysis视图(基于events_statements_summary_by_digest)—— 它自带排序、格式化、延迟计算,且不依赖 history_long - 如果必须查原始语句,优先从
events_statements_current查活跃会话,配合processlist中的ID关联,比翻 history_long 更快更准
最易被忽略的一点:很多 DBA 开启了所有 instruments,却忘了关掉 memory/% 或 wait/synch/% 这类高频率仪器,它们产生的数据量远超语句本身,反而拖垮 performance_schema 自身 —— 按需开启,别图省事全开。











