查不到 events_statements_current 数据,先确认 performance_schema 是否启用且相关 consumer 和 instruments 已开启;历史语句需查 events_statements_history_long 并注意其 LRU 清理机制;digest 聚合受标准化规则影响,IN 列表等动态内容会导致大量不同 digest;监控开销明显时应关闭非必要 instruments 和 consumers。

查不到 events_statements_current 数据?先确认 performance_schema 是否启用
MySQL 默认可能没开 performance_schema,或者开了但关键消费者被关了。没开就什么都看不到,不是 SQL 写错,是底子没搭好。
-
performance_schema必须在启动时启用(my.cnf里设performance_schema=ON),运行中不能动态打开 - 即使启用了,
events_statements_current默认不记录——要手动打开对应 consumer:UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME = 'events_statements_current';
- 别只改 consumer,还得检查 instruments:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' WHERE NAME LIKE 'statement/%';
- 改完要等新连接或新语句触发,旧会话不会补录
想看某条慢 SQL 的完整执行链?用 events_statements_history_long 配合线程 ID
events_statements_current 只存每个线程最新一条,历史细节得靠 events_statements_history_long,但它默认容量小(10000 行),且按 LRU 清理,不加过滤容易漏掉目标语句。
- 先从
threads表找到目标连接的THREAD_ID:SELECT THREAD_ID, PROCESSLIST_ID, PROCESSLIST_INFO FROM performance_schema.threads WHERE PROCESSLIST_INFO LIKE '%SELECT%order%';
- 再用该
THREAD_ID查历史:SELECT SQL_TEXT, TIMER_WAIT, LOCK_TIME, ROWS_SENT, ROWS_EXAMINED FROM performance_schema.events_statements_history_long WHERE THREAD_ID = 123 ORDER BY EVENT_ID DESC LIMIT 5;
-
TIMER_WAIT单位是皮秒,除以 10^12 得秒;LOCK_TIME是锁等待耗时,和TIMER_WAIT不是简单相加关系 - 如果查不到,大概率是
events_statements_history_long已满被覆盖,可临时调大:SET GLOBAL performance_schema_events_statements_history_long_size = 100000;(重启失效)
events_statements_summary_by_digest 聚合不准?注意 digest 生成规则和大小写敏感
这个表按 SQL “指纹”聚合,但指纹不是简单去空格,而是标准化后哈希。同逻辑不同写法的语句可能分到不同 digest,导致你以为漏统计了。
- 变量名、注释、空格、换行、大小写全被抹平,但字面量(如
WHERE id = 123和WHERE id = 456)会被替换成?,所以这两条算同一个 digest - 但
WHERE id = ?和WHERE status = ?因列名不同,digest 不同——列名不被参数化 - 如果应用用 ORM 拼 SQL(比如
SELECT * FROM t WHERE id IN (1,2,3)),每次 IN 列表长度/值不同,就会产生大量不同 digest,表里行数暴涨,反而难定位热点 - 查 digest 文本用
sys.schema_table_statistics_with_buffer视图更直观,或直接联查performance_schema.digests(8.0.26+)
开启监控后性能掉明显?关掉不需要的 instruments 和 consumers
performance_schema 不是零成本,尤其 statement/sql/* 类 instruments 开着,每条语句都走额外钩子,QPS 高时 CPU 上升 5–15% 很常见。
- 生产环境别全开:
UPDATE performance_schema.setup_instruments SET ENABLED = 'NO' WHERE NAME NOT LIKE 'statement/sql/%' AND NAME NOT LIKE 'statement/com/%'; - 关掉不用的 consumer,比如
events_waits_current或events_stages_current,除非你真在查锁或阶段耗时 - 如果只关心慢 SQL,优先开
events_statements_history_long+ 对应 instruments,其他 history 表可以关 - 监控粒度够用就行:把
TIMED设为NO可省下计时开销,但会丢掉TIMER_WAIT等字段——多数时候你要的就是它
真正麻烦的是多层嵌套调用下的 digest 归因,比如存储过程里拼的动态 SQL,digest 会把整个 CALL 语句当主体,看不出里面那条 SELECT 到底慢在哪。这时候得结合 events_statements_history_long 手动翻线程上下文,没法全自动。











