最快查INFORMATION_SCHEMA.PROCESSLIST仅见运行中存储过程;定位资源消耗须用performance_schema:先SHOW FULL PROCESSLIST找Execute状态含CALL的语句,再查events_statements_current确认CALL调用,继而用events_statements_history_long分析内部SQL耗时与扫描行数,辅以sys视图看内存和I/O。

直接查 INFORMATION_SCHEMA.PROCESSLIST 最快,但只能看到“正在执行”且没结束的存储过程;真要定位资源消耗大户,必须依赖 performance_schema,否则你看到的只是表层现象。
查当前卡住的 CALL 语句(SHOW PROCESSLIST 级)
这是第一反应动作,适合快速人工干预:
-
SHOW FULL PROCESSLIST中找Command为Execute、State非Sleep且Info包含CALL的行 - 重点关注
Time字段:超过 30 秒就该怀疑,60 秒以上基本可 kill - 注意
Id值——这是后续KILL QUERY Id的依据,不是KILL Id(后者会断开整个连接) - 如果
Info显示为NULL,说明语句已执行完或被截断,此时PROCESSLIST已无价值,得切到performance_schema
用 events_statements_current 抓实时 CALL 入口
它比 PROCESSLIST 多一层上下文:能确认是不是真的在调用存储过程,而不是某条普通 SQL 恰好含 CALL 字符串:
- 执行:
SELECT THREAD_ID, EVENT_NAME, SQL_TEXT, TIMER_WAIT/1000000000000 AS sec FROM performance_schema.events_statements_current WHERE EVENT_NAME = 'statement/sql/call' -
EVENT_NAME = 'statement/sql/call'是关键过滤条件,排除掉所有非 CALL 的语句 -
TIMER_WAIT单位是皮秒,不除以1000000000000你会看到一串十几位数字,毫无可读性 - 若返回空,说明该 CALL 已完成,或
setup_instruments里没启用statement/sql/call(需运行:UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'statement/sql/call';)
顺着线程 ID 查它内部干了什么(events_statements_history_long)
CALL 本身不耗资源,真正吃 CPU、刷磁盘的是它里面跑的 SELECT/INSERT/LOOP。这一步才能暴露根因:
- 拿到上一步的
THREAD_ID,查:SELECT EVENT_ID, SQL_TEXT, TIMER_WAIT/1000000000000 AS sec, ROWS_EXAMINED, ROWS_SENT FROM performance_schema.events_statements_history_long WHERE THREAD_ID = 12345 ORDER BY EVENT_ID DESC LIMIT 20; - 重点看
ROWS_EXAMINED是否远大于ROWS_SENT——这是隐式临时表或全表扫描的典型信号 - 如果
SQL_TEXT显示大量重复的相同语句(比如游标循环里反复查同一张表),说明逻辑设计有问题,不是 SQL 写得慢,而是调用频次太高 - 注意:默认
events_statements_history_long只存最近 1000 条,高并发下容易被覆盖,建议提前设大:SET GLOBAL performance_schema_events_statements_history_long_size = 5000;
别漏掉内存和 I/O(sys 视图辅助判断)
sys 不是银弹,但它把 performance_schema 的原始数据做了聚合,对排查“为什么慢”更直观:
- 查哪个线程吃内存最多:
SELECT user, current_allocated, current_statement FROM sys.memory_by_thread_by_current_bytes WHERE current_statement LIKE 'CALL%'; - 查哪个 CALL 引发最多磁盘读:
SELECT * FROM sys.io_by_thread_by_bytes WHERE thread LIKE '%CALL%' ORDER BY total DESC LIMIT 3; - 如果这两条都返回空,大概率是
memory/%类 instrument 没开(需:UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'memory/%';),或者线程已经退出 -
sys视图依赖performance_schema,如果SELECT @@performance_schema返回OFF,所有sys查询都会为空
最常被忽略的一点:你看到的 CALL my_proc() 耗时高,90% 情况下问题不在存储过程定义体里,而在它调用时传入的参数触发了低效执行路径——比如一个本该走索引的 WHERE id = ?,因为参数是 NULL 导致优化器放弃索引。所以盯住 events_statements_history_long 里的实际 SQL,比盯 CALL 本身重要得多。


















