MySQL のバックアップと世代管理

要件

  • バックアップはmysqldump
  • バックアップファイルは1週間前のまで残して欲しい
    • 8日以上前のものは消す


簡単じゃんと思ったら案外罠があった。

設定

バックアップ
MAILTO="youraddress"
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/home/admin/bin

0 4 * * * mysqldump -u root -p rootpass --default-character-set=utf8 --hex-blob --single-transaction --master-data=2 dbname | gzip > /var/backup/mysql/dbname_`date +"\%Y\%m\%d_\%H"`.tar.gz


crontab において「%」はメタ文字なのでエスケープする。エスケープしていないと、次のエラーに遭遇する。

/bin/sh: -c: line 0: unexpected EOF while looking for matching ``'
/bin/sh: -c: line 1: syntax error: unexpected end of file

「第 6」フィールド (行の残りの部分) には実行されるコマンドを指定する。その行のコマンド部 (改行文字または % 文字まで) が /bin/sh (またはその crontab ファイルの SHELL 環境変数で指定されたシェル) によって実行される。コマンド中にパーセント記号 (%) がバックスラッシュ (\) によってエスケープされずに置かれていると、改行文字に置き換えられ、最初に現れた % 以降の全てのデータは標準入力としてコマンドに送られる。

Manpage of CRONTAB
世代管理
0 3 * * * find /var/backup/mysql/ -type f -name "dbname*.tar.gz" -mtime +7 -daystart | xargs rm


8日以上前のを消す場合は「+8」ではなく「+7」になる。また、世代管理のjob とバックアップのjob が実行される時間の前後関係が逆になっても8日以上前のバックアップファイルを消せるように「daystart」オプションを使う。


find のオプションはややこしい。「+mtime +1」としても、昨日修正されたファイルは検索対象にならない。このことは、英語のman に書かれている(日本語のmanには書かれていない)。

  • atime n

File was last accessed n*24 hours ago. When find figures out how many 24-hour periods ago the file was last accessed, any
fractional part is ignored, so to match -atime +1, a file has to have been accessed at least two days ago.


要は、何時間前という時間単位でみているのではなく、あくまで24-hour という単位でみている。そして、+n はn 以上ではなく、n より上を表す。また、少数部分は切り捨てる。
以上より、「+mtime +1」は1 24-hour より前となるので、36時間前(1.5 24-hour 前)に修正されたファイルは対象にならない。

n 24-hour よりも前ではなく、n 時間以上前に修正されたという観点で考えたい場合は、「-mtime +n」は(n + 1) * 24 時間以上前と考える。

分かりにくいので、図に書いておく。

X でfind を実行した時、F で修正したファイルが検出されるのは「-mtime 2」か「-mtime +1」か「-mtime +0」。

    1/1     1/2     1/3     1/4     1/5
... -|-------|--F----|-------|---X---|- ...
  -- 3 --|-- 2 --|-- 1 --|-- 0 --|          # n 24-hour ago
  - +2 --|-- 2 --|----- -2 ------|          # -n, n, +n の考え方

  ---|-- 3 --|-- 2 --|-- 1 --| 0 |          # --daystart を指定した場合


daystart とか、そこまで正確にやる必要があったのかと問われると、微妙(´;ω;`)