登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL Performance Schema 按线程聚合等待事件

来源:17golang原创

时间:2026-10-31 23:26:59 306浏览 收藏

排查 MySQL 等待变慢时,单看全局等待事件只能知道“哪类事件累计得多”,很难回答“是哪条连接贡献的”。更实用的入口是 performance_schema.events_waits_summary_by_thread_by_event_name:它按 THREAD_ID 和 EVENT_NAME 聚合,再与 performance_schema.threads 关联,就能把内部线程映射到连接 ID、用户和主机。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/

最小排查链路是:先确认等待采集已开启,再查询线程汇总表,按 SUM_TIMER_WAIT 排序,并通过 PROCESSLIST_ID 区分前台连接;计时字段是 Performance Schema 的皮秒表示,不能直接当作秒读取。

先看懂按线程汇总表记录了什么

MySQL 8.4 把等待事件分成 current、history 和 summary 等不同表。本文使用的汇总表每行代表一个线程和一个事件名组合,核心字段如下:

字段含义排查用途
THREAD_IDPerformance Schema 内部线程标识关联 threads,不要直接当连接 ID
EVENT_NAME等待 instrument 名称区分文件、同步、表 IO 等等待类别
COUNT_STAR汇总事件次数判断频繁等待
SUM_TIMER_WAIT已计时等待的累计时长排序寻找累计影响较大的线程
AVG_TIMER_WAIT已计时等待的平均时长区分高频短等待和低频长等待

官方手册说明,计时值在读取时以皮秒展示,所以查询时应换算成秒或微秒。没有计时的 instrument,其计时列可能为 NULL;不要把这类空值解释为“没有等待”。

MySQL 按线程聚合等待事件的静态关系说明图,展示线程、等待汇总和连接映射
图1:结构说明图,查看 THREAD_ID、等待汇总表与连接线程之间的静态关系;这不是运行截图。

采集项没有打开时,为什么查询不到有用数据

Performance Schema 的等待采集受 instrument 和 consumer 两层配置影响。先用查询确认当前状态,再只打开需要观察的等待类别,避免把所有 instrument 无差别扩大到生产环境。

-- 先确认线程采集、当前等待消费者和目标 instrument 的状态
SELECT NAME, ENABLED
FROM performance_schema.setup_consumers
WHERE NAME IN ('global_instrumentation', 'thread_instrumentation', 'events_waits_current');

-- 只检查 IO 等待 instrument;实际名称应以本机查询结果为准
SELECT NAME, ENABLED, TIMED
FROM performance_schema.setup_instruments
WHERE NAME LIKE 'wait/io/%'
ORDER BY NAME
LIMIT 30;

-- 示例:仅为排查窗口打开线程级等待和计时;结束后按原状态恢复
UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME IN ('global_instrumentation', 'thread_instrumentation', 'events_waits_current');

UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE 'wait/io/%';

这段配置只说明调整方向,不能替代现场权限和负载评估。若目标是历史等待,还要检查对应的 events_waits_history 或 events_waits_history_long consumer;如果只想读取汇总结果,应先确认目标 instrument 已启用并计时。

把 THREAD_ID 映射到具体连接,再按累计等待排序

真正定位连接时,不要把 THREAD_ID 和 PROCESSLIST_ID 混用。threads 表中的 PROCESSLIST_ID 对前台线程对应连接标识;后台线程通常没有可供用户终止的连接 ID。下面的查询只保留前台连接,并把皮秒转换成秒:

-- 只看前台连接,按累计等待从高到低列出排查候选
SELECT
    s.THREAD_ID,
    t.PROCESSLIST_ID AS connection_id,
    t.PROCESSLIST_USER AS user_name,
    t.PROCESSLIST_HOST AS client_host,
    s.EVENT_NAME,
    s.COUNT_STAR,
    ROUND(s.SUM_TIMER_WAIT / 1000000000000, 6) AS sum_wait_seconds,
    ROUND(s.AVG_TIMER_WAIT / 1000000000000, 6) AS avg_wait_seconds
FROM performance_schema.events_waits_summary_by_thread_by_event_name AS s
JOIN performance_schema.threads AS t
  ON t.THREAD_ID = s.THREAD_ID
WHERE t.TYPE = 'FOREGROUND'
  AND t.PROCESSLIST_ID IS NOT NULL
  AND s.COUNT_STAR > 0
ORDER BY s.SUM_TIMER_WAIT DESC
LIMIT 20;

结果中的 connection_id 可与进程列表中的连接 ID 对照,EVENT_NAME 再决定下一步是看文件 IO、同步对象、表 IO 还是其他 instrument。这里的排序是“累计等待”的排序,不等于当前仍在等待,也不能单独证明某条 SQL 一定是根因。

MySQL 线程等待排查的静态结构说明图,展示 THREAD_ID 到连接字段和等待指标的关系
图2:结果说明图,展示线程 ID 到连接字段、事件次数与计时指标的静态关系;这不是线上结果截图。

用时间窗口清零,避免把旧累计量当成新故障

汇总表会持续累计,适合看窗口内的趋势,但不适合直接代表“刚刚发生的故障”。开始一次排查前,可以记录当前值;需要完全重开窗口时,按官方允许的方式清零汇总表,然后等待一个固定观察周期再查询:

-- 重新开始一个等待观察窗口;清零前先确认不影响正在进行的诊断
TRUNCATE TABLE performance_schema.events_waits_summary_by_thread_by_event_name;

-- 窗口结束后再次读取,避免把空线程或无事件行列入排序
SELECT THREAD_ID, EVENT_NAME, COUNT_STAR,
       ROUND(SUM_TIMER_WAIT / 1000000000000, 6) AS sum_wait_seconds
FROM performance_schema.events_waits_summary_by_thread_by_event_name
WHERE COUNT_STAR > 0
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 20;

清零只影响 Performance Schema 的内存汇总,不会修改业务表,也不会把它变成持久化历史。需要长期趋势时,应由外部监控按固定间隔读取并保存结果,而不是把一次汇总查询当成完整时间序列。

几个容易误判的边界

  • 看到 THREAD_ID 不等于看到连接:先关联 threads,后台线程的 PROCESSLIST_ID 可能为空。
  • 累计时间不等于墙上时钟:Performance Schema 计时值用于比较和排序,换算秒后仍要结合观察窗口解释。
  • 没有行不一定没有问题:检查 instrument 的 ENABLED、TIMED、thread instrumentation 和对应 consumer。
  • 汇总不是 SQL 根因:找到高等待线程后,还要结合当前语句、锁信息、表 IO 或应用请求链继续定位。

常见问题

为什么按线程汇总表只有少量记录? 可能是等待 instrument 未启用、没有计时,或者线程采集/consumer 没有覆盖目标事件。先查询 setup 表,再扩大观察范围。

为什么用 PROCESSLIST_ID 去查汇总表不生效? 汇总表按 THREAD_ID 聚合,连接 ID 在 threads.PROCESSLIST_ID 中,需要先做一次线程映射。

什么时候应该用 history 表? 要看最近单个事件的时间和对象时用 history;要比较某线程在一个窗口内的累计次数与等待时间时,用按线程 summary 表更直接。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>