news 2026/10/14 15:58:14

show full processlist实战:MySQL慢查询与锁等待排查指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
show full processlist实战:MySQL慢查询与锁等待排查指南

深夜接到报警,线上一个核心接口的响应时间从平均200毫秒直接飙到了3秒。登录数据库后我二话没说,先执行了show full processlist,很快看到一条update语句在列表里挂了132秒,State列显示Updating。顺着这条线程找到源头,是业务侧给一张大表做了个没走索引的更新,一次扫了几百万行。从发现问题到定位原因,前后不到两分钟。干这行这么多年,show full processlist一直是我排查MySQL问题时的首选动作,没有之一。

这篇文章就围绕show full processlist命令展开,讲清楚它的语法、输出结果每一列的含义、常见State状态背后的原理、真实故障场景里的排查思路,以及我实际使用中踩过的坑。无论你是刚接触MySQL的开发者,还是已经在运维一线摸爬滚打的DBA,用好这个命令,等于在数据库出问题时比别人多了一双眼睛。

1. show full processlist 是什么:一条命令看穿数据库正在干什么

1.1 它能定位的几类典型问题

show full processlist的作用,是查看当前MySQL中所有客户端连接的线程实时状态。每个连接在MySQL内部都对应一个线程,线程执行SQL时会经历多个阶段,这个命令就是把这些线程的快照直接摆在你面前。你可以把它类比成 Linux 里的ps -ef,ps看进程,show full processlist看数据库线程。

我平时用它主要解决这么几类问题:

  • 有没有SQL正在长时间执行,执行的是什么内容
  • 当前数据库有多少连接,这些连接来自哪里,都在干什么
  • 有没有连接卡在锁等待、元数据锁(metadata lock)这类状态上
  • 某个连接是不是空转了很长时间,导致连接池资源被白白占住

判断MySQL当前是“健康”还是“病危”,这个命令给出的信息往往比那些花哨的监控面板更直接。监控面板告诉你有慢查询,但它通常不告诉你慢查询是哪条;show full processlist则是把当前正在执行的所有语句和状态完整列出来,让你直接看到现场。

1.2 命令语法和 FULL 关键字的作用

命令本身非常简单:

SHOW PROCESSLIST; SHOW FULL PROCESSLIST;

区别在于FULL关键字:普通SHOW PROCESSLIST的 Info 列只显示SQL语句的前100个字符,而SHOW FULL PROCESSLIST会显示完整语句。

为什么我强烈建议用带FULL的版本?因为排查慢查询时,你看到的SQL往往不只是100个字符能说完的。一条复杂的联表查询,前面部分是被过滤条件,真正的重头戏可能在后面的大段子查询或ORDER BY后面,如果只给你看前100个字符,就跟看小说只看前言差不多,根本没法判断问题在哪。所以新装环境里,能不省略就不省略,直接用SHOW FULL PROCESSLIST。

一个输出示例大致长这样:

+----+------+-----------+-------+---------+------+------------------------+---------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+-------+---------+------+------------------------+---------------------+ | 1 | root | localhost | test | Query | 0 | starting | select * from t | | 2 | app | 10.0.0.1 | NULL | Sleep | 120 | | NULL | | 3 | app | 10.0.0.2 | order | Query | 82 | Sending data | select ... | +----+------+-----------+-------+---------+------+------------------------+---------------------+

看起来平淡无奇,但每一列都有讲究。

2. 输出结果逐列拆解:别只盯着 Info 看

很多新手拿到输出后,第一眼只看 Info 列,看到一条SQL就觉得“哦,问题在这”。但真正有经验的人会先看 Time 和 State,Info 反而放在最后确认。为什么?因为State描述的是线程当前正在做什么,Time说明这个状态持续了多久,两者结合才能判断是真有问题还是虚惊一场。

2.1 九个字段的含义与注意事项

输出一共八列,每一列我都给你拆开讲:

Id:线程ID,是MySQL为每个连接分配的唯一标识。这个值在后续kill连接时是必填参数,所有排查动作最后可能都要落到这一列上。

User:建立连接时使用的MySQL账号。注意,这里看不出是“谁”在执行,只能看出是什么账号。生产环境一般建议区分读写账号,通过这一列能快速判断是应用读账号还是管理账号引出了问题。

Host:客户端IP和端口号,格式是ip:port。这列在排查连接风暴时非常好用,如果发现几百个连接都来自同一个IP,说明某个应用实例可能连接没释放,或者是应用连接池配置出了问题。

db:当前连接选中的数据库名。如果连接建立后还没执行use dbname,这个值是NULL。这里有个细节:一个连接如果在事务里跨库操作,db列显示的是连接默认库,不代表当前语句操作的表一定就在这个库里,别只看这列做判断。

Command:连接当前正在执行的命令类型。常见的有Query(正在执行SQL)、Sleep(空闲等下一次指令)、Connect(连接刚建立)、Daemon(后台线程,如InnoDB后台线程)、Binlog Dump(主从复制拉取binlog)。其中Daemon和Binlog Dump属于正常后台活动,看到它们不用慌。

Time:线程进入当前状态的秒数。对Query来说,就是这条语句已经执行了多久;对Sleep来说,就是连接已经空闲了多久。这条是判断慢查询最直接的依据,没有之一。

State:线程当前状态。这是整张输出信息量最大的一列,后面单独展开讲。

Info:正在执行的SQL语句。如果线程没有在执行语句,这列是NULL。通过这列,你能看到具体是哪个SQL卡住了。

这里有一个我没提到的隐藏逻辑:show full processlist本身就是个快照,你看到的是执行那一刻的状态。如果一条SQL执行很快,你刷好几次都未必能看到它。所以这个命令更适合定位“持续长时间卡住”的问题,那种一闪而过的瞬时慢查询,得靠慢查询日志或 performance_schema 去查。

2.2 State 状态速查表:每个状态背后都有故事

State 列描述的是线程在执行SQL过程中的某个具体阶段。MySQL执行一条语句要经历解析、优化、执行、返回等很多环节,每个环节对应不同的状态名。我整理了一张高频出现的状态速查表:

State含义常见场景
Sleep连接空闲,等待客户端发送下一条指令连接池里闲置的连接,正常现象
Query正在执行SQL语句正常执行中,但如果持续很久就要警惕
Sending data正在读取、处理、发送结果集数据大查询、全表扫描、排序、临时表都可能出现
Waiting for table metadata lock等待获取元数据锁(MDL)有未提交事务占着表,DDL被堵住
Updating正在对行数据执行更新操作大update范围内的行数过多
Waiting for lock等待锁资源行锁冲突或表锁竞争
Locked等待表级锁MyISAM 表并发写入场景
Statistics正在计算统计信息大表的SQL优化阶段
Copying to tmp table正在把数据拷贝到临时表GROUP BY、ORDER BY、去重等需要临时表
Sorting result正在对结果集排序ORDER BY 没有走索引
Sending to client正在把结果集发送给客户端客户端没有及时消费结果集

这些状态单独看都没什么,关键是组合起来判断。比如Sending data+Time=82秒,基本可以认定是SQL本身执行慢;Sleep+Time=120秒,如果大量堆积,就得怀疑应用连接池配置有问题;Waiting for table metadata lock+Time一直在涨,几乎可以肯定有另一个事务没结束。

这里讲一下最容易被误读的Sending data。我见过不少同事一看到这个状态就以为SQL在“发送网络数据包”,其实它覆盖的阶段比字面意思广得多:包括InnoDB从磁盘读取数据到内存、做连接、做聚合、把结果集写回客户端等。大部分经典慢查询卡住时,State都显示为Sending data,所以看到它别急着下结论,结合Time和Info一起看才靠谱。

3. 实战排查:三个真实场景从现象到定位

工具讲了一堆,最终还是要落到实际问题上。我挑三个最典型的排查场景,把整个思路完整复盘一遍。

3.1 接口突然变慢:用 Time 列揪出慢 SQL

现象:某核心查询接口响应时间飙升,应用端监控告警,但数据库CPU并没有打满,负载也不高。

我登录数据库后执行show full processlist,发现有一条select语句的 Time 已经到60秒,State是Sending data,Info里是一个关联了四张表的查询。为了确认它不是“刚好被我碰见”,我等了5秒再执行一次,结果同一条语句还在,Time 变成了65秒,确认它确实卡住了。

拿到这条SQL后,我把它拷出来,直接EXPLAIN看执行计划。问题很明显:两张表之间做关联的字段在表上没有索引,驱动表的预估行数和实际扫描行数差了50倍以上。因为缺失索引,查询只能全表扫描加嵌套循环,性能自然上不去。

这个场景的关键点,在于第一次执行show full processlist后不要急着kill,而是先记录SQL内容,再结合EXPLAIN分析慢的根本原因。kill 只是止血,找到并补上索引才是治疗。补完索引再执行一次同样的SQL,时间从几十秒降到几十毫秒,问题才算真正解决。

3.2 表被锁住:从 Waiting for table metadata lock 追到源头

现象:业务方反馈某张表的插入操作全部堵住,应用日志里大量超时。

执行show full processlist后,我看到多条连接都停在Waiting for table metadata lock状态,而且等待时间都在几十秒以上。这些连接的Info里是insert、update这类语句,按理说不应该出现元数据锁等待。元数据锁是MySQL用来保护表结构不被修改的锁,正常情况下DML语句拿MDL锁都是瞬间完成,除非有别的会话用不释放。

这个时候show full processlist已经帮我把问题范围缩小到了“有会话占用了这张表的MDL锁”。但还要找出是谁占着锁。我继续查information_schema.innodb_trx,发现一个连接处于事务未提交状态,事务开始时间在一个多小时前,卡在一条select上但一直没有提交。这个连接虽然当时Sleep了,但事务还开着,它持有的MDL锁一直不释放,后面的DML和DDL全被堵住。

处置方式很明确:先联系业务确认那个事务是否还有用,确认后把对应线程kill掉,堵住的语句立刻恢复执行。这类问题用show full processlist能看到症状,但定位“元凶”往往需要配合innodb_trx和performance_schema一起用,后面会讲到组合操作。

3.3 连接数打满:分析 Sleep 连接和连接风暴

现象:数据库最大连接数设置为500,某天突然报 “Too many connections” 错误,新连接进不来。

先别急着调大max_connections,调大只是拖延问题。我用show full processlist看了一眼,发现连接数480多个,其中400多个都是Sleep状态,来自同一个应用IP段,符合连接池内连接数的上限。正常情况下,连接池里的连接会复用,Sleep是常态。但为什么这么多Sleep连接会打满?

继续观察,发现这些Sleep连接的空闲时间全部集中在几百秒到上千秒,说明连接长期没有被使用或回收。应用连接池的wait_timeout和max_lifetime配置不匹配,数据库侧把连接回收了,但连接池不知道,又在不断新建连接,一来二去就把连接数顶到上限。

处理上,先临时把max_connections适度调大缓解燃眉之急,然后针对性调整连接池的空闲连接存活时间和回收策略。这里要特别说明,show full processlist的价值在于让你看到连接的结构分布:有多少Sleep、多少Query、来自哪些IP。它帮我把问题从“连接数满”这种抽象表象,拆解成“连接池配置不合理导致连接堆积”这种具体定位,后面的优化才有明确方向。

4. 命令之外的组合拳:定位之后怎么办

show full processlist只解决“看”的问题,看完之后怎么处理、怎么做得更高效,才是进阶的关键。

4.1 kill 和 kill query 的正确用法

如果确认某条SQL有问题需要终止,语法是:

KILL [CONNECTION] 线程ID; KILL QUERY 线程ID;

两者的区别是:KILL CONNECTION会连同连接一起断开,客户端需要重新建立连接;KILL QUERY只终止当前正在执行的语句,连接本身还保留。MySQL 5.7 之后推荐优先用KILL QUERY,因为它更温和,不会让连接池瞬间产生大量重连。注意,单词顺序别搞反,是KILL QUERY 12345,不是QUERY KILL。

这里有个实操坑:如果线程ID对应的连接正在执行DDL(比如ALTER TABLE),kill 掉之后,MySQL可能直接走崩溃恢复流程,回滚操作本身可能比原DDL更耗时。所以遇到DDL卡住时,先搞清楚它在等什么,而不是直接kill。如果它卡在Waiting for table metadata lock,杀掉持有锁的会话通常比杀掉DDL线程更合理。

4.2 用 information_schema.processlist 做精细化筛选

show full processlist输出的是全量快照,连接一多,刷屏是家常便饭。MySQL还提供了information_schema.processlist这张视图,用法更灵活:

SELECT id, user, host, db, command, time, state, info FROM information_schema.processlist WHERE command = 'Query' AND time > 30 ORDER BY time DESC;

这条SQL能过滤出执行时间超过30秒的所有SQL,在茫茫连接里直接锁定嫌疑对象,省掉大部分人工肉眼筛选的功夫。

从实现原理上说,information_schema.processlist和show processlist读取的是同一份线程数据,但前者可以通过标准SQL做排序、过滤、聚合。我在监控脚本里就经常用它,配合GROUP BY user或者GROUP BY state统计连接分布,效果非常好:

SELECT state, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY state ORDER BY cnt DESC;

一句SQL就能看出当前数据库里线程都卡在哪个状态上。注意,如果环境里开启了 performance_schema,这张视图的数据来源也受相关配置影响,通常不需要额外设置。

4.3 基于 sys.session 做自动化监控

MySQL 5.7 之后自带的 sys schema 里有一个sys.session视图,可以看成是processlist的增强版。它多出了不少有用字段,比如连接到额、当前执行的语句、锁等待时间、事务持续时间等。

SELECT conn_id, user, current_statement, last_statement_age FROM sys.session WHERE command = 'Query' AND last_statement_age > 30;

我的经验是:日常监控脚本一律用sys.session或information_schema.processlist,避免解析show full processlist的文本输出。原因是文本输出结果格式不固定,在命令行里人眼可以看,但程序解析起来很别扭。用SQL查询拿到的是结构化数据,直接对接告警平台或者存日志都方便得多。

在做自动化时,我常用这样一个思路:每5秒执行一次采集,把超过阈值(比如30秒)的线程信息写入监控表,持续采集几分钟后,就能看到慢SQL的分布和变化趋势。等出问题时,直接查监控表就拿到当时的完整现场,比事后补日志靠谱得多。

5. 使用中容易踩的坑和我的避坑经验

这个命令虽然简单,但实际用起来有不少细节容易出问题,我一条条列出来。

5.1 权限不够导致只能看到自己的连接

默认情况下,普通MySQL账号执行show processlist时,只能看到自己账号建立的连接。这意味着如果你的运维账号权限比较小,看到的永远是“安静祥和”的状态,别人卡得要死你这边毫无波澜。要查看所有连接,账号需要PROCESS权限:

GRANT PROCESS ON *.* TO 'ops_user';

没有PROCESS权限时,还有另一种现象:能看到别人的行,但Info列显示的是unauthenticated user或者被截断的SQL内容,这种同样会严重误导判断方向。所以新装MySQL之后,给运维账号加上PROCESS权限,应该作为初始化项之一。

5.2 误把 Sending data 当成慢 SQL 直接 kill

这是我见过最频繁的误操作。前面提到过,Sending data只是线程在执行过程中的一个阶段名称,不代表真的在“发数据”。但反过来说,如果一条SQL真的慢,它多半也会卡在Sending data上。这就导致很多人养成习惯:看到Sending data就kill。

但实际上有一种常见情况:客户端设置了较小的读取超时,数据库已经把结果集准备好,正在往客户端写,客户端却不读了,连接也会停在Sending data。这种问题根源在应用侧,kill 数据库线程治标不治本,你kill完客户端重试还会复现。我的原则是:kill之前至少花10秒钟确认一下这个SQL是不是真的在服务端执行慢,而不是传输链路或者客户端消费的问题。判断依据很简单:同样的SQL在测试环境跑一遍,看它正常执行需要多久。

5.3 高频执行命令本身也会成为问题

show full processlist看起来轻量,但它在实现上要遍历MySQL内部维护的线程链表,并拷贝线程状态信息。当数据库连接数达到几千甚至上万时,这个命令本身的执行时间可能从毫秒级退化到亚秒级,频繁执行会加剧数据库压力。

我在监控方案里习惯的做法是:常规间隔不低于5秒;确认故障时手动执行可以频繁一些,但也要避免用脚本每秒钟刷一次。另外,连接数非常大的数据库,建议直接查询information_schema.processlist,并尽量用精确条件过滤,比全量show full processlist对内部锁的影响小一些。

5.4 别忽略 Command 和 State 组合看

Info列是SQL文本,Command列是这个连接在执行的命令类别,State列是SQL执行到哪个阶段,三者表面看起来独立,其实是紧密关联的一组信息。例如Command等于Binlog Dump时,State列通常是Master has sent all binlog to slave,这是主从复制正常状态,新手如果只看到“Binlog”几个字就可能误判。我自己排查问题时养成的习惯是:先把Command列过一遍,区分出正常后台活动,再集中看Query和Sleep,最后通过State和Time判断问题在哪个阶段。这套流程走下来,大部分性能问题都能圈定出清晰的排查范围。

用show full processlist这几年,最深的体会是:它是一个“定位工具”,不是一个“解决工具”。它能让你在乱成一团的数据库现场里第一时间锁定嫌疑对象,但真正解决问题,还得靠执行计划分析、索引优化、事务管理、连接池调优这些基本功。我见过不少同行只记住了一句“show full processlist”,发现问题就kill,kill完继续出问题,反复折腾却没有沉淀。正确的用法是把它当成侦查入口,每次看到异常线程后,多往前追问一步:为什么这条SQL会卡在这里?为什么连接会堆积?这样积累下来,你会慢慢养成一套属于自己的数据库排查直觉,遇到线上问题也就能越来越从容。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 15:57:19

恶意样本分析实战:远控后门从静态特征到动态行为全解析

拿到一个来路不明的可执行文件,第一反应不是双击运行,而是先问一句:它到底是什么?这正是我写这篇“某后门病毒详细分析报告”的初衷。作为安全分析入门的第一课,我用一个实际捕获的远控后门样本,完整演示从…

作者头像 李华
网站建设 2026/10/14 15:57:07

STM32片内Flash读写测试避坑指南:从扇区擦除到掉电保护

简介:这份资源面向嵌入式开发初学者与STM32工程师,聚焦片内Flash非易失性数据存储这一核心技能,帮助解决掉电数据丢失、扇区擦写策略与编程保护等实际问题。压缩包共140个文件,约2.96MB,以34个c源文件与35个h头文件为主…

作者头像 李华
网站建设 2026/10/14 15:56:57

T2000边缘计算模组开箱教程:从上电到跑通第一条NPU推理指令

简介:这份T2000使用简易教程面向华为网管系统的初学者与一线运维人员,帮助零基础用户快速掌握T2000的日常操作与业务排查方法。教程围绕网元管理器与以太网专线业务展开,涵盖展开隐藏路径、确认端口业务状态、查看端口带宽、追踪以太口与业务…

作者头像 李华
网站建设 2026/10/14 15:56:53

机房动力与环境监控系统架构与功能解析!

一、机房动环监控系统是什么机房动力与环境监控系统是对机房内动力设备(市电、配电柜、UPS、蓄电池)和环境参数(温湿度、水浸、烟感、精密空调)进行实时监测、告警与联动的系统。其核心目标是实现724小时无人值守运行,…

作者头像 李华
网站建设 2026/10/14 15:56:51

奇安信SecADS 3600应用交付实战配置指南

简介:本资源是奇安信网神SecADS 3600应用交付系统的官方快速配置手册,面向网络安全工程师、系统集成人员及售前售后技术人员,聚焦设备上线初期的高效部署与基础服务配置。手册覆盖网络串行接入拓扑、管理口默认参数、管理员账户初始化、VLAN与…

作者头像 李华
网站建设 2026/10/14 15:56:39

专有云DTS API接入实战:从AccessKey到任务生命周期管理

简介:《阿里云专有云Enterprise版V3.16.0数据传输服务DTS开发指南》是一份面向企业开发者、系统集成商及运维人员的官方产品文档,系统讲解如何利用DTS API接口完成数据迁移、同步与订阅任务的开发集成,适合使用Java、Python、Go等语言调用云服…

作者头像 李华