朋友们,杀掉一个正在执行的SQL语句是经常遇到的,大家都是使用 kill 来杀的吧?有没有遇到 kill 不掉的情况? kill 掉后又出现一个同样的SQL?Ctrl+C也没有效果?
旭杰把这块仔细研究了一下,整理成文档给大家分享,有不对或不全的欢迎留言交流,咱们共同追求进步!
kill 分类
1)kill connection 线程ID
connection可以缺省,也就是说平时执行的 kill 线程ID 就是 kill connection 线程ID。作用是:断开该线程的连接;已开始执行的SQL继续执行完成;未开始执行的SQL将不会被执行。
2)kill query 线程ID
作用是:终止该查询;但此处的终止并不是立即终止,而是告诉线程说,这条语句已经不需要继续执行了,可以开始“执行停止的逻辑了”,具体的停止动作是该线程自己做的(其实不光MySQL,各个组件都有这种设计,就是为了安全),就跟java中的interrupt似的。
注:
A、一个语句执行过程中有多处“埋点”,在“埋点”处判断如果需要停止才执行终止逻辑。
B、如果处于等待状态,必须是一个可以被唤醒的等待,否则根本不会执行到“埋点”处。
C、语句从开始进入终止逻辑,到终止逻辑完全完成,是有一个过程的。
D、要终止一个mysql线程,kill query已经是在安全范围内最高的方式了; 在操作系统层面执行kill -9 会对数据库早晨灾难性的影响,绝对不可取。
常见的终止逻辑耗时较长的情况
A、超大事务执行期间被kill;这时候,回滚操作需要对事务执行期间生成的所有新数据版本做回收操作,耗时很长。
B、大查询回滚;如果查询过程中生成了比较大的临时文件,加上此时文件系统压力大,删除临时文件可能需要等待IO资源,导致耗时较长。
C、DDL命令执行到最后阶段;如果被kill,需要删除中间过程的临时文件,也可能受IO资源影响耗时较久。
Ctrl+C
有人问直接在客户端通过 Ctrl+C 命令,是不是就可以直接终止线程呢?
答案是:不可以。MySQL也不允许自己的线程被外部直接杀掉。
这里有一个常识:客户端的操作只能操作到客户端的线程,客户端和服务端只能通过网络交互,是不可能直接操作服务端线程的。
实际上,执行 Ctrl+C 的时候,MySQL 客户端另外启动一个连接,然后发送一个 kill query 命令。既然上面提到 kill query已经是在安全范围内最高的方式了,那么可见:Ctrl+C 也是一种非常不错的终止查询的方式。
评论 (0)