乐趣区

关于gdb:第40问对进行中的-DDL-进行-kill-到底多久能响应

MySQL 中在运行一个 DDL , 此时咱们对这个 DDL 进行 kill , 那这个 DDL 多久会被 kill 掉?

要探讨这个问题, 咱们须要拆分问题: DDL 多久会被 kill 掉 = DDL 多久会开始 kill + DD L 的回滚收尾操作进行了多久

本试验只探讨如何察看: DDL 多久会开始 kill

试验

参考第 16 问, 咱们起一个数据库, 并让其在调试模式运行.

首先宽油起一个数据库实例:

改一下 start 脚本, 配置成调试模式:

重启数据库, 启动的时候减少 –debug 参数:

拜访数据库, 确认是调试版本:

创立一张简略的表, 塞 4 行数据进去:

当初写一个简略的 gdb 脚本:

这个脚本里, 咱们在 trx_is_interrupted 函数上设置了一个断点.

trx_is_interrupted 函数是 InnoDB 查看以后线程是否被 kill 的函数, 当调用这个函数时,InnoDB 才会查看以后是否有 kill 操作, 如果有, 则进行相应的解决.

(想晓得应该在哪个函数打断点, 能够寻求开发同学的帮忙)

当 gdb 运行到这个断点时, 咱们让 gdb 打印过后的堆栈, 以及一条分割线, 这样咱们就能看到是哪个流程调用了这个函数

而后开启 gdb , 这里应用了咱们之前写的脚本:

不需任何操作, 断点曾经按咱们的脚本增加好了

当初在 MySQL 中触发一个 alter :

找到咱们指定的 gdb 日志文件:

能够看到外面稀稀拉拉的写满了堆栈信息, 此时不要慌, 咱们将其复制到文本编辑器里, 一点一点来剖析:

第一个堆栈:

咱们认出了一个 read clustered index , 也就是读取聚簇索引的过程中, MySQL 会查看以后线程是否被 kill

第二个堆栈:

咱们认出了 BtrBulk , Btr 是 B-tree 的缩写, 也就是在对 B-tree 进行批量插入的过程中, MySQL 会查看以后线程是否被 kill

第三个堆栈:

这个堆栈不太容易辨认: 这是整个 DDL 的外层操作, 只晓得是重建索引 (之前两个堆栈也都是重建索引里的步骤)

找到该行最初, 标记了其代码地位为: row0merge.cc:4668 , 查看一下代码:

别怂, 咱们只意识 flush 就行了, 此处是重建索引最初的刷盘操作, 刷盘后查看以后线程是否被 kill

第四个和第五个堆栈:

最初两个堆栈相似, 都是将 online DDL log 回放到新表中时, 进行查看

综合以上试验, 咱们得出初步论断:

对于本试验中的 DDL , MySQL 在以下几处查看了以后线程是否被 kill:

  1. 从旧表中 读取聚簇索引的过程
  2. 向新表中 写入索引的过程
  3. 重建索引时, 刷盘后进行查看
  4. 将 online DDL log 回放到新表的过程
  5. 如果在这四个过程中, 产生了 kill , 那 DDL 操作很快就会开始回滚.

但这个论断依然不能满足咱们, 到底是一个过程中哪个步骤才会查看 kill 呢?

翻一下官网文档, 对 kill 行为的形容如下:

能够看到 对于少量数据操作, MySQL 会在一部分数据处理后查看线程是否被 kill

咱们的试验论断中, 1/2/ 4 三个过程都波及了大量数据的操作, MySQL 将其分为若干局部, 在解决每一部分后进行查看也非常正当

须要留神的是: 对 DDL 进行 kill , 并不总能在正当的工夫内触发: 比方对数据的解决变慢, 或者在堆栈 3 中 flush 变慢, 此时只能等到检查点才会进行查看

小贴士

本试验中, 进行的 DDL 操作, 其操作类型如图:

对于其余类型的 DDL , 大家可通过试验自行摸索.


对于 MySQL 的技术内容,你们还有什么想晓得的吗?连忙留言通知小编吧!

退出移动版