不能靠 processlist 判断存储过程是否在执行,因其不标记过程级状态,仅显示当前线程执行的sql语句(可能是call或过程内语句),且call调用后即被覆盖;应结合模糊匹配info、运行时长及标记表埋点定位。

information_schema.PROCESSLIST 不包含存储过程是否“正在运行”的直接标识——它只记录当前活跃连接线程的 SQL 执行状态,而存储过程本身不是独立线程,其内部语句会以普通 Query 命令形式出现在 PROCESSLIST 中。
为什么不能靠 PROCESSLIST 判断存储过程是否在执行
MySQL 存储过程调用后,实际执行的是其中封装的 SQL 语句,整个调用生命周期绑定在发起连接的线程上。该线程在 PROCESSLIST 中的 Command 列始终显示为 Query,Info 列显示的是当前正在执行的那条语句(可能是 CALL proc_name(),也可能是过程体内的某条 SELECT 或 UPDATE),不会标记“正在执行存储过程”。
-
CALL proc_name()出现在Info中,只说明调用刚发起,不代表过程还在跑;一旦进入过程体,这条CALL就被覆盖了 - 如果过程里有长耗时语句(如大表 JOIN),你看到的是那条
SELECT,而非proc_name -
State列(如Sending data、Locked)反映的是底层操作,和存储过程逻辑无关
想确认某个存储过程是否“当前正被调用并卡住”,该查什么
真正有用的是组合过滤:定位到可能正在执行该过程的连接,并检查其 SQL 内容与运行时长。
- 用
SHOW FULL PROCESSLIST或查询information_schema.PROCESSLIST,重点筛选:Command = 'Query'且Time > 30(按需调整阈值) - 对
Info列做模糊匹配:Info LIKE '%CALL%proc_name%'或Info LIKE '%proc_name%'(注意截断风险,FULL版本更可靠) - 若过程内有明显特征 SQL(如固定注释
/* in_proc_age */),可在Info中搜这个标记 - 结合
Host和User缩小范围,避免误判其他应用的同名调用
更可靠的替代方案:加日志或标记表
MySQL 本身不提供“过程级运行状态追踪”,生产环境需要主动埋点:
- 在存储过程开头插入一条记录到标记表:
INSERT INTO proc_runtime_log (proc_name, start_time, conn_id) VALUES ('proc_age', NOW(), CONNECTION_ID()); - 结尾或异常处理块中更新或删除该记录
- 查过程是否“还在跑”,就查这张表里未结束的记录:
SELECT * FROM proc_runtime_log WHERE proc_name = 'proc_age' AND end_time IS NULL; - 注意:标记表要用
ENGINE=InnoDB并加索引,避免自身成瓶颈
真正难的不是查状态,而是区分“过程刚启动”和“过程卡在某步”。靠 PROCESSLIST 只能辅助定位可疑线程,最终得结合过程逻辑、执行计划和外部监控来判断。











