首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MySQL - 删库了,但是很慢

MySQL - 删库了,但是很慢

作者头像
初代庄主
发布于 2022-12-19 19:25:46
发布于 2022-12-19 19:25:46
3.4K0
举报
文章被收录于专栏:初代庄主初代庄主

在 mysql 上执行了一句 drop database 半天没有完成,详细的慢查询日志如下,那当时MySQL 在做什么呢?

代码语言:javascript
复制
# 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 慢的原因了。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档