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"
- 腳本輸出示例

