MySQL 中有两个 kill 命令:
1)kill query + 线程 id,表示终止这个线程中正在执行的语句;
2) kill connection + 线程 id,这里 connection 可缺省,表示断开这个线程的连接,如果这个线程有语句正在执行,也是要先停止正在执行的语句。
kill connection本质上只是把客户端的sql连接断开,后面的执行流程还是要走kill query的。一般kill query是发生在客户端执行ctrl+c的时候。平时紧急处理直接用kill + thread_id。在kill query无效的时候,其实kill connection也是无效
大多数情况下,kill query/connection 命令是有效的。
1)执行一个查询的过程中,发现执行时间太久,要放弃继续查询,这时我们就可以用 kill query 命令,终止这条查询语句。
2)语句处于锁等待的时候,直接使用 kill 命令也是有效的
有这样奇怪的现象:
使用了 kill 命令,却没能断开这个连接。再执行 show processlist 命令,看到这条语句的 Command 列显示的是 Killed。
kill 并不是马上停止的意思,而是告诉执行线程,这条语句已经不需要继续执行了,可以开始“执行停止的逻辑了”。这跟 Linux 的 kill 命令类似,kill -N pid 并不是让进程直接停止,而是给进程发一个信号,然后进程处理这个信号,进入终止逻辑。
kill时,一个语句执行过程中有多处“埋点”,在这些“埋点”的地方判断线程状态
1)如果发现线程状态是 THD::KILL_QUERY,才开始进入语句终止逻辑;
2)如果处于等待状态,必须是可以被唤醒的等待,否则不会执行到“埋点”;
3)语句从开始进入终止逻辑,到终止逻辑完全完成,是有一个过程的。
kill 无效情况
1)线程没有执行到判断线程状态的逻辑,等到满足进入 InnoDB 的条件后,才能判断线程状态。比如因为InnoDB 的并发线程上限数的限制,可以临时调大 innodb_thread_concurrency 的值,或者停掉别的线程,让出位子给这个线程执行
2)由于 IO 压力过大,读写 IO 的函数一直无法返回,导致不能及时判断线程的状态。
3)终止逻辑耗时较长
3.1)超大事务执行期间被 kill。这时候,回滚操作需要对事务执行期间生成的所有新数据版本做回收操作,耗时很长。
3.2)大查询回滚。如果查询过程中生成了比较大的临时文件,加上此时文件系统压力大,删除临时文件可能需要等待 IO 资源,导致耗时较长。
3.3)DDL 命令执行到最后阶段,如果被 kill,需要删除中间过程的临时文件,也可能受 IO 资源影响耗时较久。
客户端通过 Ctrl+C 命令,其实在客户端的操作只能操作到客户端的线程,客户端和服务端只能通过网络交互,是不可能直接操作服务端线程的。执行 Ctrl+C 的时候,是 MySQL 客户端另外启动一个连接,然后发送一个 kill query 命令。
客户端连接慢
每个客户端在和服务端建立连接的时候,需要做的事情就是 TCP 握手、用户校验、获取权限。跟库里面表的个数无关。
客户端在连接成功后,需要多做一些操作:
1)执行 show databases;
2)切到 db1 库,执行 show tables;
3)把这两个命令的结果用于构建一个本地的哈希表。
第三条命令比较耗时,感知到的连接过程慢,其实并不是连接慢,也不是服务端慢,而是客户端慢。如果在连接命令中加上 -A,就可以关掉这个自动补全的功能(使用 Tab 键自动补全表名或者显示提示),然后客户端就可以快速返回了。
MySQL 客户端发送请求后,接收服务端返回结果的方式有两种:
1) 一种是本地缓存,也就是在本地开一片内存,先把结果存起来。如果你用 API 开发,对应的就是 mysql_store_result 方法。
2) 另一种是不缓存,读一个处理一个。如果你用 API 开发,对应的就是 mysql_use_result 方法。
MySQL 客户端默认采用第一种方式,而如果加上–quick 参数,就会使用第二种不缓存的方式。–quick 是让客户端变得更快
达到以下三点效果:
1)跳过表名自动补全功能。
2)mysql_store_result 需要申请本地内存来缓存查询结果,如果查询结果太大,会耗费较多的本地内存,可能会影响客户端本地机器的性能;
3)不会把执行命令记录到本地的命令历史文件。




