alter table ... import tablespace 能秒级恢复单表,因其跳过sql解析与索引重建,仅校验页结构、映射元数据、刷脏页;前提是源目标表严格同构且mysql大版本一致。

MySQL 单表恢复慢,不是备份方式问题,而是默认走逻辑导入(如 mysqldump + SOURCE)或全量重放日志路径。真正快的方案是跳过 SQL 解析和逐行插入,直接复用物理文件——也就是表空间传输(Transportable Tablespace)。
为什么 ALTER TABLE ... IMPORT TABLESPACE 能秒级恢复单表
它不解析 SQL、不重建索引、不校验约束,只做三件事:校验 .ibd 文件页结构一致性、映射元数据到 InnoDB 字典、刷脏页并标记为可用。整个过程本质是 OS 层文件拷贝 + 内存元数据注册,耗时取决于磁盘带宽,而非数据量大小。
但前提是:源表和目标表必须严格同构(列名、顺序、类型、字符集、ROW_FORMAT、STATS_PERSISTENT 等),且 MySQL 版本兼容(建议同大版本,如 5.7↔5.7 或 8.0↔8.0)。
- 常见错误现象:
ERROR 1808 (HY000): Schema mismatch—— 源表和目标表 DDL 不一致,哪怕只是注释不同也会失败 - 使用场景:误删单表、测试环境快速回滚、跨实例迁移小表(
- 性能影响:恢复时间 ≈
cp时间 + 几百毫秒元数据操作;对比mysql -e "source backup.sql",提速 10–100 倍(尤其对千万级以上表)
FLUSH TABLES ... FOR EXPORT 必须配 UNLOCK TABLES
FLUSH TABLES t FOR EXPORT 会加全局读锁,并暂停 purge 线程,导致所有写入阻塞。很多人卡在“导出后忘了解锁”,结果业务 hang 死。
- 正确顺序必须是:
FLUSH TABLES t FOR EXPORT;→ 拷贝t.ibd和t.cfg→UNLOCK TABLES; -
t.cfg是关键:它记录了表的加密密钥、页校验信息、space_id 等,缺一不可;MySQL 5.7+ 才生成,旧版本需用innodb_file_per_table=ON+innodb_file_format=Barracuda - 容易踩的坑:在从库执行该命令会报错
ERROR 1189 (08S01): Net read error,因为从库不允许FLUSH ... FOR EXPORT;必须在主库或独立实例上操作
分区表要单独处理每个分区的表空间
MySQL 5.7+ 支持对分区执行 DISCARD PARTITION p0 TABLESPACE 和 IMPORT PARTITION p0 TABLESPACE,但语法和普通表不同,不能混用。
- 例如恢复分区
p202401,目标表已存在且含该分区:先执行ALTER TABLE logs DISCARD PARTITION p202401 TABLESPACE;,再拷贝logs#P#p202401.ibd和logs#P#p202401.cfg,最后ALTER TABLE logs IMPORT PARTITION p202401 TABLESPACE; - 注意文件名:分区表空间文件名含
#P#标记,不能手动改名;ls查看真实名称,否则IMPORT会静默失败 - 兼容性限制:如果源表用
ALGORITHM=INPLACE修改过分区定义,可能造成space_id不匹配,此时需先OPTIMIZE TABLE强制重建分区表空间
权限与文件系统细节决定成败
即使 SQL 全部成功,chown 和 chmod 错误也会让 IMPORT 失败,错误信息却常被忽略。
- 必须确保
.ibd和.cfg文件属主为mysql:mysql,权限为660(-rw-rw----);ls -l看到 root/root 就必然失败 - 不能跨文件系统拷贝:如果源表空间在 XFS 上创建,目标目录必须也是 XFS(ext4 可能因 block size 差异报
ERROR 1812) - 最容易被忽略的一点:目标实例的
innodb_file_per_table=ON必须开启,否则IMPORT会提示Tablespace is missing for table xxx,但实际是因为它试图往系统表空间里塞,而系统表空间不支持导入











