MySQL中存在着两个kill命令,一个是kill query+线程id 表示停止执行语句,一个是kill connection + 线程id 表示断开线程的连接

但是有时候使用kill命令,没能断开这个线程,再次执行show proccesslist的命令的时候,发现Command列显示的是killed

为何没有断开这个线程,

图片

我们要想一想,收到了kill命令后,线程会做什么

加入sessionB直接终止了线程,什么都不管就直接退出,显然是不行的

但是当对一个表有增删改查操作的时候,会在表上加MDL读锁,如果sessionB处于blocked状态,直接杀死的话,这个MDL读锁就没法释放了

这样的话,kill就只是告诉线程这个语句可以停止了,不是直接强制停止,跟关闭线程池一样

这就是和linux的kill命令类似,只是发一个信息,告诉线程进入终止逻辑,但是并不强制关闭

然后kill query thread_id_x时候,MySQL做了两件事

将session B的状态改为了THD::KILL_QUERY,就是讲killed 赋值为 THD::KILL_QUERY

然后给session B发一个信号

一个语句执行过程中,有多处埋点,在这些埋点的地方判断线程状态,如果发现有THD::KILL_QUERY,就进行语句的终止

如果一个语句处于无法被唤醒的状态,那么不会执行到埋点的地方

这个语句从发起终止到完成终止,不是说停就停的

比如我们看一下kill不掉的例子

就是工作并发线程已经满了

首先设置innodb_thread_concrrency=2

图片

接下来两个sleep命令将所有工作线程占用了

接下来sessionC执行的时候,就被堵住了

sessionD执行的kill query C就没什么用了

执行kill connection,才能断开session C的连接

但是看show processlist,可以看到如下的图

图片

这就出现了killed不掉的情况了

当session 执行kill connection 的时候,是这么做的

将线程设置为KILL_CONNECTION

然后关闭线程的网络连接,导致客户端可以收到断开的提示

而且无法kill的原因总结为:

1.kill无效,就如同上面的线程无法执行,或者是IO压力大,导致分配不到资源

2.终止逻辑耗时过长

对于2:在大事务执行中进行kill,需要对新数据进行回滚

大查询回滚,查询过程中生成了大的临时文件,需要删除

DDL执行到了后期,需要删除临时文件,耗时长

所以杀死一个线程并不是那么简单的

即使用Ctrl+C来关闭连接,那么kill掉一个线程还需要涉及到其他操作,Ctrl+C只是另起一个连接,发送kill query命令

发表评论

邮箱地址不会被公开。 必填项已用*标注