events_waits_summary_global_by_event_name表用于全局汇总各类等待事件,通过sum_timer_wait排序可快速定位i/o、锁、互斥锁等资源瓶颈;其数据不含sql执行cpu时间,需结合events_statements_summary_by_digest等表综合分析。

查 events_waits_summary_global_by_event_name 快速识别等待热点
大部分性能问题不是 SQL 慢,而是卡在某类资源等待上。直接看这个表,能一眼看出系统把时间花在哪了。
执行:SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT FROM performance_schema.events_waits_summary_global_by_event_name ORDER BY SUM_TIMER_WAIT DESC LIMIT 10;
-
wait/io/file/innodb/innodb_data_file长期排前三?说明 I/O 是瓶颈,重点查磁盘延迟、innodb_io_capacity是否合理 -
wait/synch/mutex/innodb/buf_pool_mutex持续高位?InnoDB 缓冲池争用严重,可能是并发高但innodb_buffer_pool_instances设太小 -
wait/lock/metadata/sql/mdl突然飙升?DDL 操作(如加索引)阻塞了大量查询,得立刻查information_schema.PROCESSLIST找肇事语句
注意:这个表只统计“等待时间”,不包括 SQL 执行本身的 CPU 时间。所以即使 SUM_TIMER_WAIT 为 0,也不代表没瓶颈——可能纯 CPU 密集型计算压垮了线程。
用 events_statements_summary_by_digest 找“高频低耗”隐形杀手
慢查询日志漏掉的往往是最伤数据库的 SQL:执行快(
执行:SELECT digest_text AS query, COUNT_STAR, SUM_ROWS_EXAMINED, AVG_TIMER_WAIT FROM performance_schema.events_statements_summary_by_digest WHERE COUNT_STAR > 1000 ORDER BY SUM_ROWS_EXAMINED DESC LIMIT 5;
- 如果
COUNT_STAR过万,SUM_ROWS_EXAMINED却只有几千——大概率是缓存友好型查询,先别急着优化 - 如果
COUNT_STAR2000+,SUM_ROWS_EXAMINED却超百万,且digest_text含SELECT ... FROM user WHERE status = ?这类简单条件——立刻检查status列有没有索引 -
AVG_TIMER_WAIT低于 10000000000(10ms)但COUNT_STAR异常高,结合sys.format_time(SUM_LOCK_TIME)看锁等待占比,判断是否受事务隔离级别拖累
关联 data_lock_waits 和 events_statements_current 定位阻塞源头
知道某条 SQL 在等锁没用,得立刻知道它被谁锁、为什么锁。这两张表必须连查。
执行:SELECT r.sql_text AS waiting_sql, b.sql_text AS blocking_sql, lw.BLOCKING_ENGINE_TRANSACTION_ID FROM performance_schema.data_lock_waits lw JOIN performance_schema.events_statements_current r ON lw.WAITING_ENGINE_TRANSACTION_ID = r.THREAD_ID JOIN performance_schema.events_statements_current b ON lw.BLOCKING_ENGINE_TRANSACTION_ID = b.THREAD_ID;
- 结果为空?说明不是锁等待,转向查 I/O 或 CPU 使用率
-
waiting_sql是UPDATE order SET status = ? WHERE id = ?,blocking_sql是SELECT ... FOR UPDATE——基本确认是长事务未提交,查INFORMATION_SCHEMA.INNODB_TRX中TRX_STARTED时间最早的那几个 -
blocking_sql为NULL?说明阻塞方已退出但锁未释放(极少见),需重启或 kill 对应线程 ID(从lw.BLOCKING_ENGINE_THREAD_ID取)
查 memory_summary_global_by_event_name 看内存是否“悄悄涨”
内存泄漏不一定会立刻 OOM,但 HIGH_NUMBER_OF_BYTES_USED 持续单向上涨就是危险信号。这个值比当前使用量更关键。
执行:SELECT EVENT_NAME, CURRENT_NUMBER_OF_BYTES_USED, HIGH_NUMBER_OF_BYTES_USED FROM performance_schema.memory_summary_global_by_event_name WHERE HIGH_NUMBER_OF_BYTES_USED > 1024*1024*100 ORDER BY HIGH_NUMBER_OF_BYTES_USED DESC LIMIT 5;
-
memory/temptable/allocator占比最高?立刻检查tmp_table_size和max_heap_table_size,别设成 2G——大结果集强制落盘比内存爆炸更可控 -
memory/sql/thd条目数等于Threads_connected?说明连接池空闲连接太多,每个线程都带着sort_buffer_size等 buffer 占着 RSS -
memory/innodb/mem0mem高位不回落?结合SHOW ENGINE INNODB STATUS的SEMAPHORES区块,看spin waits或os waits是否异常多
真正容易被忽略的是:所有这些表的数据只对新连接生效。改完 setup_instruments 后,老连接仍不会上报内存或语句事件——必须让应用重建连接,或重启 MySQL(生产环境慎选)。











