1. 概述:可传输表空间
在 InnoDB 且 innodb_file_per_table=ON(MySQL 5.6.6 起默认开启)时,每张表的数据独立存储于一个 .ibd 文件。MySQL 提供了一对 DDL 语句,允许在表定义(数据字典元数据)与磁盘上的 .ibd 文件之间建立或解除关联:
ALTER TABLE tbl DISCARD TABLESPACE:解除当前表与.ibd的关联,并物理删除该文件。表结构仍保留在数据字典,但无任何数据文件。ALTER TABLE tbl IMPORT TABLESPACE:在表定义已存在的前提下,将一份外部.ibd文件挂接到该表,InnoDB 完成内部一致性校验。
二者组合形成**可传输表空间(Transportable Tablespaces)**机制,典型用途:替换损坏的 .ibd 文件、跨实例搬运表数据、利用物理备份快速恢复单表。
版本说明:MySQL 5.6 起逐步完善,MySQL 8.0 引入 SDI(Serialized Dictionary Information)嵌入
.ibd,元数据校验方式有所演进。
2. 标准操作流程
2.1 源端:导出一致性快照
| |
执行效果:将 buffer pool 中该表的脏页全部刷入 .ibd,使文件处于可安全拷贝的一致状态;MySQL 5.6/5.7 同时生成 .cfg 文件用于目标端校验;MySQL 8.0 中 .ibd 内已嵌入 SDI。
在持锁期间复制文件(保持当前会话不关闭):
| |
复制完成后解锁:UNLOCK TABLES;
FLUSH TABLES FOR EXPORT持有共享元数据锁(MDL),期间该表可读不可写,应在业务低峰或维护窗口执行。
2.2 目标端:建壳 -> 丢弃 -> 替换 -> 导入
| |
| |
| |
IMPORT 阶段 InnoDB 会校验 space id、页格式、SDI/.cfg 中的表定义,任何不匹配均报错并拒绝导入。
3. 四个典型场景
场景一:.ibd 文件损坏
适用条件:存在一份物理完好的替代 .ibd(来自物理备份、备库、同结构表副本等)。
常见误解:认为对"已损坏且无第二份文件"的 .ibd 执行 IMPORT 可以修复它。实际上若页链、B+ 树节点或字典信息已物理损坏,导入大概率失败;即使勉强挂载数据也不可信。
建议操作路径:
- 查阅 MySQL 错误日志,评估损坏范围
- 若有干净备份:执行
DISCARD-> 拷入备份.ibd->IMPORT - 核查一致性前提:
- 源与目标的
innodb_page_size必须相同(实例级参数,不可在线修改) ROW_FORMAT必须一致- MySQL 8.0 中若表经历过
INSTANT ADD COLUMN,ibd 内嵌的 instant 列元数据必须与目标表完全匹配
- 源与目标的
补充:字典引用丢失时可通过"按原 DDL 建空表 + DISCARD + 拷入正确 .ibd + IMPORT"挂接,属高风险,务必先在隔离环境演练验证。
场景二:跨实例迁移数据
官方最主要设计用途:避免逻辑导入(解析 SQL + 行重插入)的时间开销,直接搬运物理文件,适合数百 GB 级大表迁移。
必须严格一致的要点:表 DDL 等价(列定义、顺序、类型、字符集、索引结构)、innodb_page_size 相同(常见 16KB)、ROW_FORMAT 一致(DYNAMIC/COMPACT 等)、含外键表需先处理外键、分区表需按分区逐一操作、全文和空间索引部分版本有限制。
运维注意事项:大表在 FLUSH TABLES FOR EXPORT 持锁期间不可写,务必在维护窗口执行。若目标为主从架构,IMPORT 会写入 binlog 并在从库重放,需结合 sql_log_bin=0 评估复制一致性影响。
场景三:误删除大表的恢复
情形 A:误删 .ibd 文件,表定义仍在
| |
情形 B:执行了 DROP TABLE
DROP TABLE 会将表定义从数据字典中彻底移除,.ibd 同时被删除,此时没有空壳可供挂接,DISCARD/IMPORT 无法直接使用。
正确恢复路径(按优先级):
- 延迟从库:在 DDL 传播到从库前及时停止复制并提取数据
- binlog PITR:结合全量备份 + mysqlbinlog 重放至误操作时间点之前
- 物理备份隔离恢复:将 XtraBackup 备份恢复至隔离实例,再逻辑导出目标表
DISCARD/IMPORT 在此场景中是有可用 .ibd 副本时的加速工具,不是替代备份体系的万能修复方案。
场景四:表空间 ID 冲突
现象:IMPORT TABLESPACE 时报 space id 冲突:
InnoDB: tablespace id in file '...' is X, but in the InnoDB data dictionary it is Y
根因:每个 InnoDB 表空间都有内部 space id,同时记录在 .ibd 文件头和数据字典中,若二者不一致 InnoDB 会拒绝挂接。
正确处理方式:
- 使用完整官方流程(FLUSH FOR EXPORT -> 拷贝 ibd+cfg -> CREATE TABLE -> DISCARD -> 放文件 -> IMPORT),InnoDB 在 IMPORT 阶段依据字典重新分配正确的 space id。
- 确保目标表是新建后再 DISCARD,IMPORT 时 InnoDB 会将 ibd 内的 space id 更新为字典值,而非沿用源端的 id。
- 严禁手动修改 ibd 二进制头中的 space id:无官方支持,极易引入不可见的物理损坏,不应作为生产修复手段。
4. 限制与风险清单
| 限制项 | 说明 |
|---|---|
| 外键 | 含外键表导入需 SET foreign_key_checks=0 或临时移除外键 |
| 分区表 | 支持,但需按分区逐一操作,流程复杂 |
| 全文索引 | 部分版本不支持,需查手册确认 |
| 空间索引 | 同全文索引,存在版本限制 |
| INSTANT ADD COLUMN(8.0) | instant 列元数据历史必须完全一致,否则 SDI 校验失败 |
| innodb_page_size | 实例级参数,源与目标必须相同,不可在线变更 |
| 文件属主与权限 | ibd 属主必须为 MySQL 进程用户(如 mysql:mysql) |
| 从库操作 | 在复制从库上执行可能破坏主从一致性,默认不推荐 |
| 安全合规 | DISCARD 删除文件非安全擦除,合规场景需在存储层另行处理 |
5. 与其他方案的横向对比
| 方案 | 适用规模 | 优势 | 局限 |
|---|---|---|---|
| DISCARD / IMPORT | 单表 GB-TB 级 | 省去重解析与重插入,速度快 | DDL 页大小元数据必须严格匹配 |
| mysqldump 逻辑导出 | 中小表跨版本场景 | 兼容性最佳可跨大版本 | 时间与磁盘开销大 |
| mydumper / myloader | 中大表多线程并行 | 速度优于 mysqldump | 仍属逻辑层有行重插入开销 |
| XtraBackup 物理备份 | 整实例或多表 | 热备一致性好可用于 PITR | 工具链要求高恢复颗粒度为实例级 |
| 延迟从库 | 防误操作 DR | 实时同步可秒级介入 | 需提前规划有额外存储成本 |
6. 小结
DISCARD TABLESPACE 与 IMPORT TABLESPACE 的本质是:在表定义已存在的前提下,对 InnoDB 独立表空间文件进行物理替换。适合大表快速迁移与定向恢复。
成功使用该机制的核心前提:
- 有一份物理完好的 ibd 副本
- 源端与目标端的
innodb_page_size、ROW_FORMAT、表 DDL 严格一致 - 按照官方完整流程执行(FLUSH FOR EXPORT -> 拷贝 -> DISCARD -> 放文件 -> IMPORT),不走捷径
对于无备份的损坏、已 DROP 的表,应优先走备份 + binlog PITR 的正统恢复路径,将可传输表空间作为条件具备时的加速工具,而非替代数据保护体系的万能修复手段。