Database-Mysql-生产环境中删除大表

首先,我们来看在Mysql中删除表时删除线程会做哪些工作。
1、清除Buffer Pool缓冲
在drop table时,innodb引擎会清理该表在每个buffer pool实例中中对应的数据块页面,为了避免对系统的影响,这里的清除操作并不是真正的flush,而是将涉及到的页面从flush队列中摘除。但在摘除过程中,删除进程会持有每个buffer pool的全局锁,然后搜索这个buffer pool里对应的页面以便从flush list中删除。如果在buffer pool中需要被搜索并删除的页面过多,那么遍历时间就会增大,这就导致了其他事务操作被阻塞,严重时可导致数据库夯住。
注意:从flush list中摘除对应的页面并不是真正的删除,它会暂时存在buffer pool的空闲池中,以便重新利用。
2、删除对应的磁盘数据文件ibd
在删除数据文件时,如果数据文件过大,删除过程会产生大量的IO并耗费更多的时间,造成磁盘IO开销飙升,CPU负载过高,影响其他程序运行。

清除Buffer Pool缓冲这一过程在源码中是由buf_flush_or_remove_pages函数实现,在删除大表时改动源码这种想法并不现实,因此只能在删除对应的磁盘数据文件ibd这一过程中需求解决方法。

这里需要说到Linux系统中程序通过文件名打开文件获取内容的过程和硬链接的概念:
在这里插入图片描述

链接是为了解决文件共享使用的问题,其有隐藏文件路径、增加权限安全及节省存储等好处。
一个 inode 号对应着多个文件名,则称这些文件为硬链接,相当于给这个文件起了别名或引用。
在硬链接中,执行删除文件操作时,系统会检测是否还有其他文件名指向该文件的inode,如果是,系统只会删除该文件名对应的引用,而不会真正的删除数据。
如果是windows系统,使用mklink工具。

所以在mysql中drop table时我们可以使用硬链接的方式对数据文件做引用,这样在mysql层面删除表时并不会真正的删除数据文件。

假设我们要删除test表,首先先给数据文件test.ibd建立一个硬链接:

ln /data/mysql/mytest/test.ibd /data/mysql/mytest/test.ibd.hdlk

此时,我们可以看到:
-rw-r----- 2 mysql mysql 2158221066240 7 18 15:46 test.ibd
-rw-r----- 2 mysql mysql 2158221066240 7 18 15:46 test.ibd.hdlk

我们可以看到 test.ibd和test.ibd.hdlk 的inode均为2.

这时就可以在mysql中删除表test:
mysql> drop table test;
注意:这个时候test对应的数据文件并没有真正删除,磁盘空间并没有释放。

接下来就是删除test.ibd.hdlk文件的操作。
因为直接rm会对系统产生影响,不符合我们的初衷。因此我们使用truncate命令来做,truncate命令对磁盘IO,CPU负载几乎无影响。

删除脚本如下:

TRUNCATE=/usr/local/bin/truncate
for i in `seq 2010 -10 10 `; 
do 
  sleep 4
  $TRUNCATE -s ${i}G /data/mysql/mytest/test.ibd.hdlk 
done
rm -rf /data/mysql/mytest/test.ibd.hdlk ;

从2010G开始,每次缩减10G,停4秒,继续,直到文件只剩10G,最后使用rm命令删除剩余的部分。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值