kill命令
kill使用
- 一个是kill query +线程id,表示终止这个线程中正在执行的语句;
- 一个是kill connection +线程id,这里connection可缺省,表示断开这个线程的连接,当然如果这个线程有语句正在执行,也是要先停止正在执行的语句的。
kill 执行流程
- 修改session X的运行状态为THD:KILL_QUERY
- 给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需要申请本地内存来缓存查询结果,如果查询结果太大,会耗费较多的本地内存,可能会影响客户端本地机器的性能;
- 不会把执行命令记录到本地的命令历史文件。