エラーの内容
.ibdファイルを手動でコピーしてInnoDBテーブルを復元しようとすると、MySQLが次のエラーで処理を止めます:
ERROR 1813 (HY000): Tablespace for table '`mydb`.`mytable`' exists. Please DISCARD the tablespace before IMPORT.
このエラーはトランスポータブルテーブルスペース方式を使用している場合に発生します。つまり、バックアップの.ibdファイルを稼働中のMySQLデータディレクトリにコピーする際に起こります。原因はInnoDBが内部ディクショナリにそのテーブルのアクティブなテーブルスペースをすでに登録しているためです。
MySQLは追跡済みのテーブルスペースを上書きすることを拒否します。置き換えをインポートする前に、現在のテーブルスペースを明示的に解放する必要があります。
発生原因
InnoDBはファイルシステムとは別に独自のデータディクショナリを管理しています。ALTER TABLE ... IMPORT TABLESPACEを実行すると、MySQLはそのテーブルにテーブルスペースがすでに登録されているかどうかを確認します。ディスク上の.ibdファイルがすでにバックアップファイルに置き換わっていたとしても、登録が残っていればERROR 1813が発生します。
このエラーが確実に発生する3つの状況:
.ibdファイルをデータディレクトリに直接コピーして、バックアップから単一テーブルを復元する場合- 失敗した復元の後に古いテーブルスペースの登録が残ったまま再インポートを試みる場合
FLUSH TABLES ... FOR EXPORT/IMPORT TABLESPACEを使ってサーバー間でテーブルを移行する場合
ステップごとの修正手順
4つのステップ:テーブル構造を再作成 → テーブルスペースを破棄 → バックアップの.ibdを配置 → インポート。
ステップ1:バックアップからテーブル構造を取得する
復元しようとしている.ibdファイルと完全に一致するCREATE TABLE文が必要です。ソースサーバーがまだ稼働中であればそこから取得します:
-- ソースサーバー上で実行
SHOW CREATE TABLE mydb.mytable\G
その出力をどこかに保存してください — 次のステップで必要になります。
ステップ2:ターゲットサーバーでテーブルを削除して再作成する
ターゲットのMySQLで同じ構造のテーブルを再作成します。これによりInnoDBに新しいテーブルスペースエントリが作成されます。
USE mydb;
DROP TABLE IF EXISTS mytable;
CREATE TABLE mytable (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
-- ... 残りのカラム
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
MySQLは新しいmytable.ibdファイルを作成します。このファイルを破棄してバックアップで置き換えます。
ステップ3:テーブルスペースを破棄する
ALTER TABLE mydb.mytable DISCARD TABLESPACE;
これにより、MySQLが作成したばかりの.ibdファイルが削除され、テーブルスペースがInnoDBのディクショナリから登録解除されます。テーブル定義は残ります — 削除されるのはデータファイルのみです。
ステップ4:バックアップの.ibdファイルを所定の場所にコピーする
まずMySQLのデータディレクトリを確認します:
mysql -u root -p -e "SELECT @@datadir;"
標準的なLinuxインストールでは/var/lib/mysql/です。バックアップファイルをコピーします。MySQL 8.0以降では.ibdと.cfgの両方が必要です(.cfgはFLUSH TABLES ... FOR EXPORTによって生成されます):
# MySQL 5.7 — .ibd のみ必要
cp /path/to/backup/mytable.ibd /var/lib/mysql/mydb/
# MySQL 8.0+ — 両方のファイルが必要
cp /path/to/backup/mytable.ibd /var/lib/mysql/mydb/
cp /path/to/backup/mytable.cfg /var/lib/mysql/mydb/
オーナーシップを修正しないとインポートが無音で失敗します:
chown mysql:mysql /var/lib/mysql/mydb/mytable.ibd
chown mysql:mysql /var/lib/mysql/mydb/mytable.cfg # MySQL 8.0+ のみ
ステップ5:テーブルスペースをインポートする
ALTER TABLE mydb.mytable IMPORT TABLESPACE;
正常に完了するとQuery OK, 0 rows affectedが返ります。メッセージが表示されない場合は何か問題が発生しています — エラーログを確認してください。
修正の確認
インポートが成功してもデータを確認するまで信用しないでください:
SELECT COUNT(*) FROM mydb.mytable;
SELECT * FROM mydb.mytable LIMIT 5;
正常なインポートでもMySQLエラーログに破損の警告が隠れている場合があります。確認してください:
# Linuxのデフォルトパス
tail -50 /var/log/mysql/error.log
# またはログの場所を確認
mysql -u root -p -e "SHOW VARIABLES LIKE 'log_error';"
次に整合性の完全チェックを実行します:
CHECK TABLE mydb.mytable;
DISCARDの後もエラーが続く場合
DISCARD TABLESPACE自体が実行を拒否することがあります。まずテーブルをフラッシュしてアクティブなトランザクションをクリアしてください:
FLUSH TABLES mydb.mytable;
ALTER TABLE mydb.mytable DISCARD TABLESPACE;
それでもブロックされますか?外部キー制約が一般的な原因です。テーブルスペース操作を暗黙的に妨げます。操作中は外部キーチェックを無効にしてください:
SET foreign_key_checks = 0;
ALTER TABLE mydb.mytable DISCARD TABLESPACE;
-- ここで .ibd(および .cfg)ファイルをコピーする
ALTER TABLE mydb.mytable IMPORT TABLESPACE;
SET foreign_key_checks = 1;
正しいエクスポート方法(次回のために)
ソースサーバーを管理している場合は、ファイルをコピーする前にこの手順を実行してください。FLUSH TABLES ... FOR EXPORTは.cfgメタデータファイルを生成し、インポートを確実にします — 特に8.0以降では重要です:
-- ソースサーバー上で実行
FLUSH TABLES mydb.mytable FOR EXPORT;
-- データディレクトリから両方のファイルをコピー:
-- /var/lib/mysql/mydb/mytable.ibd
-- /var/lib/mysql/mydb/mytable.cfg
-- 完了したらロックを解放
UNLOCK TABLES;
MySQL 8.0で.cfgをスキップしてもインポートは機能しますが、MySQLはスキーマ不一致の検出がバイパスされたという警告をログに記録します。できれば避けるべきです。
クイックヒント
- 行フォーマットを一致させること:バックアップの
ROW_FORMAT(COMPACT、DYNAMIC、COMPRESSED)がターゲットのCREATE TABLEと同一である必要があります。SHOW TABLE STATUS LIKE 'mytable'\Gで確認してください。 - バージョン互換性:MySQL 8.0の
.ibdファイルを5.7にインポートすることはできません。バージョン間で内部ページフォーマットが変更されています。 - innodb_file_per_tableをONにする必要がある:この方法は各テーブルが独自の
.ibdファイルを持つ場合にのみ機能します。SHOW VARIABLES LIKE 'innodb_file_per_table'で確認してください。 - パーティションテーブル:各パーティションは独自のファイルを持ちます(
mytable#p#p0.ibd、mytable#p#p1.ibdなど)。各パーティションに対してDISCARDとIMPORTを個別に実行してください。

