Sunskey

日拱一卒,不期而至

0%

Kill不掉的语句

Kill不掉的语句

两个kill命令:一个kill query + 线程id,表示终止这个线程中正在执行的语句。

一个是kill connection + 线程id,表示断开这个线程的连接。当然如果这个线程有语句正在执行,也要先停止正在执行的语句。

kill执行的过程

1.一个语句执行过程中有多处“埋点”,在这些“埋点”的地方判断线程状态,如果发现线程状态是THD::KILL_QUERY,才开始进入语句终止逻辑。

2.如果处于等待状态,必须是一个可以被唤醒的等待,否则根本不会执行到“埋点”处

3.语句从开始进入终止逻辑,到终止逻辑完全完成,是由一个过程的。

kill无效的两类情况

1.线程没有执行到判断线程状态的逻辑。

2.终止逻辑耗时较长。

  • 超大事务执行期间被Kill。回滚需要对事务执行期间生成的所有新数据版本做回收操作,耗时很长。
  • 大查询回滚。产生了比较大的临时文件,删除临时文件可能需要等待IO资源,导致耗时边长。
  • DDL命令执行到最后的阶段,如果被Kill,需要删除中间过程的临时文件,也可能受IO资源影响。

关于kill客户端的误解

1.Ctil + C 是MySQL客户端另外启动一个连接,然后发送一个kill query命令。

2.如果库里面的表特别多,连接就会很慢。

  • 执行show databases;
  • 切到db1库,执行show tables;
  • 把这两个命令的结果用于构建一个本地的哈希表

真正耗时的步骤在第三步。我们感知的连接过程慢,其实并不是连接慢,也不是服务器慢,而是客户端慢。

如果在命令中加上-A,就可以关闭这个自动补全的功能,然后迅速返回。

3.-quick是一个更容易引起误会的参数,设置这个参数可能会降低服务端的性能。

客户端接受服务器返回结果方式两种

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

MySQL客户端默认采用第一种方式,如果加上-quick,就会使用第二种不缓存的方式。

-quick可以达到以下的三种效果

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