【XAMPP】ibdata1消失で「Table doesn’t exist in engine」エラー|InnoDBテーブルの復旧方法3選

【XAMPP】ibdata1消失で「Table doesn’t exist in engine」エラー|InnoDBテーブルの復旧方法3選 XAMPP

XAMPPでWordPressを運用中に、すべてのサイトで「Table ‘xxx’ doesn’t exist in engine」エラーが発生し、どのテーブルにもアクセスできなくなる障害が起きることがあります。

この記事では、InnoDBの共有テーブルスペースファイル ibdata1 が消失した場合の原因分析と、3つの復旧方法を実際の障害対応の時系列に沿って解説します。

スポンサーリンク

障害の症状

MySQL(MariaDB)は正常に起動するものの、InnoDBテーブルを含むすべての操作でエラーが発生します。

phpMyAdminでのエラー表示
#1932 - Table 'wp_posts' doesn't exist in engine
#1932 - Table 'wp_options' doesn't exist in engine
#1932 - Table 'wp_users' doesn't exist in engine
MariaDBエラーログ(mysql/data/hostname.err)
[ERROR] InnoDB: Operating system error number 2 in a file operation.
[ERROR] InnoDB: The error means the system cannot find the path specified.
[ERROR] InnoDB: Could not find a valid tablespace file for `wordpress/wp_posts`.
[ERROR] InnoDB: Table wordpress/wp_posts in the InnoDB data dictionary has tablespace id N,
but tablespace with that id or name does not exist.

WordPressの管理画面にもフロントにもアクセスできず、phpMyAdminでもテーブル一覧は表示されるがデータの読み取りは一切できません。

対象環境

  • XAMPP for Windows 11
  • MariaDB 10.4.14
  • WordPress 複数サイト運用(データベースを分離)

原因:ibdata1ファイルの消失

この障害の直接原因は、InnoDBの共有テーブルスペースファイル ibdata1 が消失したことです。

ibdata1の役割

ibdata1はInnoDBエンジンの中核ファイルで、以下の情報を保持しています。

格納情報 説明
内部データディクショナリ テーブル名とテーブルスペースID(.ibdファイル)のマッピング情報
undo ログ トランザクションのロールバックに必要な情報
ダブルライトバッファ データ破損を防ぐための二重書き込み領域
変更バッファ セカンダリインデックスの変更を一時的に蓄積する領域

消失するとどうなるか

ibdata1が消失した状態でMariaDBを起動すると、新規の空ibdata1が自動生成されます。この新しいibdata1には既存テーブルのマッピング情報が一切含まれていないため、ディスク上に.ibdファイル(テーブルデータの実体)が存在していても、InnoDBはそれらを認識できません。

MariaDBエラーログ(ibdata1自動生成時)
[InnoDB] The first innodb_system data file 'ibdata1' did not exist.
A new tablespace will be created!
[InnoDB] Setting file './ibdata1' size to 12 MB.
[InnoDB] Database physically writes the file full: wait...

ibdata1が消えても.ibdファイル内のデータ自体は失われていません。ただし、ibdata1なしではInnoDBがそれらのファイルを「どのテーブルか」判別できないため、実質的に全テーブルにアクセスできない状態になります。

復旧の試み(時系列)

以下、実際に行った3つの復旧方法を時系列順に紹介します。結論として、試み3のフルバックアップからの復元が最も確実な方法でした。

試み1:ibdata1のバックアップから復元 → 失敗

dataディレクトリ内に ibdata1.bak というファイルが残っていたため、これを ibdata1 にリネームして起動を試みました。

結果:失敗。バックアップファイルのLSN(Log Sequence Number)が.ibdファイルより大幅に古く、テーブルスペースのマッピング情報も現在のデータベースと一致しませんでした。

このibdata1.bakはXAMPP初期導入時に近い古いバックアップで、内部辞書にはmysqlシステムテーブルとphpMyAdminのテーブルしか登録されておらず、WordPress関連のデータベースは一切含まれていませんでした。

教訓:ibdata1のバックアップは定期的に取得する必要があります。古いバックアップは使い物になりません。

試み2:DISCARD/IMPORT TABLESPACEで手動復元 → 一部成功

.ibdファイル(テーブル単位のデータファイル)は全て無事だったため、InnoDBの DISCARD/IMPORT TABLESPACE 機能を使って手動で復元を試みました。

手順

  1. 新規ibdata1でMySQLを起動
  2. 対象データベースを作成
  3. WordPressの install.php を実行してコアテーブルのスキーマを自動生成
  4. プラグインテーブルのスキーマをプラグインソースコードから抽出して CREATE TABLE 実行
  5. 各テーブルに対して以下を繰り返し実行

WordPressコアテーブルのスキーマ取得方法:WordPress本体の wp-admin/includes/schema.php に CREATE TABLE文が定義されています。install.php を実行する代わりに、このファイルからスキーマを抽出することも可能です。プラグインのテーブルは各プラグインのソースコード内にある dbDelta() の呼び出し箇所を探してください。

DISCARD/IMPORT TABLESPACEの手順
-- ステップ1: 空の.ibdを削除
ALTER TABLE wp_posts DISCARD TABLESPACE;

-- ステップ2: バックアップから旧.ibdをコピー
-- (OSレベルで当該テーブルの.ibdファイルをデータディレクトリに配置)

-- ステップ3: 旧データを認識させる
ALTER TABLE wp_posts IMPORT TABLESPACE;

結果:43テーブル中41テーブルを復元。一部テーブルはスキーマの不整合(カラム数やインデックス定義の差異)があり、IMPORT TABLESPACE実行時にMariaDBがクラッシュしたためスキップしました。

この方法の問題点

  • テーブルごとにスキーマを正確に再現する必要がある(カラム型、インデックス、外部キーがすべて一致しないとIMPORTが失敗する)
  • プラグインのテーブルはソースコードを読んでスキーマを抽出する必要がある
  • 複数DB・数百テーブルの全復旧には膨大な手間がかかる
  • スキーマが一致しない場合、MySQLがクラッシュするリスクがある

DISCARD/IMPORT TABLESPACEは「特定のテーブルだけ復旧したい」「フルバックアップがない」という状況では有効な手段です。ただし、innodb_file_per_table が有効(.ibdファイルがテーブルごとに存在する状態)であることが前提条件です。

試み3:dataディレクトリのフルバックアップから復元 → 成功

障害発生前にdataディレクトリを丸ごとコピーした別名フォルダが保存されていたため、これを使って復元を行いました。

基本手順

  1. XAMPPのMySQLを停止
  2. 現在のdataディレクトリをリネームして退避(例: data_broken
  3. バックアップフォルダを data にリネーム
  4. MySQLを起動

ただし、このバックアップはMySQL稼働中にディレクトリをコピーしたホットコピーだったため、2つの障害が連続して発生しました。

障害1:Ariaシステムテーブルのクラッシュ

起動直後に mysql.db などのAriaエンジンのシステムテーブルが「crashed」とマークされ、MySQLが正常に起動しませんでした。

Ariaテーブル修復コマンド
# XAMPPのMySQLを停止した状態で実行
cd C:\xampp\mysql\bin

# Ariaシステムテーブルを一括修復
aria_chk -r ..\data\mysql\*.MAI

aria_chk はAriaエンジンテーブルの修復ツールで、MyISAMにおける myisamchk に相当します。-r(repair)オプションでテーブルファイルの整合性を修復します。

障害2:InnoDB ログファイルのLSN不整合

Ariaテーブルの修復後、今度はInnoDBのログファイル(ib_logfile0/ib_logfile1)のLSNとibdata1のLSNに不整合が発生し、InnoDBが起動できませんでした。

MariaDBエラーログ(LSN不整合)
[InnoDB] redo log file './ib_logfile0' exists.
Redo log was created with ibdata1 that is not the one being used now.
[ERROR] InnoDB: Log sequence number in the redo log is in the future!

対処として、ib_logfileを削除してmy.iniにinnodb_force_recoveryを設定しました。

InnoDB ログファイルの削除
# XAMPPのMySQLを停止した状態で実行
del C:\xampp\mysql\data\ib_logfile0
del C:\xampp\mysql\data\ib_logfile1
my.ini に force recovery を追加
[mysqld]
innodb_force_recovery = 1

ib_logfile0/ib_logfile1を削除すると、MariaDB起動時に新しいログファイルが自動生成されます。innodb_force_recovery = 1 はInnoDBの起動時にクラッシュリカバリのロールバック処理をスキップするオプションです。

結果:全データベース正常復旧。すべてのWordPressサイトが正常にアクセスできることを確認した後、innodb_force_recovery = 1my.ini から削除して通常運用に復帰しました。

innodb_force_recovery を設定したままにすると書き込みが制限されるため、復旧確認後は必ず削除して通常モードで再起動してください。

根本原因の整理

要因 説明
ibdata1の消失 直接原因。innodb_force_recovery 中の操作やディスク障害で消失した可能性がある
ホットコピーバックアップ MySQL稼働中のディレクトリコピーだったため、Ariaテーブルの不整合とInnoDB LSN不整合が同時に発生
ibdata1.bakの古さ XAMPP導入初期の自動バックアップで、現在のDBのマッピング情報を含んでおらず使用不可

復旧に必要な知識まとめ

項目 内容
ibdata1 InnoDBの共有テーブルスペース。内部データディクショナリ(テーブル名↔テーブルスペースIDのマッピング)を保持
.ibdファイル innodb_file_per_table 有効時の個別テーブルデータファイル。ibdata1が消えてもデータ自体は残る
DISCARD/IMPORT TABLESPACE .ibdファイルを別テーブルに差し替える機能。スキーマが完全一致していればデータの移植が可能
aria_chk -r Ariaエンジンテーブルの修復コマンド(MyISAMの myisamchk に相当)
innodb_force_recovery LSN不整合時にInnoDBを強制起動するオプション。復旧確認後は必ず削除する
ib_logfileの削除 LSN不整合が解消できない場合、削除すればMariaDBが新しいログファイルを自動再作成する

innodb_force_recoveryの各レベル

今回の復旧ではレベル1を使用しましたが、状況によってはより高いレベルが必要になる場合があります。各レベルの動作を把握しておくと、障害時の判断に役立ちます。

レベル 動作 用途
1 (SRV_FORCE_IGNORE_CORRUPT) 破損ページを検出してもクラッシュさせない 軽微な破損やLSN不整合の復旧
2 (SRV_FORCE_NO_BACKGROUND) バックグラウンドスレッド(purge等)を起動しない purgeスレッドがクラッシュする場合
3 (SRV_FORCE_NO_TRX_UNDO) トランザクションのロールバックを実行しない undo ログの破損時
4 (SRV_FORCE_NO_IBUF_MERGE) 変更バッファのマージを実行しない 変更バッファの破損時
5 (SRV_FORCE_NO_UNDO_LOG_SCAN) undo ログのスキャンをスキップ undo ログ自体の破損時
6 (SRV_FORCE_NO_LOG_REDO) redo ログのリカバリをスキップ 最終手段。redo ログ自体が破損した場合

レベル4以上ではデータの整合性が保証されません。レベル1から試し、起動できなければ段階的にレベルを上げていくのが安全です。また、レベル4以上で起動できた場合は速やかに mysqldump で論理バックアップを取得し、クリーンな環境にインポートし直すことを推奨します。

再発防止策

mysqldumpで論理バックアップを定期取得する

ファイルコピー(物理バックアップ)と違い、mysqldump で取得した論理バックアップはibdata1やib_logfileに依存しないため、確実に復元できます。

mysqldump 全データベースバックアップ
rem XAMPPの場合
C:\xampp\mysql\bin\mysqldump -u root --all-databases --single-transaction > backup_%date:~0,4%%date:~5,2%%date:~8,2%.sql

ホットコピーを避ける

MySQL稼働中のディレクトリコピーは、Ariaテーブルの不整合やInnoDBのLSN不整合を引き起こします。物理バックアップを取得する場合は、以下のいずれかの方法を使用してください。

  • MySQLを停止してからファイルをコピーする(コールドバックアップ)
  • mariabackup(Mariabackup)などの専用バックアップツールを使用する

ibdata1の重要性を認識する

.ibdファイルがすべて残っていても、ibdata1がなければ復旧は非常に困難です。ibdata1は「InnoDBテーブルの地図」のようなファイルであり、これがなければ個々の.ibdファイルのデータにアクセスする手段が限られます。

innodb_force_recovery使用後は速やかに解除する

innodb_force_recovery が有効な状態では、InnoDBへの書き込みが制限されます。復旧確認後は必ず my.ini から設定を削除し、通常モードでMySQLを再起動してください。書き込み制限モードのまま運用を続けると、二次障害の原因になります。

障害発生時の復旧フローチャート

同様の障害が発生した場合、以下の順序で復旧を試みてください。

復旧優先順位

  1. mysqldumpのバックアップがある場合 → 新規dataディレクトリでMySQL起動 → dumpをインポート(最も確実)
  2. dataディレクトリのフルコピーがある場合 → コピーをdataに配置 → aria_chk修復 → ib_logfile削除 → innodb_force_recovery=1で起動
  3. .ibdファイルのみ残っている場合 → 新規ibdata1で起動 → スキーマ再作成 → DISCARD/IMPORT TABLESPACEで復元
  4. 何もない場合 → データ復旧ツール(testdisk等)でibdata1の復元を試みる

関連記事

まとめ

ibdata1の消失はInnoDBテーブルへのアクセスが完全に失われるという深刻な障害です。しかし、.ibdファイルが残っていればデータ自体は復旧できる可能性があります。

復旧方法 前提条件 難易度 復旧率
mysqldumpからインポート 論理バックアップがある 100%
dataディレクトリのフルコピーから復元 物理バックアップがある 100%(ホットコピーの修復が必要)
DISCARD/IMPORT TABLESPACE .ibdファイルが残っている テーブル単位(スキーマ一致が必要)

最も重要な教訓は、mysqldumpによる論理バックアップを定期的に取得することです。物理バックアップはファイル間の整合性が問題になりますが、論理バックアップはSQL文の集合なので環境に依存せず確実に復元できます。