32 | 为什么还有kill不掉的语句?

(1)kill query +线程 id,终止正在执行

(2)kill connection(可缺省) + 线程 id断开连接(先停执行),

kill 没断开连接。show processlist 命令,显示Killed。不是应该看不到这个线程了吗?

有效场景:查询太久/锁等待

图 1 kill query 成功的例子

session B 被中断(符合预期)

一、收到 kill 以后,线程做什么?

第 6 篇文章增删改时,表加 MDL 读锁。 B 虽 blocked 但拿MDL 读锁。终止则没机会被释放。kill :不需执行

跟 Linux 的 kill 命令类似,kill -N pid 并不是让进程直接停止,而是给进程发一个信号,然后进程处理这个信号,进入终止逻辑。只是对于 MySQL 的 kill 命令来说,不需要传信号量参数,就只有“停止”这个命令。

1.1 kill query做了两件事:

(1)状态THD::KILL_QUERY(变量 killed 赋值为 THD::KILL_QUERY);

(2)发信号:让B知道。

多处“埋点”判断状态THD::KILL_QUERY,进入终止逻辑(不是“说停就停的”);

ps:如等待,必须是可唤醒,否则不会执行到“埋点”;

1.2 kill 不掉的例子

(1)KILL_QUERY,等待中,不会进入终止逻辑阶段。

第 29 篇文章 set global innodb_thread_concurrency=2,并发线程上限数

图 2 kill query 无效的例子

session E 中执行 show processlist,断开连接,服务端仍在执行 ,不像第一个update 退出?

图 3 kill connection 之后的效果  

等行锁时用pthread_cond_timedwait 函数,等待状态可被唤醒。10 毫秒判断是否进 InnoDB 执行,不行调用 nanosleep 函数sleep 状态。

设置为KILL_CONNECTION;关掉网络连接。显示成 Killed。

 IO 压力过大,读写 IO 无法返回,出现同样情况

(2)终止逻辑耗时较长

1.  超大事务执行期间被 kill。回滚长。

2.  大查询回滚。生成大临时文件,删除等 IO 资源,耗时长。

1.3客户端 Ctrl+C 不能终止线程

客户端和服务端只能通过网络交互不能直接操作服务端线程。 kill 涉及后端很多

停等协议:没返回时,往连接里发命令没用。Ctrl+C :另外启动连接,发送 kill query 命令。

二、另外两个关于客户端的误解

2.1 误解1:表多,连接慢

库里6 万个表,客户端连接卡:

图 4 连接等待

连接时: TCP 握手、用户校验、获取权限。跟表个数无关。

默认参数连接时,MySQL 提供本地库、表名补全功能(用的不多)。为了实现这个功能,连接成功多做操作:

show databases,切到 db1 库 show tables;上面结果构建本地哈希表(表多时间长,关掉补全就快)

2.2 加–quick(简写为 -q) 跳过阶段,性能快(错)

可能降低服务端性能,接收服务端返回结果方式:

1.  缓存(默认),mysql_store_result 方法。

2.  不缓存(加–quick),mysql_use_result 方法。//本地处理得慢,发送结果阻塞,服务端慢。

2.3 quick 优点(让客户端变快)

(1)自动补全

(2)mysql_store_result 申请内存缓存结果,但查询结果大,耗费内存多,影响性能;

(3)把执行命令记录到本地命令历史文件。

小结

“kill 不掉”是因为发送 kill 命令客户端,并没有强行停止目标线程执行,只是设置了个状态,并唤醒对应的线程。被 kill 线程,执行到判断状态的“埋点”,才进入终止逻辑阶段。

发现线程 Killed 状态,影响系统环境, Killed 状态尽快结束。

第一个例子里 InnoDB 并发度的问题,你就可以临时调大innodb_thread_concurrency 的值,或者停掉别的线程,让出位子给这个线程执行。

回滚逻辑由于受到 IO 资源限制,减少系统压力让它加速。

思考题

被 killed 事务一直回滚状态,强行重启,还是执行完成?为什么呢?


等待(更快),重启也要回滚,保证一致性

如果占用别的锁,或者占用 IO 资源过多,影响别语句执行,先做主备切换切新主库

切换后别的线程都断开连接,自动停止执行。接下来还是等它自己执行完成。减少系统压力,加速终止逻辑。

评论1

kill connection:客户端sql连接断开,会显示“killed”。平时紧急处理用kill + thread_id

kill query:后面执行流程,不会回滚,ctrl+c时

kill query无效,kill connection也无效

你可能感兴趣的:(32 | 为什么还有kill不掉的语句?)