Documentation Home
MySQL 8.3 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 40.8Mb
PDF (A4) - 40.9Mb
Man Pages (TGZ) - 294.0Kb
Man Pages (Zip) - 409.0Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb
Excerpts from this Manual

MySQL 8.3 Reference Manual  /  ...  /  Importing InnoDB Tables

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文件包含用于模式验证的元数据。

    Note

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

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

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

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

    Note

    如果您正在从加密表空间导入表,InnoDB将生成一个.cfp文件,除了.cfg元数据文件外。该.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;

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

  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 文件,如下一步所述。

    Note

    如果您要从加密表空间导入表,InnoDB 还将生成一个 .cfp 文件,除了 .cfg 元数据文件外。必须将 .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
    Note

    当在子分区表上运行 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 在表的 schema 目录中生成每个表空间文件的 .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 文件包含用于 schema 验证的元数据,在导入操作期间使用。FLUSH TABLES ... FOR EXPORT 只能在表上运行,而不能在单个表分区上运行。

  4. 从源实例的 schema 目录中复制分区 p2 和分区 p3.ibd.cfg 文件到目标实例的 schema 目录。

    $> 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 文件,如下一步所述。

    Note

    如果您从加密表空间导入分区,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;
    Note

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

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

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

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

使用说明
  • 除了即时添加或删除列的表外,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 被更新到头页。

  • 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
Note

您还可能收到警告,表空间被丢弃(如果您为目标表丢弃了表空间),并且收到一条消息,指出由于缺少 .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.1/en/innodb-troubleshooting.html