在 mysql 上执行了一句 drop database 半天没有完成,详细的慢查询日志如下,那当时MySQL 在做什么呢?
# Time: 2022-09-29Txx:xx:xx.176770+08:00
# User@Host: supper[supper] @ [127.0.0.1] Id: 21155
# Query_time: 1743.715215 Lock_time: 3.127027 Rows_sent: 0 Rows_examined: 0
SET timestamp=1664523652;
drop database app_db;
初步分析
对于这类要看 MySQL 在做什么的场景,最为直接就是执行 show processlist 命令,但是这个场景下只能看到语句在执行,至于执行到哪个函数了,这种更加细粒度的就回答不了了。
如果我们从 linux 内核层面看,还是可以发现 mysql 这个时候在执行哪些函数的;从而达到更加细粒度的确认 MySQL 在做什么,进而回答 drop database 为什么慢。
可以看到在删库时调用的是 mysql_rm_db 这个函数,而这个函数又调用了 mysql_rm_table_no_locks 函数,mysql_rm_table_no_locks 会去清理数据字典。
现在问题就来了,如果只是要清理数据字典!那删库为什么会慢呢?回答这个问题还需要更加深入地分析才行。
OFF-CPU
如果一个进程所依赖的所有资源都已经准备好,那它就可以被调度到 cpu 上执行。事情的一个反面是;如果一个进程在等待 IO 操作完成,那么它将处于一个阻塞状态,阻塞为 OFF-CPU 状态的一种。OFF-CPU 时间的长短将直接影响到响应的耗时。
对于这类阻塞场景的 cpu 堆栈采样我们可以通过 offcputime 这个工具来分析堆栈。
分析 OFF-CPU
我们可以通过 offcputime 把 OFF-CPU 状态时的 mysql 堆栈拿出来,我当前这个场景下画图之后看到的是这样的。
这里可以看到 drop table 要清理数据字典里面对应表的元数据,但是这个清理不只是删除一条记录这么简单,它还要把磁盘上的文件也清理掉。
我在分析清理文件的时候发现 vfs 并没有 rm_file 这样的 API ,而是采用“以写代删” 的方式来完成删除操作; 也就是说操作系统并不直接去删除文件,而是把文件系统里面对应的 inode 标记为“保留”来达到删除文件的目的。详细的可以看下面这个图。
结论
通过函数调用堆栈(火焰图)我们可以知道,删除一个库依赖于删除这个库下所有的表,删除一个表不只要清理数据字典还要删除磁盘文件。
前面的操作都还比较轻,耗时主要应该是花在了删除磁盘文件上。和当事人确认后得知他这个库里面,数据量并不大(不会超过 1GB);但是表特别多,一个逻辑表对应着 10000 个物理表,一套业务走下来,导致这个库里面有几十万个表,这个也就是 drop database 慢的原因了。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有