mysqlのibdataが原因でディスクフルになったときに復旧方法
さっきまで落ちてたsakuratan.bizです。どーもすみません。
原因は MySQL の InnoDB が使用する ibdata ファイルがディスクを食いつぶしてディスクフルになってたためでした。
ibdata はテーブルスペースを保存するファイルで、CentOS ですとデフォルトで /var/lib/mysql/ibdata1 に作成されます。MySQL のデフォルトでは ibdata が自動で拡張されていく設定になっていますので、放っておくとどんどんファイルサイズがでかくなって、さくらの VPS とかですと結構あっさりディスクフルになりました。
とりあえず復旧できたんで手順とか残しときます。同じようにトラブった方は参考程度にどうぞ。
まず ibdata1 がディスクを食いつぶしているので、復旧するにはこれを消すとかファイルを小さく必要があります。
ファイルサイズを小さくする方法は調べたらいっぱいでてきますので(13.5.7 InnoDB データとログ ファイルの追加と削除 とか ibdata1 のサイズを減らす手順 とか ibdata1のサイズを減らす方法とか)、概要だけ引用しますと、
- 全ての InnoDB テーブルをダンプする為に mysqldump を利用してください。
- サーバを停止してください。
- 全ての存在するテーブルスペース ファイルを削除してください。
- 新しいテーブルスペースを設定してください。
- サーバを再起動してください。
- ダンプ ファイルをインポートしてください。
MySQL :: MySQL 5.1 リファレンスマニュアル :: 13.5.7 InnoDB データとログ ファイルの追加と削除
という感じだったりします。要はバックアップ取ってテーブルスペースを作り直せということのようです。
ただまあディスクフルしてるんでサーバ上に mysqldump のダンプファイルなんか置けないので、ssh 経由で mysqldump を実行することにしました。↓のように ssh を起動することで、ネットワーク越しにコマンドを実行して mysqldump の出力をローカルに直接保存できます。
mysqldump -v -u DBUSER \
--default-character-set=binary -p DBNAME \
TABLE1 TABLE2 ... | \
gzip > mysql.dump
それとコマンドを実行する前にサーバ上のサービスをできるだけ止めてある程度作業用のメモリの確保して、ついでに不要なファイルをできるだけ削除しておいた方が良いと思います。メモリかスワップか何が原因か調べてる暇も無かったので詳細は不明ですが、リソースが足らないと mysqldump がテーブル構造を読み込む際にエラーを出します。
今回はリストアする必要が無いテーブルが何個かありましたのでダンプする対象をテーブル単位で指定していますが、全部リストアする場合はデータベース単位で指定してもらえばよろしいかと思います。運用形態によっては mysqldump に –single-transaction オプションを指定してもらった方が良いかもしれません(とりあえずウチんとこでは不要だったので指定してませんが)。
ダンプできたら mysql を止めてから ibdata1 と ib_logfile0 と ib_logfile1 を消します。他のサイトだとリネームした方が良いとか書いてますがそんな余裕無いのでいきなりマジ削除しました。最悪データ全部豚でもいーや、の覚悟でどうぞw
rm -f ibdata1 ib_logfile[01]
/etc/my.cnf に ibdata1 のサイズ制限と innodb_file_per_table を加えてからmysqld を再起動して回復しましたよ、という感じです。
innodb_file_per_table
innodb_file_per_table を指定すると、各テーブルの中身は共有テーブルスペースでは無く個別のファイルに保存されるようになるのです