メルカリさんの記事。こんなに事細かに記事にしてくれるなんて有難い。
mysqldumpの問題点
–master-data
–master-data オプションではマスタにテーブルロックがかかる。
スレーブに対して実行した場合も同様なので、バックアップ専用のスレーブサーバを作成する。
–dump-slave
–dump-slaveオプションではバックアップ期間中にレプリケーションが停止する。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.5.4 mysqldump — データベースバックアッププログラム
ourdump
kazeburo/ourdump: simplified mysql40dump
スレーブに対して実行する mysqldump の wrapper script。
(文字で書くとわかりにくので、是非紙面の図で見てください)
- FLUSH TABLES WITH READ LOCK
- SHOW MASTER/SLAVE STATUS
- 子プロセスでexec: mysql dump –single-transaction
- 親プロセスでpipe経由でバックアップ読み込む
- CRAETE TABLEの文字列を検出
- READ LOCK を解放
- CHANGE MASTERステートメントを出力
ロック期間は、1-6 までなので1s以内に解放される。
すごいんだけど、、、なんか悲しい。
–single-transaction と –dump-slave が共存できる仕組みがあれば良いのかなぁ。
みんなこんなことやってるんだろうか。
XtraBackup
物理バックアップツール。
トランザクションログを監視し、全て記録。リストア時にバックアップしたデータファイルに対してトランザクションログのバックアップファイルを使うことで不整合を解消。
$ innobackupex --defaults-file=/usr/my.cnf --user=root --password=password --salve-info --no-timestamp backup_dir
Percona XtraBackup – MySQL, MariaDB, and Percona Server Hot Backup Software for InnoDB & XtraDB
これはよさそう。
リストア
STRICT_TRANS_TABLES
リストア時にMySQLが起動すればデータの矛盾がないことが保証される。
ただし、STRICT_TRANS_TABLES が含まれていないと、 破損したバックアップデータでも無効な値や適当な値がリストアされます。
へー。こわい。
5.6からはデフォルト。
ourdump
メルカリのリストアでは10〜20時間。
$ zcat dump.sql.gz | mysql -u root db
リストア実行後にポイントインタイムリカバリを手動で行おうとすると時間がかる。
夜間実行後に手動ポイントインタイムリカバリするとロスが発生する。
以下のようなshellで一気に実行しているとのこと。
# restore.sh #!/bin/sh set -e echo 'SET session sql_log_bin=0;' echo 'SET session long_query_time=30;' echo 'SET global innodb_flush_log_at_trx_commit=0;'; zcat dump.sql.gz echo 'SET session sql_log_bin=1' echo 'SET session long_query_time=0.1;' echo 'SET global innnodb flush log at_trx_commit=1;'; echo "CHANGE MASTER TO MASTER_LOG_FILE='ファイル名', \ MASTER_LOG_POS=ポジション, MASTER_HOST='マスタのIPアドレス', \ MASTER_PORT=3306, MASTER_USER='レプリケーションユーザー', MASTER_PASSWORD='パスワード';" echo 'start slave'
- バイナリログ、スローログをoff
- innodb_flush_log_at_trx_commit=0 でI/Oを減らす
$ sh restore.sh | mysql -uroot db
リストア直後はレプリケーションが追いついていない可能性もあるので、
スレーブで SHOW SLAVE STATUS を実行し、 Seconds_Behind_Master の値が0で継続していることを確認。
XtraBackup
メルカリのリストアでは1〜2時間。
新スレーブでMySQL停止後に実施。
$ innobackupex --defaults-file=/usr/my.cnf --apply-log backup_dir # --move-backで起動時にデータファイルとして扱えるようにMySQLのデータ領域に移動 # --force-non-empty-directories で上書き $ innobackupex --defaults-file=/usr/my.cnf ---move-back --force-non-empty-directories backup_dir $ chown -R mysql:mysql mysql_data_dir
あとは、MySQL起動後に start slave;
する。レプリケーション設定がmy.cnfでrelay_log_info_repository=tableとなっている必要がある。