文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  导入 InnoDB 表

17.6.1.3 导入 InnoDB 表

本节介绍如何使用可移植表空间功能导入表,该功能允许导入位于每个表一个表空间中的表、分区表或单个表分区。您可能需要导入表的几个原因:

  • 在非生产 MySQL 服务器实例上运行报告,以避免给生产服务器带来额外负载。

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

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

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

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

本节中的以下主题描述了可移植表空间功能:

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

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

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

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

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

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

导入表

此示例演示如何导入位于每个表表空间中的文件中的常规非分区表。

  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 除了 .cfg 元数据文件之外还会生成一个 .cfp 文件。 .cfp 文件必须与 .cfg 文件一起复制到目标实例。 .cfp 文件包含一个传输密钥和一个加密的表空间密钥。在导入时, InnoDB 使用传输密钥来解密表空间密钥。有关相关信息,请参见 第 17.13 节“InnoDB 数据静止加密”

  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 除了 .cfg 元数据文件之外还会生成一个 .cfp 文件。 .cfp 文件必须与 .cfg 文件一起复制到目标实例。 .cfp 文件包含一个传输密钥和一个加密的表空间密钥。在导入时, InnoDB 使用传输密钥来解密表空间密钥。有关相关信息,请参见 第 17.13 节“InnoDB 数据静止加密”

  5. 在源实例上,使用 UNLOCK TABLES 来释放由 FLUSH TABLES ... FOR EXPORT 获取的锁。

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

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

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

在以下示例中,将导入一个四分区表的两个分区( p2p3 )。

  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;

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

    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. 将分区 p2 和分区 p3.ibd.cfg 文件从源实例架构目录复制到目标实例架构目录。

    $> 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 除了 .cfg 元数据文件之外还会生成一个 .cfp 文件。 .cfp 文件必须与 .cfg 文件一起复制到目标实例。 .cfp 文件包含一个传输密钥和一个加密的表空间密钥。在导入时, InnoDB 使用传输密钥来解密表空间密钥。有关相关信息,请参见 第 17.13 节“InnoDB 数据静止加密”

  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 时,分区和子分区表名称都允许使用。当指定分区名称时,该分区的子分区将包含在操作中。

限制
  • 可移植表空间 功能仅支持位于每个表表空间中的文件中的表。它不支持位于系统表空间或通用表空间中的表。共享表空间中的表无法静默。

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

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

使用说明
  • 除了包含立即添加或删除的列的表之外, 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 文件的情况下导入的能力可能很有用,在这种情况下,元数据不可访问。

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

  • 在 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。

  • 将更新 B 树页面。

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

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

[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
https://dev.mysqlserver.cn/doc/refman/en/innodb-troubleshooting.html