第三十二讲 (kill 命令概述)

135 阅读3分钟

kill命令

kill使用

  • 一个是kill query +线程id,表示终止这个线程中正在执行的语句;
  • 一个是kill connection +线程id,这里connection可缺省,表示断开这个线程的连接,当然如果这个线程有语句正在执行,也是要先停止正在执行的语句的。

kill 执行流程

  1. 修改session X的运行状态为THD:KILL_QUERY
  2. 给session X的执行线程发一个信号。

线程的执行流程:

  • 一个语句执行过程中有多处“埋点”,在这些“埋点”的地方判断线程状态,如果发现线程状态是THD::KILL_QUERY,才开始进入语句终止逻辑;
  • 如果处于等待状态,必须是一个可以被唤醒的等待,否则根本不会执行到“埋点”处;
  • 语句从开始进入终止逻辑,到终止逻辑完全完成,是有一个过程的。

show processlist的时候,有一个特别的逻辑:如果一个线程的状态是KILL_CONNECTION,就把Command列显示成Killed。

Kill 无效的场景

  • 线程没有执行到判断线程状态的逻辑。跟这种情况相同的,还有由于IO压力过大,读写IO的函数一直无法返回,导致不能及时判断线程的状态。
  • 终止逻辑耗时较长。从show processlist结果上看也是Command=Killed,需要等到终止逻辑完成,语句才算真正完成。这类情况,比较常见的场景有以下几种:
    • 超大事务执行期间被kill。
    • 大查询回滚。如果查询过程中生成了比较大的临时文件,加上此时文件系统压力大,删除临时文件可能需要等待IO资源,导致耗时较长。
    • DDL命令执行到最后阶段,如果被kill,需要删除中间过程的临时文件,也可能受IO资源影响耗时较久。

客户端连接

当使用默认参数连接的时候,MySQL客户端会提供一个本地库名和表名补全的功能。

为了实现这个功能,客户端在连接成功后,需要多做一些操作:

  • 执行show databases;

  • 切到db1库,执行show tables;

  • 把这两个命令的结果用于构建一个本地的哈希表。 (这一步如果表个数多的时候会花较长的时间 可能会出现连接较慢的情况)

解决: 使用-A,就可以关掉这个自动补全的功能,然后客户端就可以快速返回了

连接方式

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

  • 一种是本地缓存,也就是在本地开一片内存,先把结果存起来。如果你用API开发,对应的就是mysql_store_result 方法。
  • 一种是不缓存,读一个处理一个。如果你用API开发,对应的就是mysql_use_result方法。

客户端默认采用第一种方式,如果加上–quick参数,就会使用第二种不缓存的方式。 采用不缓存的方式时,如果本地处理得慢,就会导致服务端发送结果被阻塞,因此会让服务端变慢。

-quick的作用
  • 跳过表名自动补全功能。
  • mysql_store_result需要申请本地内存来缓存查询结果,如果查询结果太大,会耗费较多的本地内存,可能会影响客户端本地机器的性能;
  • 不会把执行命令记录到本地的命令历史文件。