Hi~朋友,关注置顶防止错过消息
mysql kill命令
-- 终止线程正在执行的语句
kill query 线程ID;
-- 断开线程的连接,connection可以省略
-- 如果该线程有正在执行的语句,会先停止正在执行的语句
kill connection 线程ID;复制
kill的执行逻辑
被kill的线程不会立即停止,因为当我们对表做增删改查时,会在表上加MDL读锁,因此如果立即停止,MDL读锁将会无法释放。
因此这里kill只是告诉线程,这条语句已经不需要继续执行,可以开始执行停止的逻辑。
对于kill query 线程ID来说:
会把线程运行状态改成THD::KILL_QUERY(对于kill connection来说是改成KILL_CONNECTION) 给线程发送一个信号
为什么需要发送信号?
对于因为锁等待的线程并不知道自己状态的变化,还是会继续等待,因此对线程发送一个信号,可以让线程退出等待,处理THD::KILL_QUERY状态。
kill不掉的情况有几种?
线程没有执行到判断线程状态的逻辑 终止逻辑耗时比较长
线程没有执行到判断线程状态的逻辑导致kill不掉
在线程并发查询数达到innodb_thread_concurrency设置时,如果执行kill query是无法终止的:
set global innodb_thread_concurrency=2;
复制
Session A | Session B | Session C | Session D | Session E |
---|---|---|---|---|
select sleep(100) from t; | select sleep(100) from t; | |||
select * from t;/*会被阻塞*/ | ||||
kill query C; | ||||
kill C; |
Session D执行以后,没有产生任何效果,当Session E执行了kill connection命令以后,Session C收到了断开连接的提示,如下图:

此时通过show processlist查看连接状态,如下图:

可以看到,id=23的状态已经变成了killed。
为什么等行锁的线程可以被kill正常退出,但是上面的情况无法正常退出?
原因是id=23的线程等待逻辑是:每隔一段时间判断一下是否可以进入InnoDB执行,如果不行,就调用nanosleep函数进入sleep状态,虽然该线程的状态已经被修改为KILL_QUERY,但是在这个等待进入InnoDB的循环过程中,并没有去判断线程状态,因此根本不会进入终止逻辑阶段。
因此此时即使客户端退出了,该线程的状态仍然是等待中,只有在等待满足进入InnoDB的条件后,才有可能判断到线程状态变成了KILL_QUERY或者KILL_CONNECTION,再进入终止逻辑阶段。
终止逻辑耗时较长的几种情况?
超大事务执行期间被kill:回滚操作需要对事务期间生成的所有数据版本做回收操作,耗时比较长 大查询回滚:查询过程中生成比较大的临时文件需要删除,如果此时文件系统压力很大,删除临时文件需要等待IO资源 DDL执行到最后阶段被kill:需要删除中间过程的临时文件,可能受IO资源影响耗时较久
本期MySQL Kill就到这,扫码关注,更多内容我们下期再见!
往期推荐