MySQL无SQL调用栈,所谓“堆栈”实为线程当前SQL+状态+阻塞上下文;监控重点是“谁在跑什么、卡在哪、为什么卡”,需结合SHOW FULL PROCESSLIST、INFORMATION_SCHEMA.PROCESSLIST和performance_schema三者分析。

不能直接看到“SQL堆栈”——MySQL没有类似Java或Python的函数调用栈概念,所谓“堆栈”实际是指当前线程正在执行的SQL语句 + 所处状态 + 阻塞上下文。监控重点不是调用链,而是“谁在跑什么、卡在哪、为什么卡”。
SHOW FULL PROCESSLIST 能看到什么、看不到什么
这是最常用也最容易误读的入口。它返回的是连接线程快照,不是实时流式追踪:
-
INFO字段显示的是当前Command = 'Query'状态下正在执行的 SQL;但若 SQL 已执行完、连接还开着,INFO就变为空或NULL,而State可能是Committing或Locked - 默认只显示前 100 行,且截断长 SQL(约 100 字符);必须加
FULL:SHOW FULL PROCESSLIST -
State比INFO更关键:比如Waiting for table metadata lock表示被 DDL 阻塞,Sending data可能正扫大表,Copying to tmp table说明排序/分组撑爆内存 - 权限限制明显:普通用户看不到其他用户的连接,
INFO强制为NULL;需PROCESS权限才能查全量
INFORMATION_SCHEMA.PROCESSLIST 是写脚本的唯一可靠选择
命令行适合人工排查,但自动化监控必须用这个视图——它支持标准 SQL 过滤,字段语义稳定:
- 过滤真正在执行的查询:必须同时满足
COMMAND = 'Query'且STATE NOT IN ('Sleep', 'Init'),不能只看INFO IS NOT NULL -
TIME是当前状态持续秒数,不是 SQL 总耗时;判断“慢”应结合业务阈值,比如TIME > 30而非硬套 60 - 常见误写:
WHERE INFO != ''会漏掉INFO为NULL的阻塞线程;正确写法是INFO IS NOT NULL或干脆不依赖INFO,靠STATE和TIME组合判断 - 该表不包含已被
KILL但尚未退出的残留线程,也不反映已断开的连接
Performance Schema 才能拿到“执行中”的真实 SQL 文本
当 PROCESSLIST 里 INFO 为空,或者你想知道“这条 SQL 到底卡在哪个阶段”,就得切到 performance_schema:
- 确认已启用:
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'performance_schema'返回ON - 查当前活跃语句:
SELECT THREAD_ID, SQL_TEXT, TIMER_WAIT FROM performance_schema.events_statements_current WHERE SQL_TEXT IS NOT NULL - 注意:
SQL_TEXT是完整语句,但可能被截断(由max_digest_length控制,默认 1024 字符);TIMER_WAIT是纳秒级耗时,需除以 10^9 换算成秒 - 相比
PROCESSLIST,它不依赖用户权限,所有线程可见;但开销略高,生产环境建议按需开启相关 consumers
KILL QUERY 和 KILL 的区别必须分清
很多故障源于误杀连接而非中断语句:
-
KILL <code>ID干掉整个连接:事务未提交则回滚,客户端收到Aborted connection日志,应用层可能重连失败 -
KILL QUERY <code>ID只中断当前语句:连接保持,State变为NULL或Sleep,适合 Web 应用等长连接场景 -
ID不是持久标识:MySQL 重启后重置,别存进配置或告警规则里长期引用;每次KILL前务必先查INFORMATION_SCHEMA.PROCESSLIST确认线程状态 - 对
State = 'Locked'或'Waiting for table metadata lock'的线程,KILL QUERY通常无效,得先干掉持锁者(比如正在执行ALTER TABLE的连接)
真正难的不是查到 SQL,而是判断它为什么卡住——INFO 显示的可能是表名,State 揭示的是引擎层行为,performance_schema 给出的是执行路径,三者缺一不可。别只盯着 SQL 文本本身。


















