kill 命令之后MySQL都做了哪些

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 大家好,我是Leo。目前在常州从事Java后端开发的工作。上一篇我们介绍了线上数据库误删数据后,到底是跑路还是该如何解决!这一篇我们介绍一下为什么我们在调试SQL的时候会出现Kill不掉线程的情况。

思路


本篇文章的介绍思路以下图的思维导图为大纲。也有利于读者更好的分辨可读性!

image.png


为什么需要kill


测试

从测试方面考虑的话,就是我们在写SQL语句的时候。开始寻找不足点,有些时候会偶然间执行一个大事务,这个时候我们为了提升效率往往会直接干到这个查询

生产

随着数据量爆发式的增长,一些查询功能越来越慢的。而我们在调试一个功能的时候往往就是调试背后的SQL语句。还有一种情况就是,修改表结构的时候,由于数据量过大,我们会放弃普遍方法,会寻找一个快速的方法。

锁等待

比如发生死锁的时候,或者两个锁在争锁的时候。往往会需要kill。结束掉一个事务给事务回滚放行另一个事务


kill内部都做了啥


首先介绍两种kill写法吧

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

言归正传

前几篇文章我们介绍过,对一个表进行增删改查的时候,会在表上加一个读锁。这个时候用户虽然处于blocked状态,但是还拿着MDL读锁。如果线程直接被kill的话,读锁就没办法释放了。所以最理想的状态应该是,kill之后,让他做一些收尾工作,全部结束之后再结束掉线程。

那么它到底做了啥

  1. 把 session B 的运行状态改成 THD::KILL_QUERY(将变量 killed 赋值为 THD::KILL_QUERY);
  2. 给 session B 的执行线程发一个信号。

流程扩展

我们继续按照上述的流程作一个扩展。为什么要发信号呢?

举一个多用户请求的例子。如果用户A处于锁等待状态,如果只是把用户A的线程状态设置为THD::KILL_QUERY ,线程A并不知道这个状态变化,还是会继续等待。发一个信号的目的,就是让 用户A 退出等待,来处理这个 THD::KILL_QUERY 状态。

换言之。如果发现线程状态是THD::KILL_QUERY 才开始进入语句终止逻辑。


kill不掉是啥鬼


首先我们介绍一个参数,控制线程并发上限的这个参数innodb_thread_concurrency 举例说明一下

  • sessionA:select sleep(100) from t
  • sessionB:select sleep(100) from t
  • sessionC:select sleep(100) from t (blocked)
  • sessionD:kill query C
  • sessionE:kill C <=> kill connection C

通过上述5个用户的执行,我们先把他设置成set global innodb_thread_concurrency=2 可以看到

  1. sesssion C 执行的时候被堵住了; 因为并发查询线程上限了
  2. 但是 session D 执行的 kill query C 命令却没什么效果,
  3. 直到 session E 执行了 kill connection 命令,才断开了 session C 的连接,提示“Lost connection to MySQL server during query”,
  4. 但是这时候,如果在 session E 中执行 show processlist,你就能看到下面这个图。

image.png

由图得知,id=12 这个线程的 Commnad 列显示的是 Killed。也就是说,客户端虽然断开了连接,但实际上服务端上这条语句还在执行过程中。

为什么在执行 kill query 命令时,不像 update 语句一样退出呢?

在实现上,等行锁时,使用的是 pthread_cond_timedwait 函数,这个等待状态可以被唤醒。但是,在这个例子里,12 号线程的等待逻辑是这样的:每 10 毫秒判断一下是否可以进入 InnoDB 执行,如果不行,就调用 nanosleep 函数进入 sleep 状态。

也就是说,虽然 12 号线程的状态已经被设置成了 KILL_QUERY,但是在这个等待进入 InnoDB 的循环过程中,并没有去判断线程的状态,因此根本不会进入终止逻辑阶段。

而当 session E 执行 kill connection 命令时

  • 把 12 号线程状态设置为 KILL_CONNECTION;
  • 关掉 12 号线程的网络连接。因为有这个操作,所以你会看到,这时候 session C 收到了断开连接的提示。

show processlist 隐藏逻辑 如果一个线程的状态是KILL_CONNECTION,就把Command列显示成Killed。

所以在show processlist列表中会把connection改成killed,也就是我们看到的状态。

综上所述 kill无效的几种情况:

  • 线程没有执行到判断线程状态的逻辑

跟这种情况相同的,还有由于 IO 压力过大,读写 IO 的函数一直无法返回,导致不能及时判断线程的状态。

  • 终止逻辑耗时较长

从 show processlist 结果上看也是 Command=Killed,需要等到终止逻辑完成,语句才算真正完成。比如超大事务被kill需要做很多回收查找,大查询回滚,DDL命令。

我们可以对大查询回滚做一个扩展介绍,前几篇文章我们介绍过查询数据的时候,当数据量超过一个数量的时候我们会采用硬盘存储,如果小于这个数量的时候会采用内存存储。所以如果在磁盘中查询的时候。进行回滚!相应的磁盘页也会消耗一定的时间去关闭释放。


客户端与服务端的关闭问题


Ctrl+C 关闭的什么

客户端的操作只能操作到客户端的线程,客户端和服务端只能通过网络交互,是不可能直接操作服务端线程的。而由于 MySQL 是停等协议,所以这个线程执行的语句还没有返回的时候,再往这个连接里面继续发命令也是没有用的。实际上,执行 Ctrl+C 的时候,是 MySQL 客户端另外启动一个连接,然后发送一个 kill query 命令。

所以,你可别以为在客户端执行完 Ctrl+C 就万事大吉了。因为,要 kill 掉一个线程,还涉及到后端的很多操作。

数据表过多会影响性能吗

我们在第一篇文章就介绍了每个客户端和服务器建立连接时,做了哪些事情。比如TCP握手,用户校验,获取权限等

但实际上,当使用默认参数连接的时候,MySQL 客户端会提供一个本地库名和表名补全的功能。为了实现这个功能,客户端在连接成功后,需要多做一些操作:

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

最耗时的也就是第三步的哈希表构建了,也就是说,我们感知到的连接过程慢,其实并不是连接慢,也不是服务端慢,而是客户端慢

-A,-quick 可以跳过这个阶段。为什么这么说呢,我们可以介绍一下 -quick参数涉及的MySQL配置。

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

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

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

采用不缓存的方式时,如果本地处理得慢,就会导致服务端发送结果被阻塞,因此会让服务端变慢

扩展

为什么取名为quick呢?

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

综上所述:quick是提升客户端的性能,不是提升服务端的性能


总结


今天大概介绍了MySQL内部在kill线程的时候,都做了哪些操作以及强化了最开始的文章深度。

这里的文章深度主要是在哈希表构建的那一段。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
28天前
|
存储 关系型数据库 MySQL
初步了解MySQL数据库的基本命令
初步了解MySQL数据库的基本命令
28 0
|
2月前
|
存储 关系型数据库 MySQL
(十五)MySQL命令大全:以后再也不用担心忘记SQL该怎么写啦~
相信大家在编写SQL时一定有一个困扰,就是明明记得数据库中有个命令/函数,可以实现自己需要的功能,但偏偏不记得哪个命令该怎么写了,这时只能靠盲目的去百度,以此来寻找自己需要的命令。
106 28
|
2月前
|
SQL 关系型数据库 MySQL
MySQL删除表数据、清空表命令(truncate、drop、delete 区别)
MySQL删除表数据、清空表命令(truncate、drop、delete区别) 使用原则总结如下: 当你不需要该表时(删除数据和结构),用drop; 当你仍要保留该表、仅删除所有数据表内容时,用truncate; 当你要删除部分记录、且希望能回滚的话,用delete;
|
2月前
|
SQL 关系型数据库 MySQL
mysql性能调优:EXPLAIN命令21
【7月更文挑战第21天】掌握SQL性能调优:深入解析EXPLAIN命令的神奇用法!
38 1
|
2月前
|
存储 SQL Cloud Native
云原生数据仓库使用问题之运行MySQL命令发现中文内容变成了问号,该如何解决
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
3月前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用问题之 MySQL数据库中,执行delete命令删除数据后,存储空间通常不会立即释放,该如何优化
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
3月前
|
NoSQL 关系型数据库 MySQL
linux服务器重启php,nginx,redis,mysql命令
linux服务器重启php,nginx,redis,mysql命令
55 1
|
3月前
|
关系型数据库 MySQL 数据库
MySQL有哪些常用命令?
【6月更文挑战第12天】MySQL有哪些常用命令?
43 3
|
3月前
|
SQL 存储 关系型数据库
Mysql配置及常见命令
mysql 语法规范 SQL不区分大小写,但是建议关键字大写,表名、列名要小写; 每个句子写完,需要以分号结尾;
37 3
|
3月前
|
关系型数据库 MySQL 数据库
Mysql的基础命令有哪些?
Mysql的基础命令有哪些?
21 0

热门文章

最新文章