MySQL物理删除大表文件的方式

MySQL Drop表的逻辑顺序

  1. 清除buffer pool中的缓存信息,需要在每个buffer pool实例中搜索到该表对应的数据页,将数据页从flush队列中移除
    • 在移除过程中会对每个buffer pool持有全局锁,如果要移除的数据页过多,遍历时间则较长,导致其他事务被阻塞甚至数据库hang住
      • 可以增加innodb_buffer_pool_instances的数量来降低每个buffer pool的大小
    • buffer pool过大也同样会导致遍历的时间过长
  2. 清除过程中还涉及对AHI(自适应hash索引)中对该表的数据,AHI占用总buffer pool的1/16的大小
    • 在并发小且数据库不是特别大的场景下建议关闭AHI特性
      • set global innodb_adaptive_hash_index=off
  3. 删除磁盘上对应的ibd文件
    • 如果磁盘文件过大,会占用大量IO
      • 使用Linux硬链接方式延迟删除物理文件

Drop操作示例

-- 先创建硬链接
ln sbtest1.ibd sbtest1.ibd.hdlk

-- 在数据库层执行drop
drop table sbtest.sbtest1;

清除硬链接磁盘数据

由于测试环境sbtest库较小,下面用dd快速造一个10G的大文件模拟磁盘数据删除操作

  • dd if=/dev/zero of=/tmp/test_data bs=1M count=10000
  • 分批次删除磁盘数据脚本示例
#!/bin/bash

## 记录执行开始时间
beginTime=`date +'%Y-%m-%d %H:%M:%S'`

## 指定文件路径及名称
truncateFile=/tmp/test_data

## 指定文件大小,单位GB
sizeOfGigaByte=10

## 判断文件是否存在,不存在直接退出
if [ ! -f ${truncateFile} ];then
    echo "${truncateFile} File does not exist!!,Please Check Again!"
    exit 1
fi

## 循环删除,表示总共10G,按每-1G来truncate数据,直到文件只剩1G后结束循环
for i in `seq ${sizeOfGigaByte} -1 1`;
do
    ## 每执行一次删除停1秒,减少IO压力
    sleep 1
    remain=${i}
    echo "`date +'%Y-%m-%d %H:%M:%S'` The remaining data: ${remain}G"
    truncate -s ${i}G ${truncateFile}
done

## 最后删除剩下的1G数据库
rm -rf ${truncateFile}
echo "${truncateFile} Has been deleted"

endTime=`date +'%Y-%m-%d %H:%M:%S'`

echo "Total Running Time(s):" $(($(date --date="$endTime" +%s)-$(date --date="$beginTime" +%s)))"s"
  • 脚本输出示例
转载请说明出处 |QQ:327488733@qq.com
原文地址:https://www.cnblogs.com/zhenxing/p/15102469.html