MySQL Drop表的逻辑顺序
- 清除buffer pool中的缓存信息,需要在每个buffer pool实例中搜索到该表对应的数据页,将数据页从flush队列中移除
在移除过程中会对每个buffer pool持有全局锁
,如果要移除的数据页过多,遍历时间则较长,导致其他事务被阻塞甚至数据库hang住- 可以增加innodb_buffer_pool_instances的数量来降低每个buffer pool的大小
buffer pool过大也同样会导致遍历的时间过长
- 清除过程中还涉及对
AHI(自适应hash索引)中对该表的数据
,AHI占用总buffer pool的1/16的大小- 在并发小且数据库不是特别大的场景下建议关闭AHI特性
- set global innodb_adaptive_hash_index=off
- 在并发小且数据库不是特别大的场景下建议关闭AHI特性
- 删除磁盘上对应的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"
- 脚本输出示例