卧槽,kill -9 竟然一直都用错了
作者:互联网
如果不仔细深究,很难发现这里是有问题的,因为网上介绍kill命令的文章很多,有些是对的,有些是错的,非常容易让我们混淆。
有说进程的:
也有说线程的:
另外,我那篇文章中写到的:
show processlist
命令查出的到底是线程ID,还是进程ID?mysql
是单进程的,kill -9 ID
到底杀掉是线程,还是进程?
带着这些疑问,让我们一起开始今天的内容。
一 从mysql说起
我之前的那篇文章主要介绍的是:使用mysql
数据库过程中遇到的问题,那就先从mysql
说起。
mysql是单进程的
众所周知:mysql
是单进程,多线程的。
在5.6以前的版本中,mysql处理连接的方式是One-Connection-Per-Thread
,mysql中的一个数据库连接对应一个线程。在高并发
的场景下,如果有非常多的连接,需要消耗非常多的内存资源
,另外上下文切换
也浪费了很多cpu
的时间。
在5.6及以后的版本中,mysql处理连接的方式是One-Thread-Per-Connection
,mysql中的一个线程对应一个数据库连接。在线程池
的实现方案中,线程可以处理的最小单位
是statment
,一个线程可以处理多个数据库连接的请求。
show processlist命令
有时我们为了定位mysql
的sql问题,特别是报:too many connections
问题时,一定会用show processlist
命令(mysql会给管理员账号,额外预留一个数据库
连接),查出线程运行情况,数据库连接的状态和有问题的sql语句。例如
id
线程idUser
执行sql的账号Host
执行sql的数据库的ip和端号db
数据库名称Command
执行命令,包括:Daemon、Query、Sleep等。Time
执行sql所消耗的时间State
执行状态info
执行信息,里面可能包含sql信息。
如果是root
账号,可以查看所有的线程。
如果是非root
账号,只能查看当前登录账号自己的线程,默认只显示前100
条记录。如果想查看更多记录,可以使用show full processlist
命令。
其实使用show processlist
命令是从information_schema.processlist
表中查出的结果。
跟使用sql语句:
select * from information_schema.processlist;
效果差不多。
但是,使用sql语句有个好处是可以加where
条件,能够进一步过滤数据。
假如查到id=220
的那个线程的sql执行非常耗时,接下来怎么办呢?
mysql也有kill命令
既然从上面已经得到了id,接下来的任务就简单了,把那个id对应的线程kill
掉就OK了。
但这里的kill
命令,并非指linux
中我们所熟悉的kill
,而是mysql
自己的。
什么?mysql也有kill
命令?
还真有。
mysql的kill命令分为两种:
- kill connection id,它会断开线程的连接,并且停止线程中正在执行的sql语句。它是默认的方式,语法可以简化为:kill id。
- kill query id,它会停止线程中正在执行的sql语句,但是不断开线程的连接。
再回头看看之前的两个问题:
show processlist
命令查出的到底是线程ID,还是进程ID?mysql
是单进程的,kill -9 ID
到底杀掉是线程,还是进程?
show processlist
查出的是线程ID。kill ID
杀掉的是线程,并且用的mysql自己的kill命令。
另外kill -9 ID
这种写法是不对的,mysql
的kill
命令并不支持-9
作为参数。
二 linux如何获取PID?
上面聊完了mysql
数据库,接下来,我们聊聊linux
。
由于linux
是开源免费的,而且稳定、性能好,非常适合部署线上服务。
top命令
如果某天,你们公司线上的某个节点,部署了多个服务,其中有一个服务cpu使用率100%,或者内存占用太多了,要如何定位到具体是哪个服务呢?
这时top
命令就派上用场了。
上图中的%CPU
列,表示cpu使用率,图中是无序的。MEM
列,表示内存占用情况,也是无序的。
如果要按cpu使用率降序,可以输入大写的:P
。
如果要按内存占用情况降序,可以输入大写的:M
。
使用top
命令能很快查到,那个服务的cpu使用过高,或者内存占用太多,能查出该服务的pid
,也就是进程号
。
接下来,就可以使用linux
的kill
命令杀掉该pid
对应的异常进程,重启服务,避免该节点资源被耗尽,而影响其他服务。
我之前用这个命令定位过,由于静态资源文件同步的的shell脚本,一次通过的文件数量太多,导致cpu使用率太高的问题。
查看java进程
1.jps
如果是java程序,想找到运行的pid
是比较容易的,可以使用:jps
命令。
这个命令的优点是非常方便得查看pid
。缺点是很多关键信息,比如:JVM参数等都没有,不方便排查问题。
2.ps -ef|grep java
如果想查看更多内容,可以使用ps -ef|grep java
。
这个命令的优点是除了能查看pid
之外,还能查看jdk版本,JVM参数等信息。缺点是如果java服务比较多,显示的内容会很多,不利于查看。
当然linux
的ps
的参数挺多的,具体含义可以参考下面内容:
常用的组合参数是:
- ef
表示全格式显示所有进程。- aux
也表示全格式显示所有进程,但会截断command列。
推荐使用- ef
参数。
查看java线程
如果知道了java进程的pid,要查看线程执行情况该怎么办呢?
可以使用jstack pid
命令。
图中的tid
就是线程ID,查询结果中还有线程执行状态和部分代码信息,有时候查看某个线程导致cpu使用率过高问题时,使用这个命令特别有效。
我后面会写一个专题讨论cpu使用率过高问题,大家可以期待一下。
需要注意的是线程id,使用kill命令,是杀不掉的。换句话说就是kill杀掉的是进程,而非线程。
三 kill命令的原理
kill命令的执行原理是:会向操作系统内核发送一个信号 和目标进程的PID,然后系统内核根据收到的信号类型,对指定进程进行相应的操作。
语法格式:kill [参数] [进程号]
常用参数:
可以使用:kill -l
查出所有信号量
然后根据信号量kill具体pid即可,具体的的语法是:
kill [信号] PID
常见信号量可参考如下表格:
其中kill PID
默认使用的是-15
。
我们平常使用最多的参数是:-3
、-9
和-15
,那么这三者有啥区别呢?
-
kill -3 pid
可以打印进程各个线程的堆栈信息
-
kill -9 pid
表示进程被终止,需要立即退出,强制杀死该进程,这个信号不能被捕获也不能被忽略。
-
kill -15 pid
正常退出是指按应用程序自己的退出流程完成退出,这样就可以清理并释放资源。
这段java代码中增加了ShutdownHook
线程,便于在当前应用进程结束时,能够执行一些额外的工作,比如:回收资源。
@EnableAsync @EnableSwagger2 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) public class Application { /** * 程序入口 * * @param args 程序输入参数 */ public static void main(String[] args) { new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { System.out.println("资源回收"); } }); } }
当执行kill -9 pid命令时,"资源回收"不会打印。
而执行kill -15 pid命令时,"资源回收"才打会印。
建议优先使用
kill -15 pid
,因为使用它可以回收资源(比如数据库连接)。但是有时候回收资源花费的时间较长,进程可能很长一段时间才会被终止,这是很多程序员不喜欢用-15
,而常用-9
的原因。
四 kill -9 有时失效了?
你在使用kill -9 pid
命令时,有没有出现过杀不掉的情况?
我反正遇到过的。
哪有些情况下杀不掉?
- 该进程是
僵尸进程
,资源已经被释放了,但是没有被父进程释放引用。这种进程,只能等父进程终止后,才能终止。 - 进程处于“
核心态
”,且在等待不可获得的资源。处于核心态的进程忽略所有信号处理,因此对于这些一直处于核心态的进程只能通过重启系统实现。
特别预告一下,我后面会写一个专题讨论cpu使用率过高问题,分享我遇到过的多种不同场景,干货满满,小伙伴们可以期待一下。
标签:竟然,卧槽,pid,命令,线程,mysql,进程,kill 来源: https://www.cnblogs.com/12lisu/p/14533571.html