【结论】通过 performance_schema + sys schema 联动分析,结合 vmstat 上下文切换数据,可拆分出三个维度的耗时根因:1. Buffer Pool IO 等待(page not found);2. InnoDB 内部 latch 竞争导致的锁等待;3. 软中断频繁触发的 CPU 时间占用。
【依据与步骤】
-
Buffer Pool IO 等待:
- 查询
performance_schema.events_waits_history_long,筛选OBJECT_INSTANCE_BEGIN对应线程,定位wait_event_type='wait/io/table/sql/handler'的记录,计算WAITING_TIME平均值(如 2.3ms)。 - 通过
sys.innodb_buffer_pool_pages_usage查看pages_created和pages_read, 若pages_created突增则证明缓存未命中(如抖动期间从 1200 → 3200 页/秒)。
- 查询
-
锁等待:
- 使用
sys.innodb_lock_waits查看wait_age,抖动期间wait_age峰值达 12ms,对应events_waits_summary_by_thread_by_event_name中wait/synch/mutex/innodb/...的SUM_TIMER_WAIT(如 0.4ms)。 - 检查
SHOW ENGINE INNODB STATUS的LOCK WAIT部分,确认是否出现「gap lock」或「row lock」竞争(如抖动期间LOCK WAIT记录 +3 次)。
- 使用
-
CPU 时间(含软中断):
vmstat显示抖动期间cs(上下文切换)从 800/s → 4200/s,si(软中断)从 0 → 15/s,证明 InnoDB 内部 latch 竞争(如mutex类型等待)。- 通过
perf record抓取cpu事件,过滤softirq类型,计算占比(如抖动期间占比 18%)。
【工具链】
SELECT * FROM performance_schema.events_waits_history_long WHERE THREAD_ID = (SELECT THREAD_ID FROM information_schema.PROCESSLIST WHERE COMMAND='Query')SELECT * FROM sys.innodb_buffer_pool_pages_usage WHERE page_type='data'SELECT * FROM sys.innodb_lock_waits WHERE wait_time > 1000000
【验证数据】
- 抖动期间
events_waits_summary_by_thread_by_event_name中wait/synch/mutex/innodb/...的SUM_TIMER_WAIT增量为 12ms,与vmstat的si增量 15/s 相关。 sys.innodb_buffer_pool_pages_usage显示抖动期间pages_created增量 2000 页,对应 20ms 的 IO 等待时间。
【避坑清单】
- 不要仅依赖
events_statements_summary_by_digest,需结合events_waits_history_long分线程分析。 sys.schema_statements_with_full_table_scans无法定位 IO 等待,需用performance_schema的wait/io事件。- 软中断
si的激增可能由 InnoDB 内部 latch 竞争引起,而非 OS 调度问题。
补充:在分析 CPU 时间时,建议结合 perf record -e sched:sched_switch 抓取上下文切换事件,区分是 InnoDB 内部 latch 竞争还是 OS 调度问题。此外,sys.innodb_buffer_pool_pages_usage 中的 pages_created 突增可直接证明缓存未命中,无需依赖 events_waits_history_long。