XAMPPでWordPressを運用中に、すべてのサイトで「Table ‘xxx’ doesn’t exist in engine」エラーが発生し、どのテーブルにもアクセスできなくなる障害が起きることがあります。
この記事では、InnoDBの共有テーブルスペースファイル ibdata1 が消失した場合の原因分析と、3つの復旧方法を実際の障害対応の時系列に沿って解説します。
障害の症状
MySQL(MariaDB)は正常に起動するものの、InnoDBテーブルを含むすべての操作でエラーが発生します。
#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
[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はそれらを認識できません。
[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 機能を使って手動で復元を試みました。
手順
- 新規ibdata1でMySQLを起動
- 対象データベースを作成
- WordPressの
install.phpを実行してコアテーブルのスキーマを自動生成 - プラグインテーブルのスキーマをプラグインソースコードから抽出して
CREATE TABLE実行 - 各テーブルに対して以下を繰り返し実行
WordPressコアテーブルのスキーマ取得方法:WordPress本体の wp-admin/includes/schema.php に CREATE TABLE文が定義されています。install.php を実行する代わりに、このファイルからスキーマを抽出することも可能です。プラグインのテーブルは各プラグインのソースコード内にある dbDelta() の呼び出し箇所を探してください。
-- ステップ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ディレクトリを丸ごとコピーした別名フォルダが保存されていたため、これを使って復元を行いました。
基本手順
- XAMPPのMySQLを停止
- 現在のdataディレクトリをリネームして退避(例:
data_broken) - バックアップフォルダを
dataにリネーム - MySQLを起動
ただし、このバックアップはMySQL稼働中にディレクトリをコピーしたホットコピーだったため、2つの障害が連続して発生しました。
障害1:Ariaシステムテーブルのクラッシュ
起動直後に mysql.db などのAriaエンジンのシステムテーブルが「crashed」とマークされ、MySQLが正常に起動しませんでした。
# 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が起動できませんでした。
[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を設定しました。
# XAMPPのMySQLを停止した状態で実行 del C:\xampp\mysql\data\ib_logfile0 del C:\xampp\mysql\data\ib_logfile1
[mysqld] innodb_force_recovery = 1
ib_logfile0/ib_logfile1を削除すると、MariaDB起動時に新しいログファイルが自動生成されます。innodb_force_recovery = 1 はInnoDBの起動時にクラッシュリカバリのロールバック処理をスキップするオプションです。
結果:全データベース正常復旧。すべてのWordPressサイトが正常にアクセスできることを確認した後、innodb_force_recovery = 1 を my.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に依存しないため、確実に復元できます。
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を再起動してください。書き込み制限モードのまま運用を続けると、二次障害の原因になります。
障害発生時の復旧フローチャート
同様の障害が発生した場合、以下の順序で復旧を試みてください。
復旧優先順位
- mysqldumpのバックアップがある場合 → 新規dataディレクトリでMySQL起動 → dumpをインポート(最も確実)
- dataディレクトリのフルコピーがある場合 → コピーをdataに配置 → aria_chk修復 → ib_logfile削除 → innodb_force_recovery=1で起動
- .ibdファイルのみ残っている場合 → 新規ibdata1で起動 → スキーマ再作成 → DISCARD/IMPORT TABLESPACEで復元
- 何もない場合 → データ復旧ツール(testdisk等)でibdata1の復元を試みる
関連記事
- 【XAMPP】「XAMPP Attempting to start Apache app…」エラーでApacheが起動しない時の解決方法
- 【SQL】テーブル一覧を取得する方法|MySQL・PostgreSQL・Oracle・SQL Server・SQLite対応
- 【PHP】SQLを扱う方法 MySQLiとPDOの比較
- 【Docker】phpMyAdminを使わずにMySQLを操作する方法(CLI編)
まとめ
ibdata1の消失はInnoDBテーブルへのアクセスが完全に失われるという深刻な障害です。しかし、.ibdファイルが残っていればデータ自体は復旧できる可能性があります。
| 復旧方法 | 前提条件 | 難易度 | 復旧率 |
|---|---|---|---|
| mysqldumpからインポート | 論理バックアップがある | 低 | 100% |
| dataディレクトリのフルコピーから復元 | 物理バックアップがある | 中 | 100%(ホットコピーの修復が必要) |
| DISCARD/IMPORT TABLESPACE | .ibdファイルが残っている | 高 | テーブル単位(スキーマ一致が必要) |
最も重要な教訓は、mysqldumpによる論理バックアップを定期的に取得することです。物理バックアップはファイル間の整合性が問題になりますが、論理バックアップはSQL文の集合なので環境に依存せず確実に復元できます。

