本节描述如何使用可移植表空间功能导入表,该功能允许导入表、分区表或单个表分区,这些表驻留在每个表文件表空间中。您可能想要导入表的原因有很多:
-
在非生产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
设置。有关信息,请参阅定义表的行格式。
本示例演示如何导入一个常规的非分区表,该表驻留在每个表空间中。
-
在目标实例上,创建一个与要导入的表具有相同定义的表。(可以使用
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
在表的模式目录中生成一个.cfg
元数据文件。该.cfg
文件包含用于模式验证的元数据。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 数据静止加密”。 -
在源实例上,使用
UNLOCK TABLES
释放FLUSH TABLES ... FOR EXPORT
语句获取的锁:mysql> USE test; mysql> UNLOCK TABLES;
UNLOCK TABLES
操作也删除了.cfg
文件。 -
在目标实例上,导入表空间:
mysql> USE test; mysql> ALTER TABLE t1 IMPORT TABLESPACE;
本示例演示如何导入一个分区表,其中每个表分区驻留在每个表空间中。
-
在目标实例上,创建一个与要导入的分区表相同定义的分区表。(可以使用
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;
从
/
目录中丢弃了三个分区的表空间datadir
/test.ibd
文件。 -
在源实例上,运行
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
只能在整个表上运行,而不能在单个表分区上运行。 -
从源实例的模式目录复制
.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 数据静态加密”。 -
在源实例上,使用
UNLOCK TABLES
释放FLUSH TABLES ... FOR EXPORT
获取的锁:mysql> USE test; mysql> UNLOCK TABLES;
-
在目标实例上,导入分区表的表空间:
mysql> USE test; mysql> ALTER TABLE t1 IMPORT TABLESPACE;
本示例演示如何导入单个表分区,每个分区驻留在文件每个表空间文件中。
在以下示例中,四分区表的两个分区 (p2
和 p3
) 被导入。
-
在目标实例上,创建一个与要导入的分区表相同定义的分区表。(可以使用
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
-
在目标实例上,丢弃要从源实例导入的分区。(在导入分区之前,必须丢弃接收分区表的相应分区。)
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
时,既允许分区名称,也允许子分区表名称。当指定分区名称时,该分区的所有子分区都将包含在操作中。 -
在源实例上,运行
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
只能在表上运行,而不能在单个表分区上运行。 -
从源实例的 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 数据静默加密”。 -
在源实例上,使用
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
时,既允许分区名称,也允许子分区表名称。当指定分区名称时,该分区的所有子分区都将包含在操作中。
-
可移植表空间功能仅支持文件每个表空间中的表,不支持系统表空间或通用表空间中的表。共享表空间中的表不能静默化。
-
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 ... TABLESPACE
和ALTER 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.1/en/innodb-troubleshooting.html