Ⅰ、背景
我们常常的生产环境中遇到清理归档表备份表的需求,一般来说这种表体积都比较大,ibd文件占很大磁盘空间,如果我们直接drop表,会带来db层和os层io两个层面的抖动,进而影响业务。
Ⅱ、数据库层怎么做
目前MySQL默认是开启AHI功能的,这种情况下,删表的时候,InnoDB存储引擎会把对应表在缓冲池中的数据都刷到磁盘上,释放空间。如果缓冲池比较大,扫描脏页会比较耗时,这时候整个实例都会被hang住,进而对线上系统造成一定的影响。 这个问题在新版的MySQL8.0中已经修复了,可以直接drop,如果我们用的还是5.7,则可以在删表之前关闭AHI,删完再打开。
set global innodb_adaptive_hash_index = 0/1;
Ⅲ、OS层怎么做
MySQL层操作drop最终会触发os层删除对应表的ibd文件,如果ibd文件较大会产生io抖动也是会影响业务的。这里我们利用Linux硬链接的原理来巧妙避开这个问题。给文件创建硬链接,则多个文件指针指向了同一个文件,如果删除其中一个文件,都不影响真实文件,只会将引用数减1,当引用数为1的时候删文件,文件才会被真正删除。
我们先给对应表的ibd文件做一个硬链接,再去drop表,此时os层只是删除了指针,并没有一次性删除实际文件,很轻,但此时这个文件已经和数据库脱离关系了。然后我们再用truncate命令慢慢将这个硬链接删掉。
ln xxx.ibd xxx.ibd.hl
drop table;
for
truncate -s xxxG xxx.ibd.hl
rm xxx.ibd.hl
Ⅳ、精细化处理流程
- 计算对应表的脏页在缓冲池中的比例,设定阈值,低于这个阈值才操作
- 选择在业务低峰期操作
- 删表前关闭AHI功能(8.0.23之后可以不做这一步)
- 给ibd文件做硬链接
- drop对应表
- truncate残留的硬链接文件
- 开启AHI
本人才疏学浅,第一步如何计算这个比例暂时还不知道怎么弄,据了解大厂好像会做这个,如果哪位大神会的请在评论区留言,非常感谢!