Documentation Home

15.6.1.3 导入 InnoDB 表

本节介绍如何使用可 传输表空间功能导入表,该功能允许导入表、分区表或驻留在 file-per-table 表空间中的单个表分区。您可能想要导入表的原因有很多:

  • 在非生产 MySQL 服务器实例上运行报告以避免对生产服务器施加额外负载。

  • 将数据复制到新的副本服务器。

  • 从备份的表空间文件恢复表。

  • 作为一种比导入转储文件更快的移动数据方式,后者需要重新插入数据并重建索引。

  • 将数据移动到具有更适合您的存储要求的存储介质的服务器。例如,您可以将繁忙的表移动到 SSD 设备,或将大表移动到大容量 HDD 设备。

传输表空间功能在本节的以下主题下进行了描述:

先决条件
  • innodb_file_per_table 变量必须启用,默认情况下是启用的。

  • 表空间的页面大小必须与目标 MySQL 服务器实例的页面大小相匹配。 InnoDB页面大小由 innodb_page_size变量定义,该变量在初始化 MySQL 服务器实例时配置。

  • 如果表有外键关系, foreign_key_checks执行前必须禁用DISCARD TABLESPACE。此外,您应该在同一逻辑时间点导出所有与外键相关的表,因为 ALTER TABLE ... IMPORT TABLESPACE不会对导入的数据强制执行外键约束。为此,停止更新相关表,提交所有事务,获取表上的共享锁,并执行导出操作。

  • 从另一个 MySQL 服务器实例导入表时,两个 MySQL 服务器实例必须具有一般可用性 (GA) 状态并且必须是相同的版本。否则,必须在导入它的同一个 MySQL 服务器实例上创建该表。

  • DATA DIRECTORY如果表是通过在语句中指定子句在 外部目录中创建的CREATE TABLE,则您在目标实例上替换的表必须使用相同的DATA DIRECTORY 子句定义。如果子句不匹配,则会报告模式不匹配错误。要确定源表是否使用DATA DIRECTORY子句定义,请使用 SHOW CREATE TABLE查看表定义。有关使用该 DATA DIRECTORY子句的信息,请参阅 第 15.6.1.2 节,“在外部创建表”

  • 如果ROW_FORMAT选项未在表定义中明确定义或被 ROW_FORMAT=DEFAULT使用, innodb_default_row_format 则源实例和目标实例上的设置必须相同。否则,当您尝试导入操作时会报告架构不匹配错误。用于 SHOW CREATE TABLE检查表定义。用于SHOW VARIABLES检查 innodb_default_row_format 设置。有关相关信息,请参阅 定义表的行格式

导入表

此示例演示如何导入驻留在 file-per-table 表空间中的常规非分区表。

  1. 在目标实例上,创建一个与您要导入的表具有相同定义的表。(您可以使用SHOW CREATE TABLE语法获取表定义。)如果表定义不匹配,则在您尝试导入操作时会报告模式不匹配错误。

    mysql> USE test;
    mysql> CREATE TABLE t1 (c1 INT) ENGINE=INNODB;
  2. 在目标实例上,丢弃您刚刚创建的表的表空间。(导入前,必须丢弃接收表的表空间。)

    mysql> ALTER TABLE t1 DISCARD TABLESPACE;
  3. 在源实例上,运行 FLUSH TABLES ... FOR EXPORT以停止要导入的表。当表停止时,只允许在表上进行只读事务。

    mysql> USE test;
    mysql> FLUSH TABLES t1 FOR EXPORT;

    FLUSH TABLES ... FOR EXPORT确保将对命名表的更改刷新到磁盘,以便在服务器运行时可以制作二进制表副本。FLUSH TABLES ... FOR EXPORT运行时, 在 表的架构目录中InnoDB生成一个 元数据文件。.cfg.cfg文件包含在导入操作期间用于模式验证的元数据。

    笔记

    正在执行的连接 FLUSH TABLES ... FOR EXPORT必须在操作运行时保持打开状态;否则, .cfg文件将被删除,因为连接关闭时锁被释放。

  4. .ibd文件和 .cfg元数据文件从源实例复制到目标实例。例如:

    $> scp /path/to/datadir/test/t1.{ibd,cfg} destination-server:/path/to/datadir/test

    .ibd文件和 .cfg文件必须在释放共享锁之前复制,如下一步所述 。

    笔记

    如果您从加密表空间导入表, 除了 元数据文件之外还会InnoDB生成一个 文件。该 文件必须与 文件一起复制到目标实例。该 文件包含一个传输密钥和一个加密的表空间密钥。导入时, 使用传输密钥解密表空间密钥。有关相关信息,请参阅 第 15.13 节,“InnoDB 静态数据加密”.cfp.cfg.cfp.cfg.cfpInnoDB

  5. 在源实例上,用于 释放语句 UNLOCK TABLES获取的锁 :FLUSH TABLES ... FOR EXPORT

    mysql> USE test;
    mysql> UNLOCK TABLES;

    UNLOCK TABLES操作还会删除该 .cfg文件。

  6. 在目标实例上,导入表空间:

    mysql> USE test;
    mysql> ALTER TABLE t1 IMPORT TABLESPACE;
导入分区表

此示例演示如何导入分区表,其中每个表分区都位于一个文件每表表空间中。

  1. 在目标实例上,创建一个分区表,其定义与要导入的分区表相同。(您可以使用 SHOW CREATE TABLE语法获取表定义。)如果表定义不匹配,则在您尝试导入操作时会报告模式不匹配错误。

    mysql> USE test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;

    在该 目录中, 三个分区各有一个表空间文件。 /datadir/test.ibd

    mysql> \! ls /path/to/datadir/test/
    t1#p#p0.ibd  t1#p#p1.ibd  t1#p#p2.ibd
  2. 在目标实例上,丢弃分区表的表空间。(导入操作前,必须丢弃接收表的表空间。)

    mysql> ALTER TABLE t1 DISCARD TABLESPACE;

    分区表的三个表空间.ibd文件从 目录中丢弃。 /datadir/test

  3. 在源实例上,运行 FLUSH TABLES ... FOR EXPORT以停顿您要导入的分区表。当表停止时,只允许在表上进行只读事务。

    mysql> USE test;
    mysql> FLUSH TABLES t1 FOR EXPORT;

    FLUSH TABLES ... FOR EXPORT确保将对命名表的更改刷新到磁盘,以便可以在服务器运行时进行二进制表复制。FLUSH TABLES ... FOR EXPORT运行时, 在 表的模式目录中为每个表的表空间文件InnoDB生成 .cfg元数据文件。

    mysql> \! ls /path/to/datadir/test/
    t1#p#p0.ibd  t1#p#p1.ibd  t1#p#p2.ibd
    t1#p#p0.cfg  t1#p#p1.cfg  t1#p#p2.cfg

    这些.cfg文件包含在导入表空间时用于模式验证的元数据。 FLUSH TABLES ... FOR EXPORT只能在表上运行,不能在单个表分区上运行。

  4. .ibd.cfg文件从源实例架构目录复制到目标实例架构目录。例如:

    $>scp /path/to/datadir/test/t1*.{ibd,cfg} destination-server:/path/to/datadir/test

    在 释放共享锁之前必须复制 .ibd和文件,如下一步所述。.cfg

    笔记

    如果您从加密表空间导入表, 除了 元数据文件之外还会InnoDB生成一个 文件。文件必须与文件一起复制到目标 实例 。这些 文件包含一个传输密钥和一个加密的表空间密钥。导入时, 使用传输密钥解密表空间密钥。有关相关信息,请参阅 第 15.13 节,“InnoDB 静态数据加密”.cfp.cfg.cfp.cfg.cfpInnoDB

  5. 在源实例上,用于 UNLOCK TABLES释放通过获取的锁 FLUSH TABLES ... FOR EXPORT

    mysql> USE test;
    mysql> UNLOCK TABLES;
  6. 在目标实例上,导入分区表的表空间:

    mysql> USE test;
    mysql> ALTER TABLE t1 IMPORT TABLESPACE;
导入表分区

此示例演示如何导入单个表分区,其中每个分区驻留在一个文件每表表空间文件中。

在以下示例中,导入了四分区表的 两个分区(p2 和)。p3

  1. 在目标实例上,创建一个分区表,其定义与要从中导入分区的分区表相同。(您可以使用SHOW CREATE TABLE语法获取表定义。)如果表定义不匹配,则在您尝试导入操作时会报告模式不匹配错误。

    mysql> USE test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;

    在该 目录中, 四个分区各有一个表空间文件。 /datadir/test.ibd

    mysql> \! ls /path/to/datadir/test/
    t1#p#p0.ibd  t1#p#p1.ibd  t1#p#p2.ibd t1#p#p3.ibd
  2. 在目标实例上,丢弃您打算从源实例导入的分区。(在导入分区之前,您必须从接收分区表中丢弃相应的分区。)

    mysql> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;

    两个废弃分区的表空间.ibd文件从 目标实例上的目录中删除,留下以下文件: /datadir/test

    mysql> \! ls /path/to/datadir/test/
    t1#p#p0.ibd  t1#p#p1.ibd
    笔记

    ALTER TABLE ... DISCARD PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名称都是允许的。指定分区名称时,该分区的子分区将包含在操作中。

  3. 在源实例上,运行 FLUSH TABLES ... FOR EXPORT以停止分区表。当表停止时,只允许在表上进行只读事务。

    mysql> USE test;
    mysql> FLUSH TABLES t1 FOR EXPORT;

    FLUSH TABLES ... FOR EXPORT确保将对命名表的更改刷新到磁盘,以便可以在实例运行时进行二进制表复制。FLUSH TABLES ... FOR EXPORT运行时, 在 表的模式目录中为表的每个表空间文件 InnoDB生成一个 元数据文件。.cfg

    mysql> \! ls /path/to/datadir/test/
    t1#p#p0.ibd  t1#p#p1.ibd  t1#p#p2.ibd t1#p#p3.ibd
    t1#p#p0.cfg  t1#p#p1.cfg  t1#p#p2.cfg t1#p#p3.cfg

    这些.cfg文件包含在导入操作期间用于模式验证的元数据。 FLUSH TABLES ... FOR EXPORT只能在表上运行,不能在单个表分区上运行。

  4. 将分区 和分区的文件.ibd和 文件 从源实例架构目录复制到目标实例架构目录。 .cfgp2p3

    $> scp t1#p#p2.ibd t1#p#p2.cfg t1#p#p3.ibd t1#p#p3.cfg destination-server:/path/to/datadir/test

    在 释放共享锁之前必须复制 .ibd和文件,如下一步所述。.cfg

    笔记

    如果您从加密表空间导入分区,除了 元数据文件之外还会InnoDB生成一个 文件。文件必须与文件一起复制到目标 实例 。这些 文件包含一个传输密钥和一个加密的表空间密钥。导入时, 使用传输密钥解密表空间密钥。有关相关信息,请参阅 第 15.13 节,“InnoDB 静态数据加密”.cfp.cfg.cfp.cfg.cfpInnoDB

  5. 在源实例上,用于 UNLOCK TABLES释放通过获取的锁 FLUSH TABLES ... FOR EXPORT

    mysql> USE test;
    mysql> UNLOCK TABLES;
  6. 在目标实例上,导入表分区 p2p3

    mysql> USE test;
    mysql> ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
    笔记

    ALTER TABLE ... IMPORT PARTITION ... TABLESPACE在子分区表上运行时,分区和子分区表名称都是允许的。指定分区名称时,该分区的子分区将包含在操作中。

限制
  • Transportable Tablespaces功能仅支持驻留在 file-per-table 表空间中的表 。驻留在系统表空间或通用表空间中的表不支持它。共享表空间中的表不能被停顿。

  • FLUSH TABLES ... FOR EXPORT具有FULLTEXT索引的表不支持,因为无法刷新全文搜索辅助表。导入带FULLTEXT索引的表后,运行 OPTIMIZE TABLE重建 FULLTEXT索引。或者,在导出操作之前删除 FULLTEXT索引,并在目标实例上导入表后重新创建索引。

  • 由于.cfg元数据文件的限制,在导入分区表时,不会报告分区类型或分区定义差异的模式不匹配。报告列差异。

  • 在 MySQL 8.0.19 之前,索引键部分排序顺序信息不会存储到.cfg表空间导入操作期间使用的元数据文件中。因此假定索引键部分排序顺序为升序,这是默认值。因此,如果导入操作中涉及的一个表是使用 DESC 索引键部分排序顺序定义的,而另一个表不是,则记录可能会按意外的顺序排序。解决方法是删除并重新创建受影响的索引。有关索引键部分排序顺序的信息,请参阅第 13.1.15 节,“CREATE INDEX 语句”

    文件格式在.cfgMySQL 8.0.19 中更新为包含索引键部分排序信息。上述问题不影响 MySQL 8.0.19 服务器实例或更高版本之间的导入操作。

使用说明
  • 除了包含立即添加或删除的列的表外, ALTER TABLE ... IMPORT TABLESPACE不需要 .cfg元数据文件来导入表。但是在没有文件的情况下导入时不执行元数据检查.cfg,并发出类似如下的警告:

    Message: InnoDB: IO Read error: (2, No such file or directory) Error opening '.\
    test\t.cfg', will attempt to import without schema verification
    1 row in set (0.00 sec)

    .cfg 仅当预计不会出现模式不匹配且表不包含任何立即添加或删除的列时,才应考虑 导入没有元数据文件的表。在无法访问元数据的崩溃恢复场景中,无需文件即可导入的功能.cfg可能很有用。

    尝试在ALGORITHM=INSTANT不使用.cfg文件的情况下导入包含已添加或删除的列的表可能会导致未定义的行为。

  • 在 Windows 上,InnoDB以小写形式在内部存储数据库、表空间和表名称。为避免在 Linux 和 Unix 等区分大小写的操作系统上出现导入问题,请使用小写名称创建所有数据库、表空间和表。确保以小写形式创建名称的一种简便方法是 lower_case_table_names在初始化服务器之前将其设置为 1。(禁止 lower_case_table_names 使用与服务器初始化时使用的设置不同的设置启动服务器。)

    [mysqld]
    lower_case_table_names=1
  • 在子分区表上运行 时,分区ALTER TABLE ... DISCARD PARTITION ... TABLESPACEALTER TABLE ... IMPORT PARTITION ... TABLESPACE子分区表名都是允许的。指定分区名称时,该分区的子分区将包含在操作中。

内部结构

以下信息描述了在表导入过程中写入错误日志的内部信息和消息。

何时ALTER TABLE ... DISCARD TABLESPACE在目标实例上运行:

  • 该表在 X 模式下被锁定。

  • 表空间与表分离。

何时 FLUSH TABLES ... FOR EXPORT在源实例上运行:

  • 为导出而刷新的表在共享模式下被锁定。

  • 清除协调器线程已停止。

  • 脏页同步到磁盘。

  • 表元数据被写入二进制 .cfg文件。

此操作的预期错误日志消息:

[Note] InnoDB: Sync to disk of '"test"."t1"' started.
[Note] InnoDB: Stopping purge
[Note] InnoDB: Writing table metadata to './test/t1.cfg'
[Note] InnoDB: Table '"test"."t1"' flushed to disk

何时UNLOCK TABLES在源实例上运行:

  • 二进制.cfg文件被删除。

  • 释放正在导入的一个或多个表上的共享锁,并重新启动清除协调器线程。

此操作的预期错误日志消息:

[Note] InnoDB: Deleting the meta-data file './test/t1.cfg'
[Note] InnoDB: Resuming purge

ALTER TABLE ... IMPORT TABLESPACE在目标实例上运行时,导入算法对每个正在导入的表空间执行以下操作:

  • 检查每个表空间页面是否损坏。

  • 每个页面上的空间 ID 和日志序列号 (LSN) 都会更新。

  • 为标题页验证标志并更新 LSN。

  • Btree 页面已更新。

  • 页面状态设置为脏,以便将其写入磁盘。

此操作的预期错误日志消息:

[Note] InnoDB: Importing tablespace for table 'test/t1' that was exported
from host 'host_name'
[Note] InnoDB: Phase I - Update all pages
[Note] InnoDB: Sync to disk
[Note] InnoDB: Sync to disk - done!
[Note] InnoDB: Phase III - Flush changes to disk
[Note] InnoDB: Phase IV - Flush complete
笔记

.ibd您可能还会收到一条表空间被丢弃的警告(如果您丢弃了目标表的表空间)和一条消息,指出由于缺少文件 而无法计算统计信息:

[Warning] InnoDB: Table "test"."t1" tablespace is set as discarded.
7f34d9a37700 InnoDB: cannot calculate statistics for table
"test"."t1" because the .ibd file is missing. For help, please refer to
http://dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting.html