Rol*_*DBA 21
MyISAM 的复制非常简单,而 InnoDB 则完全有 100% 的风险(接近自杀)。
从你的问题中,你提出了
cp /db1/mytable.frm /db2/mytable.frm
Run Code Online (Sandbox Code Playgroud)
这样做是可以的。但是,您不能只移动 .frm。您必须移动所有组件。根据您的问题,让我们以一个名为 db1.mytable 的表为例。在正常安装中,该表位于 /var/lib/mysql/db1。将有三个文件组成该表。
您必须移动所有三个文件才能移动一张表。如果所有表都使用 MyISAM 存储引擎,则可以关闭 mysql 并复制。如果您只是简单地制作该表的副本并将其放入另一个数据库中,则应该使用 SQL 来执行此操作。
例如,如果要将 db1.mytable 复制到数据库 db2,请执行以下操作:
CREATE TABLE db2.mytable LIKE db1.mytable;
ALTER TABLE db2.mytable DISABLE KEYS;
INSERT INTO db2.mytable SELECT * FROM db1.mytable;
ALTER TABLE db2.mytable ENABLE KEYS;
Run Code Online (Sandbox Code Playgroud)
现在,如果您只是将表从 db1 移动到 db2,您可以这样做:
ALTER TABLE db1.mytable RENAME db2.mytable;
Run Code Online (Sandbox Code Playgroud)
由于 InnoDB 在其下工作的基础架构,复制非常危险。有两个基本的基础设施:1) innodb_file_per_table 禁用和 2) innodb_file_per_table 启用
InnoDB 的致命弱点是系统表空间文件 ibdata1(通常位于 /var/lib/mysql)。该文件中包含什么?
禁用 innodb_file_per_table 后,所有这些类型的 InnoDB 信息都位于 ibdata1 中。ibdata1 之外的任何 InnoDB 表的唯一表现形式是 InnoDB 表的 .frm 文件。一次复制所有 InnoDB 数据需要复制所有 /var/lib/mysql。
复制单个 InnoDB 表是完全不可能的。您必须 mysqldump 提取表的转储作为数据及其相应索引定义的逻辑表示。然后,您将该转储加载到同一服务器或另一台服务器上的另一个数据库。
启用 innodb_file_per_table 后,表数据及其索引位于 .frm 文件旁边的数据库文件夹中。例如,对于表 db1.mytable,该 InnoDB 表在 ibdata1 之外的表现形式为:
db1.mytable 的所有元数据仍然驻留在 ibdata1 中,绝对没有办法解决这个问题。重做日志和 MVCC 数据也仍然存在于 ibdata1 中。
如果您只想复制 .frm 和 .ibd 文件,那么您将面临痛苦的世界。复制 InnoDB 表的 .frm 和 .ibd 文件只有在您可以保证 .ibd 文件的表空间 id 与 ibdata1 文件的元数据中的表空间 id 条目完全匹配的情况下才是好的。
我在 DBA StackExchange 中写了两篇关于这个表空间 ID 概念的文章
这是关于如何在表空间 ID 不匹配的情况下将 .ibd 文件重新附加到 ibdata1 的优秀链接:http : //www.chriscalender.com/ ? tag=innodb-error-tablespace-id-in-file 。读完这篇,你应该能明白我为什么说近乎自杀了。
对于 InnoDB,您只需要这样做
CREATE TABLE db2.mytable LIKE db1.mytable;
INSERT INTO db2.mytable SELECT * FROM db1.mytable;
Run Code Online (Sandbox Code Playgroud)
制作 InnoDB 表的副本。如果要将其迁移到另一个数据库服务器,请使用 mysqldump。
复制整个 MySQL 数据目录是一种实用的技术,假设 MySQL 服务已停止并且您希望复制整个数据库服务器。
这是移动具有大索引的数据库的有用技术,并且 mysql 转储将不包括索引,需要在导入时重新生成索引。我发现这种技术在设置 MySQL 从站时很有用。
复制单个文件取决于使用的表模式,但在大多数情况下不是合适的解决方案。