先日、当然MySQLのプロセスがダウンし、
正常に再起動しない事態となりました。
バックアップは日次のみで、最悪の場合は日次バックアップに戻すとしても、
できることなら最新のデータを保持したまま復旧したいということで、
できる限りのデータを救い上げて復旧するために行なった手順をメモしておきます。
緊急だったので、手順の是非はありますが、とりあえず以下の通りです。
- 起動スクリプト(/etc/init.d/mysqld)ではなく、mysqld_safeによる起動を試みる
- 強制リカバリモードでの起動(innodb_force_recoveryのレベルを1つずつあげながら、起動するまで)
- mysqldumpでデータを抜き出す
(クラッシュしているテーブルに当たるとエラーで止まるので、都度除外しながら) - 3で発覚した、クラッシュしているテーブルの復旧を試みる
- 最後の手段!同環境の別サーバを立ててデータを移行する
- クラッシュしていて抜き出せなかったテーブルを手動で復旧する
1. 起動スクリプト(/etc/init.d/mysqld)ではなく、mysqld_safeによる起動を試みる
# /usr/bin/mysqld_safe --user=root &
この時点では、原因が分からなかったので別の方法でとりあえず起動させてみようということで行いましたが、
あとで調べたら、起動スクリプト(/etc/init.d/mysqld)も中でmysqld_safeを呼んでいるらしく、この作業は時間の無駄でした・・・
起動ログ(/var/log/mysqld.log)を見ると、クラッシュリカバリに失敗して起動できていないことがわかったので、
2. 強制リカバリモードでの起動(innodb_force_recoveryのレベルを1つずつあげながら、起動するまで)
# vi /etc/my.conf
[mysqld] innodb_force_recovery = 1 #1~6まで、起動するまで一つずつ上げていく
1~2まで特に変わらず起動失敗。3で起動はするけどデータベースが認識できていない感じでした。
4でやっと一応ちゃんと動く形で起動しました。
復旧に入ろうにもとりあえず、救えるだけのデータは救ってから・・・ということでとりあえずバックアップを取ります。
mysqldumpでデータを抜き出す
(クラッシュしているテーブルに当たるとエラーで止まるので、都度除外しながら)
# mysqldump -uroot -pパスワード DB名 > /tmp/backup.dump
クラッシュしているテーブルに当たるとエラーを吐いて止まります。
とりあえず、クラッシュしているテーブルは都度スキップしながら救えるだけ救います。
# mysqldump -uroot -pパスワード --ignoretable=壊れているテーブル名 DB名 > /tmp/backup.dump
「–ignoretable=壊れているテーブル名」は壊れているテーブル分だけ繰り返します。
3で発覚した、クラッシュしているテーブルの復旧を試みる
# mysqlcheck -r DB名 壊れているテーブル名 -u root -pパスワード
起動時のリカバリシーケンスで失敗しているので、期待薄な気はしていたのですがやはり駄目でした・・・
不幸中の幸いで壊れているテーブル、最悪中身は無くても良かったので、
とりあえず先に進みます。
最後の手段!同環境の別サーバを立ててデータを移行する
ここは、ただのMySQLサーバ構築なので割愛します。
イメージバックアップがあったので、一から作る必要はなかったのですが、
権限周りだけ再設定が必要でした。
そして、データを入れます。
# mysql -uroot -pパスワード DB名 < /tmp/backup.dump
クラッシュしていて抜き出せなかったテーブルを手動で復旧する
とりあえず、最悪中身は無くても良いテーブルだったので、
DDLだけ流してテーブル構造だけ先に戻してアプリを復旧させ、
後で日次バックアップから入れられるだけのデータを入れました。
後でわかったのですが、
クラッシュしたのはMySQL5.0のバグとのことでした・・・(サポート公式回答済み)
古いバージョン使い続けるのは良くないということと、
費用がきつくても被害が大きくなる場合は、
最低限フェイルセーフレプリケーションだけでもやるべきだな~痛感した一件でした。。。
そもそも、無駄に高い国内DCなんて使わずに、
Amazon RDSを使えば、こんな心配もせずに済むんですけどねw