Help us understand the problem. What is going on with this article?

Percona xtrabackupを使用したバックアップ、リストアでハマったこと

More than 3 years have passed since last update.

10月からリブセンスに入社した @takemotto です。
この記事は 2015年 Livesense Advent Calendar 第21日目です。
現在、本番DBと開発DBのデータ同期にxtrabackupの導入を進めています。
本日は実際にxtrabackupを使ってみて、私が「ハマった」ことをご紹介したいと思います。

環境や前提条件

CentOS 6.4
MySQL 5.6.12
xtrabackup 2.2.11
lz4がインストールされていること

構築方法

弊社一部環境ではmroogaを使用しているため、弊社先輩方の記事をありがたく参考にさせていただきました。あざます。
Percona xtrabackupでmroongaをバックアップ・リストア
CentOS6.xに最新版のMySQL5.6とmroongaを最速でRPMインストールする方法

使い方

Xtrabackupバックアップ、リストア手順

まずバックアップの使い方を簡単にご紹介します。
今回のバックアップはxtrabackupコマンドではなく、そのラッパーツールであるinnobackupexコマンドを使用します。
こんな感じです。

$ sudo innobackupex --user=root --stream=xbstream --parallel=4  /var/tmp/xtrabackup/ | lz4 -9 > /var/tmp/<ファイル名>.xbstream.lz4

これでフルバックが取得できます。圧縮しているのは、バックアップファイルをリストア先に転送するためです。
圧縮をかけないと日付のフォルダが作成されます。ちなみに圧縮にはlz4を使用しています。
当初、pigzを使用していましたがCPUリソースをフルに使うし気軽に検証ができないことと、
lz4がいいかも!といった流れになったのでlz4を使用しています。
この辺りの検証はこちらの記事を参考にさせていただきました。使用しているオプションもこちらの記事を参考にしています。
Percona XtraBackupの抽出と圧縮の並列処理

データベース単位でバックアップしたい場合は、「--database」オプション使用すればOKです。
指定しなければすべてのDBがバックアップされます。

$ sudo innobackupex --user=root --stream=xbstream --parallel=4 --databases='<DB名>' /var/tmp/xtrabackup/ | lz4 -9 > /var/tmp/<ファイル名>.xbstream.lz4

リストアしたい場合は、こんな感じです。

# /var/tmpに上記手順で取得したバックアップがある前提で
$ cd /var/tmp
$ mkdir xtrabackup
$ cd xtrabackup

## 解凍処理
$ lz4 -d ../<ファイル名>.xbstream.lz4 | xbstream -x -v

するとMySQLのデータディレクトリ配下のファイルが展開されます。
次にリストアです。
事前にmysqlを停止して、mysqlのデータディレクトリ(今回の場合だと/var/lib/mysql)を退避もしくは削除しておく必要があります。

$ cd ../
## WAL(Write Ahead Log)を適用
$ sudo innobackupex --user=root --apply-log xtrabackup/
・・・・・
151218 10:55:06  innobackupex: completed OK!

## リストア開始
$ sudo innobackupex --copy-back xtrabackup/
innobackupex: Finished copying back files.

151218 11:31:05  innobackupex: completed OK!

# 起動
$ sudo chown -R mysql:mysql /var/lib/mysql
$ sudo service mysql start
Starting MySQL... SUCCESS!

以上でリストア完了です。

ハマったこと

本番環境DBと開発環境DBに差異がある問題

たとえば本番環境には「A,B」という2つのDB、開発環境には「A,B,C」という3つDBがあったとします。
ここで言うDB「C」は個人用の開発DBだったり。
上記手順では、開発環境のデータディレクトリを一旦退避させ、copy-backコマンドでリストアしているため、リストアした際に開発環境DBの「C」が消えてしまいます。

その対策として見つけた方法がテーブル単位でバックアップリストアする方法です。
バックアップする際に指定したテーブルだけをバックアップ、リストアすることで、その他のDB消されることはありません。
こちらの記事を参考にしました。
Percona XtraBackupの機能紹介 (2) テーブル単位で抽出

手順はこんな感じにしました。

## バックアップ
$ sudo mysqldump -uroot --no-data <DB名> > /var/tmp/<DB名>_mysql_no_data.sql
$ sudo xtrabackup --backup --datadir=/var/lib/mysql --target-dir=/var/tmp/export_tables --tables="^<DB名>[.]*.*"
$ sudo xtrabackup --prepare --target-dir=/var/tmp/export_tables --export

## リストア
$ myslq -uroot <DB名> < /var/tmp/<DB名>_mysql_no_data.sql

## DISCARD
$ myslq -uroot <DB名> -e "ALTER TABLE <DB名> DISCARD TABLESPACE"

## expとibdファイルを配置
$ sudo cp -p /var/tmp/export_tables/<DB名>/*.exp /var/lib/mysql/<DB名>/
$ sudo cp -p /var/tmp/export_tables/<DB名>/*.ibd /var/lib/mysql/<DB名>/
$ sudo chown -R mysql:mysql $MYSQL_DATADIR/$target_db

## IMPORT
$ myslq -uroot <DB名> -e "ALTER TABLE <DB名> IMPORT TABLESPACE"
$ sudo service mysql start

上記手順で検証して、スクリプト化していざ実行ということに。
金曜日の夜にしかけて、土曜日の朝確認し、問題なければ完了という想定。
という私の甘い考えは脆くも崩れ去りました。
朝ログ確認するとDISCARD TABLESPACE処理でこけているではありませんか。。。
更に一旦DBを削除して、元のスクリプトに戻そうとしてもDBが削除できない。。。

DISCARD TABLESPACEがこけた原因は2つでした。

  • 外部キー制約にひっかかかった
ERROR 1451 (23000) at line 1: Cannot delete or update a parent row: a foreign key constraint fails ()
  • ストレージエンジンがInnoDB 以外のものが含まれていた
ERROR 1031 (HY000) at line 1: Table storage engine for '<テーブル名>' doesn't have this option

まずは「外部キー制約にひっかかかった」件について

DISCARD TABLESPACEで .ibdファイルを削除しているのですが、外部キー制約があるテーブルは削除前に外部キー制約を一旦解除する必要があるようです。よく見ると参考元の記事にも書いてありました。
以下のコマンドで解除できます。

mysql> SET FOREIGN_KEY_CHECKS = 0

次に「ストレージエンジンがInnoDB 以外のものが含まれていた」件について

DISCARD TABLESPACEは、InnoDB以外では使用できないようです。
今回はリストア対象にストレージエンジンがMyISAMとmroongaのテーブルが含まれていたため失敗していました。考慮不足。。。
IMPORT TABLESPACEも同様です。
対策はシンプルでストレージエンジンがInnoDBであるものだけ実行するロジックに変更しました。

データベースの数が多すぎて、バックアップできない

上記作業を実施するにあたり、事前に開発環境DBのフルバックをしようと考えていました。
以下のコマンドです。--databaseを指定していないため、フルバックが走るはずです。

$ sudo innobackupex --user=root --stream=xbstream --parallel=4  /var/tmp/xtrabackup/ | lz4 -9 > /var/tmp/<ホスト名>.xbstream.lz4

2015-12-18 09:51:19 7f935bdbe720  InnoDB: Operating system error number 24 in a file operation.
InnoDB: Error number 24 means 'Too many open files'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.6/en/operating-system-error-codes.html
InnoDB: Error: could not open single-table tablespace file ./kaguno_production_dev6059/product_texts.ibd
InnoDB: We do not continue the crash recovery, because the table may become
InnoDB: corrupt if we cannot apply the log records in the InnoDB log to it.
InnoDB: To fix the problem and start mysqld:
InnoDB: 1) If there is a permission problem in the file and mysqld cannot
InnoDB: open the file, you should modify the permissions.
InnoDB: 2) If the table is not needed, or you can restore it from a backup,
InnoDB: then you can remove the .ibd file, and InnoDB will do a normal
InnoDB: crash recovery and ignore that table.
InnoDB: 3) If the file system or the disk is broken, and you cannot remove
InnoDB: the .ibd file, you can set innodb_force_recovery > 0 in my.cnf
InnoDB: and force InnoDB to continue crash recovery here.
innobackupex: got a fatal error with the following stacktrace: at /usr/bin/innobackupex line 2711
    main::wait_for_ibbackup_file_create('/tmp/xtrabackup_suspended_2') called at /usr/bin/innobackupex line 2731
    main::wait_for_ibbackup_suspend('/tmp/xtrabackup_suspended_2') called at /usr/bin/innobackupex line 1984
    main::backup() called at /usr/bin/innobackupex line 1609

なんだと。。。
結論からいうとDB数が多すぎたことが原因?でした。
「Error number 24 means 'Too many open files'.」
といわれていますし、恐らくそうなんじゃないかなと。
なので今回は、バックアップするDBを明示的に指定して、絞ることで対応しました。

$ sudo innobackupex --user=root --stream=xbstream --database='DB1 DB2 DB3' --parallel=4  /var/tmp/xtrabackup/ | lz4 -9 > /var/tmp/<ホスト名>.xbstream.lz4

まとめ

開発環境で試したところ、mysqldumpと比べてリストアの速度が約2倍早くなりました。
また今回のようにテーブル毎にバックアップ、リストアする必要がなければ、xtrabackupを使用することで比較的に簡単にバックアップ、リストアが実現できるのではないでしょうか。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away