誰もが一度は「差分だけバックアップできたらな」と思うところですが、なんとXtraBackupには差分バックアップがあるのです。
巨大に膨れ上がったデータベースの更新分だけを抽出して、別サーバで完全体に戻しておく、といったことができるため、より効率的なバックアップを行うことができます。少なくともバイナリログによる差分バックアップとかダサいことはやる必要がなくなります。
メリットとデメリット
メリット
デメリット
差分バックアップ
バックアップ取得
まるごと取得したバックアップに対して、差分だけを別のディレクトリに保存していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# まず全体 mkdir -p /backup/base xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/base/ # 最初の全体分をベースにして1つ目の差分 mkdir /backup/increment-01 xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/increment-01/ \ --incremental-basedir=/backup/base/ # 1つ前の差分をベースにして2つ目の差分 mkdir /backup/increment-02 xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/increment-02/ \ --incremental-basedir=/backup/increment-01/ |
ファイル種類
ベースは通常通り ibdata と .ibd ファイルで保存されますが、差分は同ファイルに .delta .meta の拡張子がついたデータが保存されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# ls -1 /backup/base/* /backup/base/ibdata1 /backup/base/xtrabackup_checkpoints /backup/base/xtrabackup_logfile /backup/base/sbtest: sbtest.ibd test.ibd # ls -1 /backup/increment-01/* /backup/increment-01/ibdata1.delta /backup/increment-01/ibdata1.meta /backup/increment-01/xtrabackup_checkpoints /backup/increment-01/xtrabackup_logfile /backup/increment-01/sbtest: sbtest.ibd.delta sbtest.ibd.meta test.ibd.delta test.ibd.meta |
容量
差分を取る前に数回更新クエリを実行しただけですが、ベースが1GBに対して、差分は1MBに満たないサイズになっています。
1 2 3 4 |
# du -sh /backup/* 1.1G /backup/base 720K /backup/increment-01 740K /backup/increment-02 |
チェックポイント
それぞれの xtrabackup_checkpoints ファイルにはLSNの値が記録されています。from_lsn から to_lsn までが差分として記録した範囲です。last_lsn はxtrabackup終了時のチェックポイントであり、取得中に更新クエリが実行されていると to_lsn より値が大きくなることがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# cat /backup/base/xtrabackup_checkpoints backup_type = full-backuped from_lsn = 0 to_lsn = 1135932766 last_lsn = 1135932766 # cat /backup/increment-01/xtrabackup_checkpoints backup_type = incremental from_lsn = 1135932766 to_lsn = 1135936218 last_lsn = 1135938198 # cat /backup/increment-02/xtrabackup_checkpoints backup_type = incremental from_lsn = 1135936218 to_lsn = 1135939188 last_lsn = 1135943164 |
リストア
まずベースを –prepare –apply-log-only してから、ベースに対して、差分を適用していきます。仕上がったベースディレクトリが完成品となり、続きは通常のリストアと同じ手順になります。
1 2 3 4 5 6 7 8 9 10 |
# ベースのprepare xtrabackup --prepare --apply-log-only --target-dir=/backup/base # ベースに差分1つ目を適用 xtrabackup --prepare --apply-log-only --target-dir=/backup/base --incremental-dir=/backup/increment-01 # さらに2つ目を適用 xtrabackup --prepare --apply-log-only --target-dir=/backup/base --incremental-dir=/backup/increment-02 # できた /backup/base をデータディレクトリとして利用する |
正常性の確認
差分で取得してベースに適用したデータが、本当に正しいデータとなっているかを確認します。以下のような手順でバックアップ取得とクエリ実行を行い、最初のベースに差分を適用したデータと、最後に再取得したベースをmd5で比較します。なんとなくログファイルを 1MB×2 と極小にして実験しています。
バックアップ取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# お掃除 rm -R /backup/* # ベース mkdir /backup/base_before xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/base_before/ # 更新クエリを流しっぱ sysbench --mysql-host=localhost --mysql-user=test --mysql-password=test \ --test=oltp --oltp-table-size=4400000 --oltp-index-updates run & # 1, 2 回目の差分 mkdir /backup/increment-01 xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/increment-01/ \ --incremental-basedir=/backup/base_before/ mkdir /backup/increment-02 xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/increment-02/ \ --incremental-basedir=/backup/increment-01/ # 更新クエリ停止 pkill sysbench # 3 回目の差分 mkdir /backup/increment-03 xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/increment-03/ \ --incremental-basedir=/backup/increment-02/ # 新規バックアップ mkdir /backup/base_after xtrabackup --backup --datadir=/fio/mysql/ --target-dir=/backup/base_after/ |
リストア
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 最初のベース xtrabackup --prepare --apply-log-only --target-dir=/backup/base_before/ # 差分1 xtrabackup --prepare --apply-log-only --target-dir=/backup/base_before \ --incremental-dir=/backup/increment-01 # 差分2 xtrabackup --prepare --apply-log-only --target-dir=/backup/base_before \ --incremental-dir=/backup/increment-02 # 差分3 xtrabackup --prepare --apply-log-only --target-dir=/backup/base_before \ --incremental-dir=/backup/increment-03 # 新規バックアップ xtrabackup --prepare --apply-log-only --target-dir=/backup/base_after/ |
比較
ibdataと更新したテーブルの.ibdをmd5で比較してみます。
1 2 3 4 5 6 7 8 9 10 11 |
# Before md5sum /backup/base_before/ibdata1 0c24044ad9519d3d12bdb5a7ad06b202 md5sum /backup/base_before/sbtest/sbtest.ibd 634a684b05f5df2325a6ebd00215a6ac # After md5sum /backup/base_after/ibdata1 0c24044ad9519d3d12bdb5a7ad06b202 md5sum /backup/base_after/sbtest/sbtest.ibd 634a684b05f5df2325a6ebd00215a6ac |
差分3まで適用したバックアップと、新規バックアップのハッシュ値が一致したので、差分システムに問題ないことが判明しました。
使いどころ
普通のバックアップは、1日に1回の全体バックアップで、別サーバに転送しておいて、最新何日か分と月初めなど特定の日にちを除いて間引きする、といったものだと思います。それに対して差分バックアップはどう使うべきか考えてみます。
例えば極端に、最初の1回を除いて残り全て差分で保存したらどうなるか。
1年後にバックアップを必要とした時、365個の差分を割り当ててからリストアすることになります。これだと数が多いし、1年間の差分が全て正常かなんて自信がもてないでしょう。せめて、差分を取得するたびに別サーバで差分を適用して常に完成版を作っておくべきと思いますが、それでもその完成版が正常なバックアップであることを定期的に証明したいだろうし(※1)、世代管理という機能を失うのであまり上手くありません。
日曜日だけ全体バックアップにして、他は差分にするといった落とし所もありますが、本番サーバで全体バックアップを実行してしまうとあまり通常の方法と変わりありません。
※1 差分の正常性を疑うなら、通常の全体バックアップも疑うべきで、逆に考えると差分も信じるしかないのですが・・・差分だとやはり心理的に怖さがあるので大丈夫だと確認できる仕組みを用意したいところです
重要なポイントとして、差分のウマ味は、本番サーバでの処理時間と容量が激減し、別サーバへの転送時間も短くなることなので、その部分は常に固定にしたいと考えます。
なので例えば、本番サーバでは常に差分のみ取得して転送し、別サーバでは適用を行いつつ日曜には完成版のコピーを保管しておき、3ヶ月以上経過したものは削除する。これだと12個の完成版と、3ヶ月分の差分ファイルで済み、特定の日にちのデータが欲しい時用の世代管理にもなります。あとはディスク容量に応じて間引きやコピー頻度を調整するだけです。
こうなると、あとは差分適用バックアップの正常性のみが問題になります。
とはいえ、データの中身を照会しての完全一致確認など不可能ですから、信頼してしまうのも1つの手だと思います。
ハッシュでの確認が簡単ですが、常に更新される本番データでそれはできないので、サービスメンテナンスのタイミングで
とオペレーションを増やせば定期的に確認できます。この方法は、作業量増加により人災が起こる可能性も増えますが、それよりもバックアップに対する姿勢と質が強固になるメリットがあると思います。
落とし所が難しいですが、サービスが大きくなると必須な仕組みにもなりうるので、お試ししておくと良いのではないでしょうか。