17.6.1.3 导入 InnoDB 表
本节描述了使用Transportable Tablespaces特性导入表的方法,该特性允许将文件-per-表空间中的表、分区表或单个表分区导入到 MySQL 服务器中。有许多原因您可能想导入表:
-
在非生产 MySQL 服务器实例上运行报告,以避免在生产服务器上添加额外负载。
-
将数据复制到新副本服务器上。
-
从备份的表空间文件中恢复表。
-
作为比导入 dump 文件更快的方式,后者需要重新插入数据并重建索引。
-
将数据移到具有更适合存储要求的存储媒体上。例如,您可能将繁忙表移到 SSD 设备上,或者将大表移到高容量 HDD 设备上。
Transportable Tablespaces特性在本节中的以下主题中有描述:
-
必须启用
innodb_ file_per_table
变量,这是默认情况。 -
表空间的页面大小必须与目标MySQL服务器实例的页面大小相匹配。
InnoDB
页面大小由innodb_page_size
变量定义,该变量在初始化MySQL服务器实例时配置。 -
如果表具有外键关系,必须在执行
DISCARD TABLESPACE
之前禁用foreign_ key_ checks
。此外,您应该在同一个逻辑时间点导出所有相关的外键表,因为ALTER TABLE ... IMPORT TABLESPACE
不强制执行导入数据时的外键约束。要实现这一点,请停止更新相关表,提交所有事务,获取共享锁定,并执行导出操作。 -
从另一个MySQL服务器实例导入表时,两个MySQL服务器实例都必须具有General Availability(GA)状态且版本号相同。否则,表必须在目标MySQL服务器实例上创建,以便将其导入。
-
如果表格在外部目录中创建,使用
CREATE TABLE
语句中的DATA DIRECTORY
子句指定了目录,那么在目标实例中要替换的表格必须使用相同的DATA DIRECTORY
子句。否则,会报告 schema 不匹配错误。要确定源表是否定义了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
设置。有关相关信息,请参阅表的行格式定义。
导入表
这个示例演示了如何将一个非分区的常规表从文件表空间中导入到另一个文件表空间中。
-
在目标实例上,创建与您想导入的表定义相同的表。 (可以使用
SHOW CREATE TABLE
语法获得表定义。如果表定义不匹配,在尝试导入操作时将报告架构不匹配错误。mysql> USE test; mysql> CREATE TABLE t1 (c1 INT) ENGINE=INNODB;
-
在目标实例上,丢弃您刚创建的表空间。 (在导入之前,您必须丢弃接收表的表空间。)
mysql> ALTER TABLE t1 DISCARD TABLESPACE;
-
在源实例上,运行
FLUSH TABLES ... FOR EXPORT
以静止要导入的表。当一个表被静止时,只允许对该表进行只读事务。mysql> USE test; mysql> FLUSH TABLES t1 FOR EXPORT;
FLUSH TABLES ... FOR EXPORT
确保了对指定表的更改被刷新到磁盘,以便在服务器运行时生成二进制表副本。当FLUSH TABLES ... FOR EXPORT
被运行时,InnoDB
在表的schema目录中生成一个.cfg
元数据文件。该.cfg
文件包含用于 schema 验证的元数据,该元数据将在导入操作期间使用。Note执行
FLUSH TABLES ... FOR EXPORT
的连接必须保持打开状态,否则在锁释放时.cfg
文件将被删除。 -
从源实例复制
.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 Data-at-Rest Encryption”。 -
在源实例中,使用
UNLOCK TABLES
释放由FLUSH TABLES ... FOR EXPORT
语句获取的锁定:mysql> USE test; mysql> UNLOCK TABLES;
UNLOCK TABLES
操作还将删除.cfg
文件。 -
在目标实例中,导入表空间:
mysql> USE test; mysql> ALTER TABLE t1 IMPORT TABLESPACE;
Importing Partitioned 表
这个示例演示了如何导入一个分区表,每个表分区都位于文件-每-表空间中。
-
在目标实例上,创建一个与要导入的分区表具有相同定义的分区表。 (您可以使用
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
-
在目标实例上,丢弃分区表的表空间。 (在导入操作之前,您必须在接收表上丢弃表空间。)
mysql> ALTER TABLE t1 DISCARD TABLESPACE;
分区表的三个表空间
.ibd
文件从/
目录中丢弃。datadir
/test -
在源实例上,运行
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#p0.cfg t1#p#p1.cfg t1#p#p2.cfg
.cfg文件包含用于在导入表空间时验证架构的元数据。
FLUSH TABLES ... FOR EXPORT
只能在表级别运行,而不能在单个表分区上运行。 -
从源实例架构目录复制
.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 Data-at-Rest Encryption”。 -
在源实例上,使用
UNLOCK TABLES
释放由FLUSH TABLES ... FOR EXPORT
获取的锁:mysql> USE test; mysql> UNLOCK TABLES;
-
在目标实例上,导入分区表的表空间:
mysql> USE test; mysql> ALTER TABLE t1 IMPORT TABLESPACE;
本示例演示了如何导入单个表分区,每个分区位于文件-每-表空间文件中。
在以下示例中,四个分区中的两个分区(p2
和 p3
)被导入。
-
在目标实例上,创建一个与要导入分区的表定义相同的分区表。如果表定义不匹配,当您尝试导入操作时将报告架构不匹配错误。
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
-
在目标实例上, discard intended to import from the source instance。 (在导入分区之前,您必须从接收的分区表中 discard 对应的分区。)
mysql> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;
目标实例上的
.ibd
文件将被从/
目录中删除,留下以下文件:datadir
/testmysql> \! ls /path/to/datadir/test/ t1#p#p0.ibd t1#p#p1.ibd
Note当
ALTER TABLE ... DISCARD PARTITION ... TABLESPACE
在子分区表上运行时,允许指定分区和子分区名称。当指定分区名称时,该分区的子分区将被包含在操作中。 -
在源实例上,运行
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
只能在表级别运行,而不能在单个表分区上运行。 -
将partition
p2
和 partitionp3
的.ibd
和.cfg
文件从源实例的schema目录复制到目标实例的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
将生成一个.cfp
文件,以及一个.cfg
元数据文件。需要将.cfp
文件与.cfg
文件一起复制到目标实例中。.cfp
文件包含传输密钥和加密表空间密钥。在导入时,InnoDB
使用传输密钥来解密表空间密钥。有关相关信息,请参见第17.13节,“InnoDB Data-at-Rest Encryption”。 -
在源实例上,使用
UNLOCK TABLES
释放由FLUSH TABLES ... FOR EXPORT
获取的锁定:mysql> USE test; mysql> UNLOCK TABLES;
-
在目标实例上,导入表分区
p2
和p3
:mysql> USE test; mysql> ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
Note当
ALTER TABLE ... IMPORT PARTITION ... TABLESPACE
在子分区表上运行时,允许同时指定分区和子分区表名。当指定了分区名称时,该分区的所有子分区将被包含在操作中。
-
可transportable表空间特性仅支持在文件-per-表空间中存储的表。它不支持系统表空间或通用表空间中的表。共享表空间中的表不能被静默。
-
FLUSH TABLES ... FOR EXPORT
不支持具有FULLTEXT
索引的表,因为全文搜索辅助表不能被刷新。在导入具有FULLTEXT
索引的表后,运行OPTIMIZE TABLE
以重建FULLTEXT
索引。Alternatively,在导出操作之前删除FULLTEXT
索引,然后在目标实例上重新创建索引。 -
由于
.cfg
元数据文件限制,partition type或partition definition差异时不报告schema mismatches。当导入分区表时报告列差异。
-
除了包含瞬间添加或删除列的表外,
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
元数据文件的情况下,仅当不期望架构不匹配且表中无瞬态添加或删除列时才考虑导入该表。可以在崩溃恢复场景中使用该功能,因为元数据不可访问。尝试使用
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 ... TABLESPACE
和ALTER TABLE ... IMPORT PARTITION ... TABLESPACE
语句时,允许指定分区和子分区表名。指定分区名称时,将该分区的所有子分区包含在操作中。
以下信息描述了表导入过程中写入错误日志的内部信息和消息。
在目标实例上运行ALTER TABLE ... DISCARD TABLESPACE
时:
-
表被锁定在X模式下。
-
表空间从表中分离出来。
在源实例上运行FLUSH TABLES ... FOR EXPORT
时:
-
要导出的表被锁定在共享模式下。
-
purge协调线程停止。
-
脏页同步到磁盘上。
-
表元数据写入到二进制
.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
文件被删除。 -
要导入的表或表的共享锁被释放,purge协调线程被重新启动。
预期的错误日志消息对于这个操作:
[Note] InnoDB: Deleting the meta-data file './test/t1.cfg'
[Note] InnoDB: Resuming purge
在目标实例上运行ALTER TABLE ... IMPORT TABLESPACE
时,导入算法对每个要导入的表空间执行以下操作:
-
每个表空间页被检查是否损坏。
-
每个页上的space ID和日志序列号(LSNs)被更新。
-
标志被验证,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
http://dev.mysql.com/doc/refman/en/innodb-troubleshooting.html