Database JUNKY

MySQL,MariaDBを中心としたブログです

MySQL: 不要なバイナリログを削除(パージ)する shell

MySQLレプリケーションってMASTERが吐き出すバイナリログをリレーしてレプリケーションをするわけなのですが、そのままにしておくとMasterにバイナリログがどんどん溜っていきディスクを圧迫してきます。自動削除の機能もあるのだけど・・MASTERのバイナリログをSLAVEが処理しているかなんて見ないで削除してしまう(そもそもレプリケーションのための設定ではない)ので、ちょっと怖いなあーといった感じですね。 そんなこんなで、全てのSLAVEが処理済のバイナリログを削除(purge)するshellを作ってみました。最近shellばっかり作っているな・・。

バイナリログ自動削除オプションは、例えば以下のような設定をMASTERのmy.cnfに加えてあげることによって、下記例ですと10日以上経過したログファイルを削除するってオプションなんですが、ここでは今回触れません。 [shell] set-variable = expire_logs_days=10 [/shell]

そこでこんなshellを作ってみました。

[shell]

cat master_binlog_purge.sh


!/bin/bash

#

スレーブのbin-log進捗状況を確認し、処理済みのbinlogをパージする

#

tmp ディレクト

_workdir=/tmp

db_config (マスター、スレーブ共にアカウントは同じことを前提)

dbuserid=root dbpasswd=rootpassword

master 情報を記載する

_master=192.168.101.44

slave 情報を記載する

slavegrp=() slavegrp=("${slavegrp[@]}" "dbm01") slavegrp=("${slavegrp[@]}" "dbm02") slavegrp=("${_slavegrp[@]}" "dbm03")

bin-logのファイル名を取得する

_binlog=()

テスト用(実際の利用時は消してください)

log_bin="mysql-bin.999999" echo $log_bin > ${_workdir}/sort.in

各SLAVEのMASTER_LOG_FILEのファイル名を取得する

for *1 do log_bin=$(mysql -h ${slavegrp[$I]} -u ${dbuserid} -p${dbpasswd} -e 'show slave status\G;' | grep -i " Master_Log_File" | echo awk -F: '{print $2}';) echo $log_bin >> ${_workdir}/sort.in done

ファイル${workdir}/sort.inを数値のソートし、ソート結果をファイル${workdir}/sort.outに出力

sort -r ${workdir}/sort.in > ${workdir}/sort.out  <--- 降順ソートはこれ

sort ${workdir}/sort.in > ${workdir}/sort.out

ファイル${_workdir}/sort.outの内容を読み込み、配列に格納

while read SORTFILE do binlog=("${binlog[@]}" $SORTFILE) done < ${_workdir}/sort.out

実運用時は不要(チェック用)

for *2 do echo ${binlog[$I]} done

マスターDBのログをPURGEする

mysql -h ${master} -u ${dbuserid} -p${dbpasswd} -e "PURGE MASTER LOGS TO '${binlog[0]}';"

テンポラリファイルの削除

rm -f ${workdir}/sort.in rm -f ${workdir}/sort.out

exit 0

[/shell]

ざっくりした説明ですと、複数のスレーブのステータスを参照して、一番若い番号のbinlogを抽出して、その番号でマスタのバイナリログをパージするといったshellです。

MASTERで手動で行うPURGEコマンドはこんな感じ [sql] mysql> PURGE MASTER LOGS TO 'mysql-bin.000020'; Query OK, 0 rows affected (2 min 8.51 sec) [/sql] これだと、 mysql-bin.000020 以前(つまりmysql-bin.000020は削除されない)のバイナリログが削除されるわけです。単純にはこれをしたいがために、スレーブのバイナリログの進行状況を確認するのですが、複数のスレーブを確認するのは面倒なので、shell化しましたよ!って話でした。

*1: I = 0; I < ${#slavegrp[@]}; ++I

*2: I = 0; I < ${#binlog[@]}; ++I