单靠.ibd文件无法恢复被DROP DATABASE的库,因元数据、表空间ID及字典绑定均已丢失,且无.frm或SDI无法重建表结构;唯一可靠路径是用含.cfg/SDI的备份逐表导入。

不能直接靠.ibd文件恢复被DROP DATABASE的整个库——因为数据库级删除会清空所有表的元数据、移除所有.ibd文件的注册、并可能触发共享表空间(ibdata1)中系统表的更新。单独保留下来的.ibd文件,没有对应的.frm(MySQL 5.7)或SDI元数据(MySQL 8.0+),MySQL根本无法识别其结构和表空间ID,ALTER TABLE ... IMPORT TABLESPACE会直接报错 Tablespace is missing for table 或 Failed to find tablespace for table。
为什么单靠.ibd文件无法重建DROP DATABASE后的库
执行DROP DATABASE db1后,InnoDB实际做了三件事:从INFORMATION_SCHEMA.SCHEMATA删库记录;遍历该库下所有表,逐个调用DROP TABLE逻辑(清理字典、unlink .ibd、标记空间可重用);若使用共享表空间,还会在ibdata1中擦除相关SYS_TABLES/SYS_COLUMNS等系统页。这意味着:
- .ibd文件即使没被覆盖,也失去了与数据字典的绑定关系,表空间ID已失效
- MySQL 8.0+不再生成.frm文件,结构信息全存在.ibd内部的SDI段里,但
IMPORT TABLESPACE要求目标表必须已存在且结构完全匹配——而你连表都建不起来 - 没有
db1库名,你就没法创建同名库下的同名表,CREATE TABLE语句本身就需要先USE db1
唯一可行路径:用备份中的.ibd + 对应的.cfg/SDI重建单表
如果你有最近一次XtraBackup全备(或冷备),且备份时开启了--export,那每个.ibd都配有一个.cfg(含校验后的表结构描述)。这是目前最可靠、无需逆向解析的方案:
- 先用
xtrabackup --prepare --export --target-dir=/backup/full准备好备份 - 新建空库:
CREATE DATABASE db1; - 按备份里的
CREATE TABLE语句重建每张表(注意字符集、ROW_FORMAT、STATS_PERSISTENT等细节) - 对每张表执行:
ALTER TABLE db1.t1 DISCARD TABLESPACE;,再cp /backup/full/db1/t1.{ibd,cfg} /var/lib/mysql/db1/,最后ALTER TABLE db1.t1 IMPORT TABLESPACE; - 务必
chown mysql:mysql *.ibd *.cfg,否则导入会静默失败
没有备份但.ibd还在磁盘上?试试SDI提取 + 手动建表
仅适用于MySQL 8.0.21+且原实例未重启过(.ibd文件仍被进程持有)的情况。核心是把嵌在.ibd里的SDI(Serialised Dictionary Information)抽出来还原建表语句:
- 停止所有写入,防止.ibd被覆写
- 用
ibd2sdi t1.ibd -o t1.sdi.json(Percona Toolkit提供)提取结构定义 - 从JSON里人工拼出
CREATE TABLE语句(注意ENGINE=InnoDB ROW_FORMAT=Dynamic等隐式参数) - 建好表后,
DISCARD再IMPORT,但成功率取决于SDI是否完整——若.ibd已被部分覆盖,ibd2sdi会报Failed to read SDI from page 0 - 别信“用foremost恢复已删除.ibd”的说法:ext4/xfs的unlink后恢复成功率<5%,且恢复出的文件常缺页或损坏
真正卡住的地方从来不是技术动作,而是表结构一致性。哪怕你成功import了100张表,只要其中一张的CHARSET或COLUMN_FORMAT和原库不一致,后续SELECT就可能触发Incorrect information in file错误——这问题不会在import时报出,而是在第一次查询时才暴露。



















