<p>用SELECT * FROM information_schema.PROCESSLIST WHERE TIME > 30 ORDER BY TIME DESC快速定位超30秒查询,注意需PROCESS权限、TIME非SQL执行耗时、Sleep连接可能为应用未关闭,结合performance_schema.events_statements_current和慢日志综合分析。</p>

SHOW PROCESSLIST 返回了太多行,怎么快速定位运行超 30 秒的查询
默认 SHOW PROCESSLIST 只显示当前用户会话,且不按执行时间排序,容易漏掉真正在拖慢数据库的长查询。关键不是“看到”,而是“筛出”。
- 用
SELECT * FROM information_schema.PROCESSLIST WHERE TIME > 30 ORDER BY TIME DESC替代原命令,TIME字段单位是秒,直接过滤更准 -
information_schema.PROCESSLIST需要PROCESS权限,普通应用账号通常没有,得用 DBA 账号或配置了对应权限的监控账号 - 注意
TIME是该线程持续空闲或执行的时间,并非 SQL 执行耗时本身;对State = "Sending data"或"Copying to tmp table"的长时间条目要优先关注
为什么 root 用户也看不到某些连接,比如已断开但未清理的 Sleep 连接
SHOW PROCESSLIST 默认只显示当前用户发起的连接;即使你是 root,也受 MySQL 8.0+ 的 show_processlist_priv 实际生效范围影响——有些连接可能被隐藏,尤其是由系统线程、复制 IO/SQL 线程或使用 mysqlx 协议建立的连接。
- 加
WITH FULL(MySQL 5.7+)可显示完整Info字段内容,避免被截断导致看不出真实 SQL:SHOW FULL PROCESSLIST - MySQL 8.0 起,
performance_schema.threads更全,能查到所有线程(包括内部线程),但需确认performance_schema已启用且thread_instrumentation开启 - Sleep 状态连接如果
TIME极大(如几万秒),大概率是应用没正确 close,不是数据库卡住,别误判为阻塞源
Kill 掉一个查询后,客户端却没报错,或者报错延迟很高
执行 KILL QUERY [id] 或 KILL [id] 并不等于立即终止:它只是给线程发中断信号,后续行为取决于当前执行阶段和存储引擎。
-
KILL QUERY只中断语句执行,线程保持连接(State可能变init或Waiting for query cache lock);KILL才真正断开连接 - InnoDB 在事务中途被 kill,会触发回滚,而大事务回滚可能比执行还慢——这时你看到
State = "Rolling back",别急着再 kill - 客户端是否立刻感知,取决于其 socket timeout 设置和是否轮询
mysql_ping();很多 ORM 默认不设net_read_timeout,导致“kill 了但还在等”
想自动抓取并记录长查询,但又不想频繁刷 SHOW PROCESSLIST
高频轮询 SHOW PROCESSLIST 本身就会增加 server 负担,尤其在连接数多时。更好的方式是利用已有机制捕获,而非轮询。
- 开启慢查询日志(
slow_query_log = ON),配合long_query_time = 1(单位秒),它记录的是执行完成后的 SQL,适合归档分析,但无法实时干预 - 用
performance_schema.events_statements_current表 + 定时采集(如每 5 秒),筛选TIMER_WAIT > 30000000000(30 秒 = 30e9 纳秒),比轮询 processlist 更轻量 - 注意
performance_schema内存占用可控,但events_statements_history_long若开启且容量小,会覆盖快,建议只开current表用于实时监控
实际排查时,最常被忽略的是:TIME 字段值为 0 的活跃查询(比如刚 start transaction 但还没执行语句),它不会出现在 long_query_time 日志里,也不会被 TIME > 30 捕获,但可能锁住资源——得结合 INFORMATION_SCHEMA.INNODB_TRX 和锁视图一起看。


















