《MYSQL45讲》kill不掉的线程

kill query + 线程id :终止这个线程正在执行的语句

kill connection + 线程id :关闭这个线程的连接,也会先停止这个线程正在执行的语句。这个connection可以缺省。

本文讨论的情况是:使用了kill命令,却没有断开连接,show processlist命令执行结果中,被kill的线程显示killed,这个killed是什么意思?以及一些常见的命令误解

1.收到kill query命令后,线程会做什么?

1.MYSQL中有个处理的kill命令的线程,处理kill命令的线程首先会设置该线程的状态为KILL_QUERY

2.给该线程发送一个“你被kill了”的信号

一个语句的执行过程中有多处埋点,执行到埋点处就会判断自己的线程状态。

如果线程在等待某个资源,那这个等待必须是可以唤醒的,否则就无法到达埋点处。

执行kill query 线程id命令,处理kill命令的线程首先会设置该线程的状态为KILL_QUERY,然后给该线程发送一个信号,该线程收到信号后知道自己被kill了,如果正在锁等待,就停止等待。去处理这个KILL_QUERY状态。 如果不发信号,该线程就仍然在锁等待,不知道自己被kill了。

2.收到kill connection命令后,会发生什么?

1.将被kill线程的状态设置为Kill_Connection

2.关闭被kill线程的网络连接

3.由于最大并发线程数不够导致的新线程等待并且kill不掉

当线程数已经达到最大并发线程数(innodb_thread_concurrency),此时一个新的查询请求想进来,需要等待有空闲线程,所以会每隔10ms尝试进入一次,并没有去判断线程的状态,所以此时kill query这个线程是没用的,而kill connection是可以的,直接关闭网络连接,但是一查,该线程仍然在等待中,不过状态是KILLED,因为

如果一个线程的状态是KILL_CONNECTION,就会把Command列显示成Killed。

为什么这样设计,因为断开连接只是将客户端和服务端连接断开了,而服务端的线程还是存在的。

那么该线程什么时候才能停止呢?

答案是要等到该线程能够进入innodb时,才会判断出自己的状态是了KILL_QUERY或者KILL_CONNECTION,此时才会进入终止线程的逻辑。

4.由于耗时长导致的一段时间内线程kill不掉

情况1:大事务,被kill时要将前面的更改都回滚,耗时长。

情况2:大查询回滚。

情况3:DDL命令执行到最后时被kill。

关于客户端的3个误解

1.在一个查询语句长时间阻塞时,客户端直接执行ctrl+c可以终止这个线程吗?

是不可以的,执行ctrl+c时,是启动另一个线程向服务端发送kill query命令,而MYSQL是停等协议,也就是要等到客户端的操作只能影响你客户端的线程,你ctrl+c只是客户端线程终止,只是你客户端退出了,服务端的线程仍然在运行。

2.数据库的表特别多,客户端连接就会很慢

客户端连接服务端需要执行的步骤是TCP握手,用户账号密码校验,获取权限。

可以看出来与表的数量没有关系。

表越多连接越速度越慢的原因是

客户端在连接成功后,需要将“每个库有哪些表”存本地缓存,用于名称补全的。

使用-A可以取消掉这个操作。

3.-quick命令不会让服务端变快

MYSQL客户端发送请求后,接收服务端返回结果的方式有两种:

1.在本地开个缓存,先把结果存起来。

2.不缓存,读一个处理一个

默认是第一个,而使用-quick就算第2个设置。

如果不缓存,本地如果处理慢了,就会导致服务端的结果被阻塞(因为停等协议),就导致服务端变慢了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值