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

実録: MySQLのリストア

More than 1 year has passed since last update.

実録: MySQLのリストア

運用していた自宅サーバーでディスク破損が発生し、苦労しながらも何とか復旧させました。その過程でMySQLをリストアした試行錯誤の記録です。

ディスク破損時の状況

ディスク破損時のサーバーおよびMySQLのは、次の状況でした。

  • OSは、Ubuntu Server 16.04
  • Qemu/KVMのゲストOSとして運用
  • バックアップは、dumpコマンドを用いて取得し、別のディスクに保存
    • //homeは別パーティッション
    • /homeのバックアップは毎日取得
    • /のバックアップは1週間に1度取得
  • WordPressMediaWikiをMySQLを用いて運用
  • MySQL
    • バージョンは、5.7.16
    • データファイルは、/homeに配置
    • バックアップは特にしていない(OSレベルのバックアップをしていれば大丈夫だと思っていた…)

InnoDB破損からのリストア

自宅サーバーは、新しいハードディスクを接続してから//homeに対してrestoreコマンドを使うことで復元することで成功しました。この段階で、ほかのソフトは問題なく動作したものの、MySQLは起動に失敗する状態でした。エラーログを確認すると、InnoDBが破損していたようです。

そこで、MySQLでInnoDB破損したときの復旧方法を参考に、次の手順で復旧を試みました。

  1. MySQLの設定ファイル/etc/my.cnf末尾にinnodb_force_recovery = 1を追記して、InnoDB強制リカバリモードでMySQLを起動
  2. 全データベースをダンプ mysqldump -u root -p -x --all-databases > alldatabase.dump
  3. innodb_force_recovery = 1を削除して、MySQLを再起動
  4. ダンプファイルをリストア mysql -u root -p < alldatabase.dump

リストア完了と思ったが…

このとき、mysqlデータベースの一部のテーブルでCREATEができないというエラーが発生しました。こちらと同様の現象だったようです。そこで、ダンプファイルをからエラーの表示されているテーブルの記述を削除したファイルを作成し、再度リストアを試みました。後述するようにこの対応は、失敗でした。ただし、MySQLは無事に起動できるようになり、そしてWordPressやMediaWikiも正常にアクセスできるようになりました。

mysqldumpを実行できない

正常に動作しているように見えたMySQL。しかし、何日か経ってmysqldumpを実行しようとしたときに、エラーが発生してできないことに気がつきました。どうも、必要なテーブルがないといっているようです(正確なエラーメッセージは記録を忘れました)。

調査のためにmysqlcheckを実行した場合は、問題ないと表示されます。しばらく考えた末、ようやくInnoDB破損からのリストアに失敗していることに思い当たりました。また、幸いなことに、そのときに取得したバックアップは残っていました。一方、ちょっとですがWordPressやMediaWikiのデータも更新しており、できれば最新のデータを残したいと思っていました。

mysqlデータベースのリストア失敗

そこでまず試したのは、mysqlデータベースだけのリストア。取得していたダンプファイルからmysqlデータベースのデータだけを取り出したダンプファイルを作成し、リストアを実行しました。しかし、次のエラーが発生して、失敗してしまいました。

ERROR 1030 (HY000): Got error 168 from storage engine

調べると、データファイルに書き込みができないことが原因であり、
権限、所有者、容量不足、open file数制限などがさらなる原因の可能性があるとのことです。しかし、ついに原因はわかりませんでした。

データベース全体のリストア

仕方がないので、取得していたダンプファイルからデータベース全体をリストアし、前回のリストア後の更新は破棄し、MySQLを初期化してからリストアすることにしました。実施した手順は次のとおりです。

  1. MySQLをシャットダウン
  2. MySQLのデータファイルをすべて退避
  3. mysqldを初期化モードで起動。 mysqld --initialize
  4. mysqlのrootユーザーのパスワードを設定
  5. mysqldumpから、データベース全体をリストア

このあと、MySQLのプロセスが起動していること、WordPressとMediaWikiが(いったんリストアしたあとの更新が失われた状態で)正常に動作していることを確認しました。また、mysqldumpによるダンプ取得が正常にできることも確認しました。ようやく、MySQLのリカバリ完了です。

反省点

今回の経験を元に、MySQLは次にように運用すべきだと考えています。

  • mysqldumpでのバックアップは取得しておく。OSレベルでのバックアップとリストアが成功しても、MySQLのデータは破損している場合がある。
  • MySQLのリストアがうまくできない場合は、MySQLを初期化してからリストアすることも検討する
  • リストアの訓練は重要

リストアの訓練

さらに重要な課題として、リストアの訓練について考える必要があります。

バックアップを取得していてもほんとうにそのバックアップで復旧できるのか、実際に訓練してみないとわからないことを改めて実感しました。リストアの訓練は大事です。他人様のデータや業務データを扱っている場合は特に
そうでしょう。システムが正常に動作しなくなった場合には、慌てたり落ち込んだりして、どうしても正常な判断が難しくなり、ミスを重ねてしまうおそれもあります。

正常に動作している内にリストアの訓練を実施しておけば、バックアップが本当に有効かどうかを検証できますし、いざというときにミスを起こす可能性も減らせます。
幸いなことに最近では、仮想化やコンテナなどの普及によりリストアの訓練もしやすくなっています。MySQLを使っている方はぜひ、リストアの訓練実施を検討すべきでしょう。

j8takagi
Why not register and get more from Qiita?
  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