一、什么是传输表空间

简单来说,传输表空间就是将一个MySQL实例中的表空间文件(.ibd文件)复制到另一个MySQL实例中,并通过特定命令将其挂载到目标数据库的技术。这就像搬家时直接把整个衣柜搬走,而不是一件件重新挂衣服。

核心优势在于:

  1. 比传统导出导入快10倍以上
  2. 几乎不影响源库性能
  3. 支持跨版本迁移(5.6→5.7→8.0)

二、完整操作流程演示

环境准备(MySQL 8.0技术栈)

-- 源库创建测试表
CREATE DATABASE source_db;
USE source_db;

CREATE TABLE t_order (
  id INT AUTO_INCREMENT PRIMARY KEY,
  order_no VARCHAR(20) NOT NULL,
  amount DECIMAL(10,2) DEFAULT 0.00,
  KEY idx_order_no (order_no)
) ENGINE=InnoDB;

-- 插入50万测试数据
DELIMITER //
CREATE PROCEDURE batch_insert()
BEGIN
  DECLARE i INT DEFAULT 1;
  WHILE i <= 500000 DO
    INSERT INTO t_order(order_no, amount) 
    VALUES(CONCAT('NO',i), ROUND(RAND()*100,2));
    SET i = i + 1;
  END WHILE;
END //
DELIMITER ;

CALL batch_insert();

关键操作步骤

-- 步骤1:在源库锁定表
FLUSH TABLES t_order FOR EXPORT;  -- 此时会生成.cfg元数据文件

-- 步骤2:复制文件(在操作系统层面执行)
/* 
cp /var/lib/mysql/source_db/t_order.{ibd,cfg} /backup/
*/

-- 步骤3:释放锁
UNLOCK TABLES;

-- 步骤4:在目标库创建相同结构的表
CREATE DATABASE dest_db;
USE dest_db;

CREATE TABLE t_order (
  id INT AUTO_INCREMENT PRIMARY KEY,
  order_no VARCHAR(20) NOT NULL,
  amount DECIMAL(10,2) DEFAULT 0.00,
  KEY idx_order_no (order_no)
) ENGINE=InnoDB;

-- 步骤5:丢弃目标表空间
ALTER TABLE t_order DISCARD TABLESPACE;

-- 步骤6:复制文件到目标库数据目录
/*
cp /backup/t_order.{ibd,cfg} /var/lib/mysql/dest_db/
chown mysql:mysql /var/lib/mysql/dest_db/t_order.*
*/

-- 步骤7:导入表空间
ALTER TABLE t_order IMPORT TABLESPACE;

-- 验证数据
SELECT COUNT(*) FROM t_order;  -- 应返回500000

三、技术实现原理

整个过程就像器官移植手术:

  1. FLUSH TABLES FOR EXPORT:相当于给表打上冷冻剂,生成.cfg文件记录表结构校验信息
  2. DISCARD TABLESPACE:目标表进入"无器官"状态
  3. IMPORT TABLESPACE:将新器官(.ibd文件)与目标表血管(数据字典)连接

关键校验点

  • 表结构定义必须完全一致(包括字段顺序、索引、字符集)
  • 页面的LSN号会被重置
  • 会验证文件头中的space ID

四、典型应用场景

1. 跨实例大数据量迁移

当需要迁移500GB以上的大表时,传统dump方式可能需要数小时,而传输表空间通常能在30分钟内完成。

2. 数据仓库快速加载

每天将生产库的订单表同步到分析库,相比ETL流程可节省80%时间。

3. 表空间回收

对于删除大量数据后表空间未收缩的情况:

-- 在原库执行
CREATE TABLE t_order_new LIKE t_order;
INSERT INTO t_order_new SELECT * FROM t_order;
FLUSH TABLES t_order_new FOR EXPORT;
-- 然后按照标准流程迁移

五、注意事项与踩坑指南

  1. 版本兼容性矩阵

    • 5.6 → 5.7:必须相同小版本
    • 5.7 → 8.0:需要开启explicit_defaults_for_timestamp
  2. 常见报错处理

-- 错误1:Schema mismatch
ERROR 1808 (HY000): Schema mismatch

-- 解决方案:用SHOW CREATE TABLE对比表结构

-- 错误2:加密表空间
ERROR 3185 (HY000): Can't find master key from keyring

-- 解决方案:先在目标库创建相同加密密钥
  1. 性能影响
    • FOR EXPORT锁表期间会阻塞所有写操作
    • 建议在业务低峰期操作
    • 大表准备.cfg文件可能消耗较多I/O

六、与传统方法的对比

指标 传输表空间 mysqldump 主从复制
速度 ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐
锁表时间 分钟级 小时级 持续
网络带宽消耗
操作复杂度
数据一致性 强一致 强一致 最终一致

七、高级技巧延伸

1. 批量操作脚本示例

#!/bin/bash
# 批量迁移整个数据库
DB="source_db"
TABLES=$(mysql -Nse "SHOW TABLES FROM $DB")

for TABLE in $TABLES; do
  # 导出单表流程
  mysql -e "FLUSH TABLES $DB.$TABLE FOR EXPORT"
  cp /var/lib/mysql/$DB/$TABLE.{ibd,cfg} /backup/
  mysql -e "UNLOCK TABLES"
  
  # 导入流程
  mysql -e "ALTER TABLE $DB.$TABLE DISCARD TABLESPACE"
  cp /backup/$TABLE.{ibd,cfg} /var/lib/mysql/$DB/
  mysql -e "ALTER TABLE $DB.$TABLE IMPORT TABLESPACE"
done

2. 与GTID复制结合

-- 在从库执行
STOP SLAVE;
-- 传输表空间操作...
START SLAVE;
-- 会自动从主库补binlog

八、总结

传输表空间就像数据库世界的"器官移植手术",虽然操作步骤稍复杂,但对于大数据量迁移场景堪称神器。掌握这项技术后,当遇到TB级数据迁移需求时,你就能淡定地说:"小case,今晚加个班搞定!"

最后提醒三个黄金法则:

  1. 操作前一定备份
  2. 严格校验表结构
  3. 做好回滚预案