MySQLのinnodb_force_recoveryでInnoDBクラッシュ障害から復旧する手順|起動不能なDBからデータを救出する方法

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Linuxtips > データーベース管理 > MySQLのinnodb_force_recoveryでInnoDBクラッシュ障害から復旧する手順|起動不能なDBからデータを救出する方法
「MySQLを再起動しようとしたら、起動しない。」

エラーログには「InnoDB: Corruption」「Page read failed」の文字が並んでいる。バックアップはあるが2日前のもので、その間に処理したデータをそのまま捨てることにはなかなか踏み切れない。こうした事態は突然やってきます。

この記事では、MySQL 8.0系/MariaDB 10.6系を想定環境として、InnoDB障害でMySQLが起動しなくなった場合に innodb_force_recovery を使ってデータを救出・復旧する手順を解説します。エラーログの読み方から、mysqldumpによるデータ抽出、新規インスタンスへの再インポートまでをステップごとに説明します。

この記事のポイント

・innodb_force_recoveryは値1から始め、起動できたら即mysqldumpを取る
・値4以上になるとDMLが禁止され、データ欠損のリスクが急に高まる
・復旧後は必ずinnodb_force_recoveryを削除し、新規DBへ再インポートする
・エラーログの確認が最初のステップ(RHEL系は/var/log/mysqld.log)


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜInnoDBクラッシュでMySQLが起動しなくなるのか

MySQLのデフォルトストレージエンジンであるInnoDBは、トランザクション整合性を保つためにデータファイル(.ibd)とログファイル(ib_logfile)をペアで管理しています。正常な停止であればログを適切に閉じてからシャットダウンしますが、以下のようなケースでは書き込み途中のままファイルが閉じられ、次回起動時に不整合が検出されます。

・OSの強制終了やサーバー電源断(UPSなし環境で多い)
・OOM Killerによるmysqldプロセスの強制終了
・ディスクの物理的な障害(バッドセクタ)
・ファイルシステムのエラー(ext4・XFSのジャーナル破損)

起動時にInnoDBがデータファイルの不整合を検出すると、安全のため起動を拒否します。エラーログには次のようなメッセージが残ります。

# よく見られるInnoDB障害のエラーメッセージ例(環境により異なります) [ERROR] InnoDB: Corruption in the InnoDB tablespace [ERROR] InnoDB: Trying to access page number X in space Y [ERROR] InnoDB: Page [page id: space=5, page number=1234] read failed with error [ERROR] InnoDB: Unable to open tablespace '/var/lib/mysql/mydb/orders.ibd' [ERROR] Plugin 'InnoDB' init function returned error [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed

最後の2行が出ると、MySQLは完全に起動を拒否した状態です。この状態から innodb_force_recovery を使って強制的に起動し、データを救出します。

innodb_force_recoveryの設定値と安全な選択基準

innodb_force_recovery は、MySQLの設定ファイル(my.cnf)の [mysqld] セクションに記述する整数値です。0が通常動作で、1~6の数値を設定することで、起動時のInnoDBチェックを段階的に緩和します。

値 動作の変化 データへの影響
1 破損ページを検出しても無視してストレージエンジンを起動する 低。まずここから試す
2 バックグラウンドスレッド(mainスレッド・purgeスレッド)を無効化 低。purgeが止まるが読み取りは可
3 クラッシュリカバリ後のトランザクションロールバックを無効化 低~中。未コミットデータが残る場合あり
4 挿入バッファ(Insert Buffer)のマージを無効化。書き込み操作(DML)が禁止される 中。インデックスが不完全になる可能性
5 UNDOログを無視して起動 高。未コミットデータが混入する場合あり
6 REDOログを無視して起動。最後の手段 最高。データ欠損が起きる可能性がある
値4以上に設定すると、INSERT・UPDATE・DELETEなどの書き込み操作が一切受け付けられなくなります。値3以下で起動できた場合は、mysqldumpさえ取れれば通常の読み取り・エクスポートが問題なく行えます。できる限り値を低く抑えることが復旧の鉄則です。

段階的にMySQLを復旧する手順

1. エラーログで障害の種類を特定する

最初にエラーログを確認し、何が原因で起動を拒否しているのかを把握します。

# RHEL/CentOS/Rocky Linux/AlmaLinux 系のエラーログ確認 tail -200 /var/log/mysqld.log | grep -i 'error\|innodb\|abort' # Ubuntu/Debian 系の確認先 tail -200 /var/log/mysql/error.log | grep -i 'error\|innodb\|abort' # ログファイルの場所をmy.cnfで確認する方法 grep log_error /etc/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf 2>/dev/null

「InnoDB: Corruption」「Plugin 'InnoDB' init function returned error」の文字が出ていればInnoDB障害です。「ERROR 2002」や「Can't connect to local MySQL server」だけの場合は、mysqldプロセス自体が起動していない別原因の可能性があります。

2. innodb_force_recoveryを設定してMySQLを起動する

エラーログでInnoDB障害を確認したら、my.cnfを編集します。

# /etc/my.cnf または /etc/mysql/mysql.conf.d/mysqld.cnf を編集 # [mysqld] セクションに追記する [mysqld] innodb_force_recovery = 1

追記後にMySQLの起動を試みます。

systemctl start mysqld systemctl status mysqld

起動に失敗する場合は、値を 1 → 2 → 3 と1つずつ増やして再試行します。値を変更するたびに systemctl stop mysqld → my.cnf を編集 → systemctl start mysqld の順で操作してください。できる限り3以下で起動することを目指します。

値3以下で起動できた場合は、次のステップに進みます。値4以上でしか起動できない場合は、mysqldumpの一部オプションが機能しない点を念頭に置いてください(後述)。

3. mysqldumpでデータをエクスポートする

MySQLが起動した直後、追加の操作をする前にすぐにデータをダンプします。innodb_force_recoveryで動いている間は障害状態が続いているため、長時間この状態を維持するのは危険です。

# 全データベースを一括ダンプ(innodb_force_recovery = 1~3 の場合) mysqldump -u root -p \ --all-databases \ --single-transaction \ --skip-lock-tables \ --routines \ --triggers \ > /tmp/all_dbs_rescue.sql # ダンプファイルのサイズを確認 ls -lh /tmp/all_dbs_rescue.sql # 先頭行でCREATE DATABASEが含まれているか確認 head -30 /tmp/all_dbs_rescue.sql

innodb_force_recoveryが4以上の場合、--single-transaction は書き込み操作を伴うため使えません。その場合は次のコマンドで対応します。

# innodb_force_recovery = 4 以上の場合(書き込み禁止のため --skip-lock-tables のみ) mysqldump -u root -p \ --all-databases \ --skip-lock-tables \ --routines \ --triggers \ > /tmp/all_dbs_rescue.sql

ダンプが取れたら、MySQLを停止します。

systemctl stop mysqld

4. データディレクトリを初期化してインポートする

ダンプが取れた後は、破損したInnoDBファイルが残る既存のデータディレクトリを使い続けることは避けます。新規のデータディレクトリを作成してインポートします。

まず、my.cnfから innodb_force_recovery の設定を削除します。

# [mysqld] セクションから以下の行を削除またはコメントアウト # innodb_force_recovery = X ← この行を削除する

次に、破損した旧データディレクトリを退避させ、新しいディレクトリを作成します。この段階で旧データディレクトリは削除しません。復旧後の確認が終わるまで保管しておきます。

# 破損した旧データディレクトリを退避(削除しない) mv /var/lib/mysql /var/lib/mysql.broken # 新しいデータディレクトリを作成 mkdir -p /var/lib/mysql chown mysql:mysql /var/lib/mysql chmod 750 /var/lib/mysql # SELinuxが有効な環境ではラベルを設定する(RHEL系) restorecon -R /var/lib/mysql # InnoDBを初期化 mysqld --initialize --user=mysql --datadir=/var/lib/mysql

初期化が完了すると、MySQLは一時パスワードを生成します。エラーログから確認します。

# 一時パスワードを確認 grep 'temporary password' /var/log/mysqld.log | tail -1 # 出力例(環境により異なります) # [Note] A temporary password is generated for root@localhost: Ab1Cd2Ef3G!

MySQLを起動し、一時パスワードでログインしてパスワードを変更します。

# MySQL起動 systemctl start mysqld # 一時パスワードでログイン mysql -u root -p

-- 一時パスワード変更(MySQLのパスワードポリシーに合わせた文字列を指定する) ALTER USER 'root'@'localhost' IDENTIFIED BY 'YourNewSecurePass123!'; FLUSH PRIVILEGES; EXIT;

パスワード変更後、ダンプファイルをインポートします。

# ダンプをインポート(新パスワードで実行) mysql -u root -p < /tmp/all_dbs_rescue.sql # インポート完了後にデータベース一覧を確認 mysql -u root -p -e "SHOW DATABASES;"

インポート中にエラーが出た場合は、特定のテーブルが破損してダンプ取得時にも不整合が生じている可能性があります。エラーメッセージで該当テーブルを特定し、そのテーブルだけをスキップして残りをインポートするアプローチを検討します。

復旧後に必ずやること

インポートが完了してMySQLが通常動作に戻ったら、以下の確認と後片付けを行います。

テーブルの整合性チェック

# 全データベース・全テーブルのチェック mysqlcheck -u root -p --all-databases --check # 問題が見つかった場合は修復を試みる mysqlcheck -u root -p --all-databases --repair

バイナリログの確認

データを新規DBに再インポートした時点でバイナリログの連続性は途切れます。MySQLのレプリケーションを構成している場合は、スレーブ側の再設定が必要です。バイナリログのポジションやGTIDを記録しておきます。

-- 現在のバイナリログ位置を確認 SHOW MASTER STATUS\G -- バイナリログの一覧 SHOW BINARY LOGS;

旧データディレクトリの整理

復旧後1週間程度は /var/lib/mysql.broken を保管し、問題がなければ削除します。なお、ディスクの物理障害が原因だった場合は、ディスクそのものを交換しないと再発します。dmesg やRAIDのイベントログでハードウェアの状態も確認してください。

Linuxサーバーでデータベースを安全に自前運用するノウハウをより体系的に身につけたい場合は、Linux Master Pro Seminarでハンズオン形式で学べます。

「それでも起動しない」時の対処法

innodb_force_recovery = 6 に設定しても起動しない場合は、InnoDB以外の問題が重なっている可能性があります。以下の点を順に確認します。

ディスク容量の確認

# ディスク使用量の確認 df -h # /var/lib/mysql のinode使用率も確認 df -i /var/lib/mysql

ディスクが100%満杯だと、InnoDBの起動処理中に書き込みができず失敗します。不要ファイルを削除して空き容量を確保します。

ハードウェア障害の確認

# カーネルのディスクエラーを確認 dmesg | grep -i 'error\|fail\|bad\|reset' # ディスクの健全性確認(smartmontools が必要) smartctl -a /dev/sda

SELinuxによるアクセス拒否の確認(RHEL系)

# SELinuxの状態確認 getenforce # mysqlに関するAVC拒否ログの確認 ausearch -c mysqld -m avc 2>/dev/null | tail -20

データディレクトリを新しい場所に作成した場合、SELinuxのラベルがmysqlプロセスのアクセスを拒否することがあります。restorecon -R /var/lib/mysql を実行してラベルを修正します。

ファイル権限の確認

# データディレクトリの権限と所有者を確認 ls -la /var/lib/ | grep mysql ls -la /var/lib/mysql/ | head -20 # 正しい状態の例(環境により異なります) # drwxr-x--- 7 mysql mysql 4096 Nov 5 13:00 mysql

値6でも全く起動しない場合は、最終手段としてバックアップからの復旧+バイナリログ再生(PITR)を検討します。この時点でデータの救出は諦め、直近のバックアップと保全済みのバイナリログを使って可能な限り新しい時点まで戻す方針に切り替えます。

本記事のまとめ

innodb_force_recovery は、InnoDB障害でMySQLが起動しなくなった場合のデータ救出ツールです。値を低く抑えながら段階的に試し、起動できた瞬間にmysqldumpを取る——この2点が復旧成功のカギです。

やりたいこと コマンド/設定
エラーログを確認する tail -200 /var/log/mysqld.log | grep -i error
innodb_force_recoveryを設定する my.cnfの[mysqld]に innodb_force_recovery = 1 を追記
MySQL起動を確認する systemctl start mysqld && systemctl status mysqld
全DBをダンプする(値3以下) mysqldump -u root -p --all-databases --single-transaction > /tmp/rescue.sql
全DBをダンプする(値4以上) mysqldump -u root -p --all-databases --skip-lock-tables > /tmp/rescue.sql
データディレクトリを初期化する mysqld --initialize --user=mysql --datadir=/var/lib/mysql
一時パスワードを確認する grep 'temporary password' /var/log/mysqld.log
ダンプをインポートする mysql -u root -p < /tmp/rescue.sql
テーブルの整合性チェック mysqlcheck -u root -p --all-databases --check
InnoDB障害は防ぐことが難しい場合もありますが、mysqldumpやxtrabackupによる定期バックアップ、バイナリログの有効化を組み合わせておけば、最悪の事態での復旧範囲を最小限に抑えられます。バックアップと復旧テストの定期実施は、本番DBサーバー運用の基本です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、2日間のハンズオンセミナーで実践的なスキルを習得できます。MySQL・MariaDBのセットアップから本番運用の設計まで、実機を使った演習で確実に身につけます。
>> Linux Master Pro Seminar の詳細を見る

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。