ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

卧槽,kill -9 竟然一直都用错了

2021-03-14 18:33:14  阅读:1262  来源: 互联网

标签:竟然 卧槽 pid 命令 线程 mysql 进程 kill


如果不仔细深究,很难发现这里是有问题的,因为网上介绍kill命令的文章很多,有些是对的,有些是错的,非常容易让我们混淆。

有说进程的:

 

 

 

 

 

也有说线程的:

 

 

 

 

另外,我那篇文章中写到的:

  1. show processlist 命令查出的到底是线程ID,还是进程ID?
  2. 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 线程id
  • User 执行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命令分为两种:

  1. kill connection id,它会断开线程的连接,并且停止线程中正在执行的sql语句。它是默认的方式,语法可以简化为:kill id。
  2. kill query id,它会停止线程中正在执行的sql语句,但是不断开线程的连接。

 

再回头看看之前的两个问题:

  1. show processlist 命令查出的到底是线程ID,还是进程ID?
  2. mysql是单进程的,kill -9 ID到底杀掉是线程,还是进程?

show processlist查出的是线程ID。kill ID杀掉的是线程,并且用的mysql自己的kill命令。

另外kill -9 ID这种写法是不对的,mysqlkill命令并不支持-9作为参数。

二 linux如何获取PID?

上面聊完了mysql数据库,接下来,我们聊聊linux

由于linux是开源免费的,而且稳定、性能好,非常适合部署线上服务。

top命令

如果某天,你们公司线上的某个节点,部署了多个服务,其中有一个服务cpu使用率100%,或者内存占用太多了,要如何定位到具体是哪个服务呢?

这时top命令就派上用场了。

 

 

 

 

上图中的%CPU列,表示cpu使用率,图中是无序的。MEM列,表示内存占用情况,也是无序的。

如果要按cpu使用率降序,可以输入大写的:P

如果要按内存占用情况降序,可以输入大写的:M

使用top命令能很快查到,那个服务的cpu使用过高,或者内存占用太多,能查出该服务的pid,也就是进程号

接下来,就可以使用linuxkill命令杀掉该pid对应的异常进程,重启服务,避免该节点资源被耗尽,而影响其他服务。

我之前用这个命令定位过,由于静态资源文件同步的的shell脚本,一次通过的文件数量太多,导致cpu使用率太高的问题。

查看java进程

1.jps

如果是java程序,想找到运行的pid是比较容易的,可以使用:jps命令。

 

 

 

 

这个命令的优点是非常方便得查看pid。缺点是很多关键信息,比如:JVM参数等都没有,不方便排查问题。

2.ps -ef|grep java

如果想查看更多内容,可以使用ps -ef|grep java

 

 

 

 

 

这个命令的优点是除了能查看pid之外,还能查看jdk版本,JVM参数等信息。缺点是如果java服务比较多,显示的内容会很多,不利于查看。

当然linuxps的参数挺多的,具体含义可以参考下面内容:

 

 

 

 

 

 

 

常用的组合参数是:

  • - 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命令时,有没有出现过杀不掉的情况?

我反正遇到过的。

哪有些情况下杀不掉?

  1. 该进程是僵尸进程,资源已经被释放了,但是没有被父进程释放引用。这种进程,只能等父进程终止后,才能终止。
  2. 进程处于“核心态”,且在等待不可获得的资源。处于核心态的进程忽略所有信号处理,因此对于这些一直处于核心态的进程只能通过重启系统实现。

 

特别预告一下,我后面会写一个专题讨论cpu使用率过高问题,分享我遇到过的多种不同场景,干货满满,小伙伴们可以期待一下。

 

标签:竟然,卧槽,pid,命令,线程,mysql,进程,kill
来源: https://www.cnblogs.com/12lisu/p/14533571.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有