暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL 为什么Kill不掉线程

1250



Hi~朋友,关注置顶防止错过消息



mysql kill命令

-- 终止线程正在执行的语句
kill query 线程ID;
-- 断开线程的连接,connection可以省略
-- 如果该线程有正在执行的语句,会先停止正在执行的语句
kill connection 线程ID;

复制

kill的执行逻辑

被kill的线程不会立即停止,因为当我们对表做增删改查时,会在表上加MDL读锁,因此如果立即停止,MDL读锁将会无法释放。

因此这里kill只是告诉线程,这条语句已经不需要继续执行,可以开始执行停止的逻辑。

对于kill query 线程ID来说:

  1. 会把线程运行状态改成THD::KILL_QUERY(对于kill connection来说是改成KILL_CONNECTION)
  2. 给线程发送一个信号

为什么需要发送信号?

对于因为锁等待的线程并不知道自己状态的变化,还是会继续等待,因此对线程发送一个信号,可以让线程退出等待,处理THD::KILL_QUERY状态。

kill不掉的情况有几种?

  • 线程没有执行到判断线程状态的逻辑
  • 终止逻辑耗时比较长

线程没有执行到判断线程状态的逻辑导致kill不掉

在线程并发查询数达到innodb_thread_concurrency设置时,如果执行kill query是无法终止的:

set global innodb_thread_concurrency=2;

复制
Session ASession BSession CSession DSession 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就到这,扫码关注,更多内容我们下期再见!



往期推荐

MySQL数据误删以后不要跑路

如何判断MySQL实例出了问题

MySQL GTID主备切换协议

MySQL主从如何保证高可用

MySQL主从同步如何保证数据一致性

MySQL如何保证数据不丢失


文章转载自程序员修炼笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论