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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM