如何在MySQL中迁移InnoDB数据文件

直接拷贝.ibd文件报错“Tablespace is missing for table”是因为InnoDB不信任外部文件,必须通过FLUSH TABLES ... FOR EXPORT生成配套.cfg文件,并用IMPORT TABLESPACE显式导入,且要求源目标表结构、字符集、ROW_FORMAT等完全一致。

为什么直接拷贝 ibd 文件会报错 Tablespace is missing for table

因为 InnoDB 默认不信任外部导入的 .ibd 文件——它只认自己管理的表空间元数据。即使你把 table.ibd 和 table.frm(或 table.sdi)都拷过去了,MySQL 启动时发现数据字典里没有对应记录,就会拒绝加载,报这个错误。

可传输表空间(Transportable Tablespaces)就是为解决这个问题设计的:它要求你先“标记”表为可导出状态,生成一致的 .ibd 快照,并导出配套的元数据文件(.cfg),再在目标库中用 IMPORT TABLESPACE 命令显式告诉 InnoDB:“这张表的数据我带来了,请校验并接入字典”。

  • 必须满足:源表和目标表结构完全一致(包括字符集、ROW_FORMAT、PAGE_COMPRESSED 等)

  • 源表必须是独立表空间(innodb_file_per_table=ON),且不能是分区表的子分区(MySQL 8.0.23+ 支持分区级传输)

  • .cfg 文件不可手动生成或修改,必须由 FLUSH TABLES ... FOR EXPORT 产生

执行 FLUSH TABLES t FOR EXPORT 后要立刻做三件事

这条命令会让表进入只读状态,并冻结其元数据快照(用于生成 .cfg)。但它不会自动释放锁,也不代表你可以马上拷文件——稍有延迟就可能因其他事务写入导致 .cfg 和 .ibd 不一致。

  • 立即用 cp /var/lib/mysql/db/t.{ibd,cfg} /backup/ 拷走两个文件(顺序不重要,但必须都在锁持有期间完成)

  • 立刻执行 UNLOCK TABLES(注意:不是 FLUSH TABLES,后者会释放锁但不清除导出状态)

  • 检查 .cfg 文件是否非空:stat /backup/t.cfg + head -c 20 /backup/t.cfg;空文件说明导出失败,常见于表被 ALTER 中或处于崩溃恢复状态

目标库 IMPORT TABLESPACE 失败的三个高频原因

即使文件拷对了、结构一致,仍可能卡在导入环节。关键看错误日志里具体哪一行报错:

  • Incorrect key file for table 't'; try to repair it → 表结构不一致,比如源库是 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8,目标库建表时漏写了 KEY_BLOCK_SIZE 参数

  • Cannot continue operation, data file size does not match dictionary → .ibd 被意外截断或拷贝不完整(常见于 rsync 未加 --partial 或网络中断后没校验)

  • Failed to open the tablespace file ... because it is not a valid InnoDB data file → MySQL 版本跨度过大(如从 5.7 导出,8.0.22 以下版本无法导入),或开启了 innodb_checksum_algorithm=crc32 但目标库是 strict_crc32

修复方式不是重试,而是回退到源库重新 FLUSH ... FOR EXPORT,并确认目标库 CREATE TABLE 语句与 SHOW CREATE TABLE 输出完全一致(连注释都不能多)。


您可以还会对下面的文章感兴趣:

暂无相关文章