mysql之数据离线迁移

在实际的业务需求中,mysql数据库往往需要从一个服务器迁移或者导出到另外一台服务器。这个数据导入导出的工作,是不可避免的。

mysql对于数据的导入导出提供了逻辑操作与物理操作两种方式,其中mysqdump的逻辑操作往往需要生成SQL文件,如果数据量比较大,可能执行的效果比较差,耗时比较长。本文主要介绍一下基于mysql文件层面的物理操作,也可以叫做冷备份。

mysql的相关官网说明

mysql官网

Transportable Tablespace(可传输表空间 ) 是 MySQL InnoDB 存储引擎提供的一种机制,允许用户将某个表的表空间文件(.ibd )及其元数据校验文件(.cfg)从一台服务器"运输"到另一台服务器,并直接挂载到目标数据库的表结构上。

核心原理

InnoDB 表空间文件内部包含了一个唯一的 Tablespace ID 和 Schema 指纹。直接拷贝 .ibd 文件时,目标库的元数据(Data Dictionary)中记录的 ID 与文件内部的 ID 不一致,导致无法识别。

  • .ibd实际的数据文件
  • .cfg :由 FLUSH TABLES ... FOR EXPORT 命令生成。它包含了表空间的元数据副本(包括 Tablespace ID、Schema 校验和、页大小等)。
  • 流程本质:
    1. 目标库先创建一个空表,生成一个新的空的 .ibd。
    2. 执行 DISCARD TABLESPACE:目标库删除这个空的 .ibd,并进入"等待导入"状态。
    3. 放入源库的 .ibd 和 .cfg。
    4. 执行 IMPORT TABLESPACE:目标库读取 .cfg,验证 .ibd 的完整性和一致性。如果通过,它将更新内部数据字典,将现有的 .ibd 文件"认领"为该表的数据文件。

详细的操作流程

假设我们要迁移表 users,数据库为 test_db。

前提条件:

  • 源库和目标库 MySQL 大版本一致(如都是 5.7 或 8.0)。
  • 源库和目标库的 innodb_file_per_table 均为 ON。
  • 目标库已创建好结构完全一致的表。

第一阶段:在源库(Source)生成文件

这一步的目的是获取一份一致性快照数据文件配套的校验文件

  1. 确保表是可传输的(通常默认就是,但显式执行一次更稳妥):
bash 复制代码
USE test_db;
-- 这一步会刷新脏页到磁盘,并锁定表进行元数据冻结
FLUSH TABLES users FOR EXPORT;

注意:执行此命令后,表 users 会被锁定为只读(Read Only),直到你解锁或复制完文件。其他会话对该表的写操作会被阻塞。

  1. 复制文件
    保持终端窗口不关闭(保持锁状态),打开另一个终端或通过脚本复制文件。
    找到数据目录(通常是 /var/lib/mysql/test_db/):
    • users.ibd:数据文件。
    • users.cfg:关键文件,包含元数据校验信息。
bash 复制代码
# 在另一个终端执行
cp /var/lib/mysql/test_db/users.{ibd,cfg} /tmp/backup_for_migration/

# 确认文件已复制完成
ls -lh /tmp/backup_for_migration/
  1. 解锁源库
    文件复制完成后,必须立即解锁,恢复业务写入。
    回到第一个执行 SQL 的终端:
bash 复制代码
UNLOCK TABLES;

此时源库业务恢复正常。

第二阶段:在目标库(Target)准备环境

  1. 创建结构一致的表
    在目标库执行与源库完全相同的 CREATE TABLE 语句。
sql 复制代码
CREATE DATABASE IF NOT EXISTS test_db;
USE test_db;

CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    -- 必须与源库完全一致,包括字符集、排序规则、索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

提示:可以用 SHOW CREATE TABLE users\G 在源库查看精确语句。

  1. 丢弃自动生成的表空间:

刚才建表时,InnoDB 已经生成了一个空的 users.ibd。需要删掉它,以便导入旧的。

sql 复制代码
ALTER TABLE users DISCARD TABLESPACE;

执行后,去操作系统查看 /var/lib/mysql/test_db/users.ibd,它应该已经消失了。此时表存在,但无法读写数据。

第三阶段:导入文件到目标库

  1. 拷贝文件到目标数据目录:
    将第一阶段生成的 users.ibd 和 users.cfg 上传到目标库对应的数据目录。
bash 复制代码
# 假设文件在 /tmp/backup_for_migration/
cp /tmp/backup_for_migration/users.{ibd,cfg} /var/lib/mysql/test_db/
  1. 修正文件权限(至关重要):
    MySQL 进程通常以 mysql 用户运行。如果文件归属是 root,导入会失败。
mysql 复制代码
chown mysql:mysql /var/lib/mysql/test_db/users.{ibd,cfg}
chmod 660 /var/lib/mysql/test_db/users.{ibd,cfg}
  1. 执行导入命令
    登录目标库 MySQL:
bash 复制代码
USE test_db;
ALTER TABLE users IMPORT TABLESPACE;
  • 如果成功:无任何输出,表立即变为可用状态。
  • 如果失败:会报错。常见原因包括:
    • Schema mismatch:建表语句不一致(字段类型、顺序、字符集等)。
    • Tablespace ID mismatch:通常是因为没执行 DISCARD TABLESPACE 或者 .cfg 文件不匹配。
  1. 验证数据:
sql 复制代码
SELECT COUNT(*) FROM users;
SELECT * FROM users LIMIT 5;

特点与限制
优点

  1. 速度极快:不涉及逻辑导出(SQL 生成)和导入(SQL 解析执行),本质是文件拷贝,适合 TB 级大表迁移。
  2. 节省 IO:不会像 mysqldump 那样产生巨大的重做日志(Redo Log)和二进制日志(Binlog)压力(导入时可以暂时关闭 Binlog)。
  3. 支持分区表:可以单独导入某个分区,也可以导入整个分区表。

限制与注意事项

  1. 版本严格限制:
  • 源和目标必须是相同的大版本(如 5.7 -> 5.7, 8.0 -> 8.0)。
  • 跨大版本(如 5.6 -> 8.0)通常不支持,因为 .ibd 内部格式可能发生变化。
  1. 架构一致:
  • 表结构(DDL)必须比特级一致。哪怕是字符集 utf8 和 utf8mb4 的区别,或者自增列初始值不同,都可能导致 Schema mismatch 错误。
  1. 只针对 InnoDB:MyISAM 或其他引擎不适用。
  2. 外键约束:如果表之间有外键约束,导入过程可能会比较复杂,建议先禁用外键检查 (SET FOREIGN_KEY_CHECKS=0),导入后再开启。
  3. 只读窗口:在源库执行 FLUSH TABLES ... FOR EXPORT 期间,该表是只读的。虽然时间很短(仅拷贝文件的时间),但在高并发场景下仍需注意。

总结

Transportable Tablespace 是 MySQL 官方提供的"物理备份/迁移"方案。

  • 核心命令组合:FLUSH TABLES ... FOR EXPORT (源) + DISCARD TABLESPACE (目标) + IMPORT TABLESPACE (目标)
  • 关键文件:.ibd (数据) + .cfg (元数据校验)
  • 适用场景:海量数据快速迁移、表空间损坏后的单表恢复、跨实例克隆大表
相关推荐
电商API&Tina2 小时前
京东商品详情API接口接入与应用
数据库·microsoft
OnYoung2 小时前
理解关系数据库表间的一对一和一对多关系
数据库
南 阳2 小时前
Python从入门到精通day37
数据库·python·oracle
轩情吖3 小时前
MySQL初识
android·数据库·sql·mysql·adb·存储引擎
Traced back3 小时前
【.NET7 WinForm 实战】三层架构+EF Core+多数据库+完整功能(源码+教程+脚本)
数据库·架构·.net
观测云3 小时前
KES(KingbaseES)数据库监控最佳实践
数据库
ding_zhikai3 小时前
【Web应用开发笔记】Django笔记4-1:简单使用 Django 与本地数据库
数据库·笔记·后端·python
奇点爆破XC3 小时前
Redis迁移
数据库·redis·bootstrap
断手当码农3 小时前
Redis 实现分布式锁的三种方式
数据库·redis·分布式