Mysql show processlist 详解
show processlist 命令
show processlist 是显示用户正在运行的线程,需要注意的是,除了 root 用户能看到所有正在运行的线程外,其他用户都只能看到自己正在运行的线程,看不到其它用户正在运行的线程。除非单独给这个用户赋予了PROCESS 权限。
show processlist 显示的信息都是来自MySQL系统库 information_schema 中的 processlist 表。所以使用下面的查询语句可以获得相同的结果:select * from information_schema.processlist;
如下是执行命令的结果:
1 | mysql> show processlist; |
- Id: 就是这个线程的唯一标识,当我们发现这个线程有问题的时候,可以通过 kill 命令,加上这个Id值将这个线程杀掉。前面我们说了show processlist 显示的信息时来自information_schema.processlist 表,所以这个Id就是这个表的主键。
- User: 就是指启动这个线程的用户。
- Host: 记录了发送请求的客户端的 IP 和 端口号。通过这些信息在排查问题的时候,我们可以定位到是哪个客户端的哪个进程发送的请求。
- DB: 当前执行的命令是在哪一个数据库上。如果没有指定数据库,则该值为 NULL 。
- Command: 是指此刻该线程正在执行的命令。
- Time: 表示该线程处于当前状态的时间。
- State: 线程的状态,和 Command 对应,下面单独解释。
- Info: 一般记录的是线程执行的语句。默认只显示前100个字符,也就是你看到的语句可能是截断了的,要看全部信息,需要使用 show full processlist。
看一下 Command 的值
- Binlog Dump: 主节点正在将二进制日志 ,同步到从节点
- Change User: 正在执行一个 change-user 的操作
- Close Stmt: 正在关闭一个Prepared Statement 对象
- Connect: 一个从节点连上了主节点
- Connect Out: 一个从节点正在连主节点
- Create DB: 正在执行一个create-database 的操作
- Daemon: 服务器内部线程,而不是来自客户端的链接
- Debug: 线程正在生成调试信息
- Delayed Insert: 该线程是一个延迟插入的处理程序
- Drop DB: 正在执行一个 drop-database 的操作
- Execute: 正在执行一个 Prepared Statement
- Fetch: 正在从Prepared Statement 中获取执行结果
- Field List: 正在获取表的列信息
- Init DB: 该线程正在选取一个默认的数据库
- Kill : 正在执行 kill 语句,杀死指定线程
- Long Data: 正在从Prepared Statement 中检索 long data
- Ping: 正在处理 server-ping 的请求
- Prepare: 该线程正在准备一个 Prepared Statement
- ProcessList: 该线程正在生成服务器线程相关信息
- Query: 该线程正在执行一个语句
- Quit: 该线程正在退出
- Refresh:该线程正在刷表,日志或缓存;或者在重置状态变量,或者在复制服务器信息
- Register Slave: 正在注册从节点
- Reset Stmt: 正在重置 prepared statement
- Set Option: 正在设置或重置客户端的 statement-execution 选项
- Shutdown: 正在关闭服务器
- Sleep: 正在等待客户端向它发送执行语句
- Statistics: 该线程正在生成 server-status 信息
- Table Dump: 正在发送表的内容到从服务器
- Time: Unused
注意:主要需要关注 query和sleep命令。sleep是在等待prestatement(sql语句),它已经建立了connect,但是还没有开始执行,所以sleep状态多的话,那么数据库连接池就会被占用。所以:有时候sleep增多的原因可能是慢查询sql,但是sleep不是慢查询,因为它还没有开始执行。
看一下State的值:
After create
当线程在创建表的函数的末尾创建表(包括内部临时表)时,会发生这种情况。即使由于某些错误而无法创建表,也会使用此状态。
altering table
服务器正在执行就地服务
ALTER TABLE
。Analyzing
该线程正在计算
MyISAM
表键分布(例如forANALYZE TABLE
)。checking permissions
线程正在检查服务器是否具有执行该语句所需的特权。
Checking table
线程正在执行表检查操作。
cleaning up
该线程已经处理了一条命令,并准备释放内存并重置某些状态变量。
closing tables
线程正在将已更改的表数据刷新到磁盘并关闭已使用的表。这应该是一个快速的操作。如果没有,请确认您没有完整的磁盘,并且磁盘使用率不是很高。
Waiting for `lock_type` lock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
服务器正在等待`THR_LOCK`从元数据锁定子系统获取 锁或锁,其中 *`lock_type`*指示了锁的类型。
此状态表示正在等待 `THR_LOCK`:
- `Waiting for table level lock`
这些状态指示等待元数据锁定:
- `Waiting for event metadata lock`
- `Waiting for global read lock`
- `Waiting for schema metadata lock`
- `Waiting for stored function metadata lock`
- `Waiting for stored procedure metadata lock`
- `Waiting for table metadata lock`
- `Waiting for trigger metadata lock`
其他的请参考mysql官网即可:https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html
**注意:这里需要关注的是locked这种状态,我们无法操作表或者其他的时候,也许是遇到了死锁,或者加锁时间太长等**
#### 常用的检查mysql问题的sql
- 按客户端 IP 分组,看哪个客户端的链接数最多
```mysql
select client_ip,count(client_ip) as client_num from (select substring_index(host,':' ,1) as client_ip from processlist ) as connect_info group by client_ip order by client_num desc;查看正在执行的线程,并按 Time 倒排序,看看有没有执行时间特别长的线程
1 | select * from information_schema.processlist where Command != 'Sleep' order by Time desc; |
- 找出所有执行时间超过 5 分钟的线程,拼凑出 kill 语句,方便后面查杀
1 | select concat('kill ', id, ';') from information_schema.processlist where Command != 'Sleep' and Time > 300 order by Time desc; |
- 检查是否有死锁,并找出具体线程名
1 | mysql -u root -e "show processlist" | grep -i "Locked" >> locked_log.txt |