答案是:通过performance_schema.threads查活跃线程是定位高cpu sql的起点,需结合events_statements_summary_by_thread_by_event_name和os层ps/top交叉验证,区分真实cpu密集型与锁争用等伪高cpu场景。

查 performance_schema.threads 找活跃线程
Performance Schema 默认开启(MySQL 5.6+),但部分线程(如后台线程、复制IO/SQL线程)可能被过滤掉,threads 表是起点。先确认哪些线程当前处于活跃状态:
SELECT thread_id, name, type, processlist_id, processlist_user, processlist_host, processlist_db, PROCESSLIST_INFO FROM performance_schema.threads WHERE THREAD_ID IN (SELECT THREAD_ID FROM performance_schema.events_statements_current WHERE SQL_TEXT IS NOT NULL) ORDER BY PROCESSLIST_TIME DESC LIMIT 10;-
processlist_id对应SHOW PROCESSLIST中的 ID,可交叉验证;PROCESSLIST_INFO是当前执行的 SQL(注意:只保留最近一条,且可能被截断) - 若
PROCESSLIST_INFO为空,不代表没在跑——可能是 sleep 状态、或正在执行非 SQL 操作(如排序、磁盘 I/O 等),需结合其他表判断
用 events_statements_summary_by_thread_by_event_name 看 CPU 消耗大户
单条 SQL 的执行时间(TIMER_WAIT)不等于 CPU 时间,但高 SUM_TIMER_WAIT 通常伴随高 CPU 占用,尤其当 COUNT_STAR 高 + AVG_TIMER_WAIT 不低时:
SELECT thread_id, SUM_TIMER_WAIT, COUNT_STAR, AVG_TIMER_WAIT, SUM_ROWS_AFFECTED FROM performance_schema.events_statements_summary_by_thread_by_event_name WHERE EVENT_NAME = 'statement/sql/select' AND SUM_TIMER_WAIT > 1000000000000 ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;- 把
EVENT_NAME换成'statement/sql/update'或'statement/sql/insert'可排查写操作 - 注意单位:
TIMER_WAIT是皮秒(ps),1e12 ps = 1 秒;SUM_TIMER_WAIT > 1e12表示该线程 SQL 累计执行超 1 秒,值得深挖 - 如果某线程
COUNT_STAR极高但AVG_TIMER_WAIT很低,可能是高频小查询(如心跳检测),未必是 CPU 元凶,得看events_waits_summary_by_thread_by_event_name
结合 events_waits_summary_by_thread_by_event_name 判断是否卡在等待
真正吃 CPU 的线程,往往 wait 类事件占比低;而大量 wait/io/file 或 wait/synch/mutex 表明它在等资源,CPU 可能并不高——别被表象误导:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
SELECT thread_id, EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT FROM performance_schema.events_waits_summary_by_thread_by_event_name WHERE thread_id = 123 AND COUNT_STAR > 100 ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;(替换123为可疑 thread_id) - 重点看
wait/synch/mutex/innodb/类事件:若SUM_TIMER_WAIT高,说明线程在争抢锁,可能引发 CPU 空转(自旋) -
wait/io/file/innodb/innodb_data_file高 → 磁盘 I/O 瓶颈,CPU 可能不高;wait/cpu/cpu在 MySQL 中并不存在,CPU 使用本身不走 wait 表,所以「CPU 高」必须通过events_statements_*+ 实际 top 输出交叉印证
导出线程栈并关联 OS 层进程
Performance Schema 不提供线程栈或 CPU 使用率百分比,最终确认必须落到 OS 层:
- 从
threads表拿到thread_id,再查SELECT * FROM performance_schema.threads WHERE thread_id = 123;,记下PROCESSLIST_ID - 在 Linux 上运行
mysqladmin -u root -p processlist或SHOW FULL PROCESSLIST;,找到对应Id的State和Info - 用
ps -T -p $(pgrep mysqld) -o pid,tid,%cpu,comm,args | grep -E "(^ *[0-9]+ +123|$(cat /proc/$(pgrep mysqld)/task/*/status 2>/dev/null | grep -B1 'Tgid:.*' | grep -A1 'Tgid' | awk '{print $2}' | head -1))"(实际建议简化:先ps -eL o pid,lwp,comm,%cpu | grep mysqld,再按 LWP 匹配thread_id) - 关键点:
performance_schema.threads.THREAD_ID≠ OS 级线程 ID(LWP),但 MySQL 5.7+ 中THREAD_ID与/proc/<pid>/task/<tid>/status</tid></pid>中的Tid一致(需确认mysqld进程 PID)
真正难的不是查哪条 SQL 慢,而是区分「CPU 密集型」和「伪高 CPU(比如大量 mutex 自旋、或频繁上下文切换导致的调度开销)」——这两类在线程栈里表现完全不同,但 Performance Schema 本身不暴露栈帧。










