読者です 読者をやめる 読者になる 読者になる

恥知らずのウェブエンジニア -web engineer, shameless

これは一歩を踏み出すことができない者たちのブログ

続 サービス稼働中に不要なDBのテーブルを安全に削除する方法

mysql

前回の続編です。

youngforever.hatenablog.com

前回まで

前回はdropするテーブルのデータファイルにハードリンクを貼ることでdrop時にファイル削除されることを回避することができました。

しかしioniceで優先度を下げても、巨大なテーブルのデータファイルなどを削除する際はCPU使用率など見る限り負荷がかかっていました。 ioniceは緩やかに削除というより実行の順番の優先度を下げるという挙動のようです。

なので、次に負荷をかけずに巨大なファイルを削除するということで下記を参考にさせてもらいました。 www.nari64.com

truncateコマンドで徐々にファイルサイズを削り、小さくした後に削除するというやり方です。

安全にテーブルdropする手順

まとめて下記のような流れで処理しました

  • 削除前に念のため、dump取る
mysqldump DB_NAME hoge_table > dump_hoge_table.sql
  • 対象テーブルのデータファイルにハードリンクを貼る
ln /usr/local/mysql/data/DB_NAME/hoge_table.ibd /root/hoge_table.ibd
ln /usr/local/mysql/data/DB_NAME/hoge_table.frm /root/hoge_table.frm
  • drop tableを実行
mysql DB_NAME -e "DROP TABLE hoge_table"
  • ハードリンクを貼ったファイルをtruncateコマンドで徐々にサイズを削った後に、rmを実行
//ファイルサイズ取得
$file_size = 0;
$cmd    = "du -m {$file_path} | awk '{print $1}'";
exec($cmd, $output, $ret);
if($ret == 0) $file_size = $output[0];

//truncateで徐々に切り詰める
if($file_size){
  $i = 1;
  while ($i <= $file_size) {
    $tmp_size = $file_size - $i;
    $cmd    = "truncate -s {$tmp_size}M {$file_path}";
    exec($cmd, $output, $ret);
    //0.1sec sleep
    usleep(100000);
    $i++;
  }
//ファイル削除
$cmd = "rm {$file_path}";
$res = exec($cmd, $output, $ret);

的な感じで、稼働中の本番DBで百数テーブル、260GB程度削除しましたが、負荷なく実行できました。 そこそこ時間はかかりますが、、、truncateの部分はもっと攻めて良さそうですがそれはまた次の機会に・・・

これでどんどん不要なテーブル消せますね!

感謝致します。

f:id:ogataka50:20151020111355j:plain