以下是关于 MERGE
表的已知问题
在早于 5.1.23 的 MySQL 服务器版本中,可以使用非临时子 MyISAM 表创建临时合并表。
从 5.1.23 版本开始,MERGE 子表通过父表进行锁定。如果父表是临时的,则不会被锁定,因此子表也不会被锁定。并行使用 MyISAM 表会导致表损坏。
如果您使用
ALTER TABLE
将MERGE
表更改为其他存储引擎,则对底层表的映射将丢失。相反,来自底层MyISAM
表的行将被复制到已更改的表中,然后该表使用指定的存储引擎。用于
MERGE
表的INSERT_METHOD
表选项指示要使用哪个底层MyISAM
表来插入到MERGE
表中。但是,直到至少有一行直接插入到MyISAM
表中,该MyISAM
表的AUTO_INCREMENT
表选项对插入到MERGE
表中的内容才会生效。MERGE
表不能在整个表上维护唯一性约束。当您执行INSERT
时,数据将进入第一个或最后一个MyISAM
表(由INSERT_METHOD
选项决定)。MySQL 确保唯一键值在该MyISAM
表内保持唯一,但在整个底层表集中不保证唯一性。由于
MERGE
引擎无法在底层表集中强制唯一性,因此REPLACE
无法按预期工作。两个关键事实是类似的考虑适用于
INSERT ... ON DUPLICATE KEY UPDATE
.MERGE
表不支持分区。也就是说,您不能对MERGE
表进行分区,也不能对MERGE
表的任何底层MyISAM
表进行分区。您不应该在任何映射到打开的
MERGE
表的表上使用ANALYZE TABLE
、REPAIR TABLE
、OPTIMIZE TABLE
、ALTER TABLE
、DROP TABLE
、DELETE
(不带WHERE
子句)或TRUNCATE TABLE
。如果您这样做,MERGE
表可能仍然引用原始表,并产生意外的结果。要解决此问题,请在执行任何上述操作之前,通过发出FLUSH TABLES
语句确保没有打开的MERGE
表。意外结果包括在对
MERGE
表的操作报告表损坏的可能性。如果在对底层MyISAM
表进行上述操作之一后发生这种情况,则损坏消息是虚假的。为了处理这种情况,在修改MyISAM
表后,发出FLUSH TABLES
语句。DROP TABLE
在 Windows 上对MERGE
表使用的表不起作用,因为MERGE
存储引擎的表映射对 MySQL 的上层隐藏。Windows 不允许删除打开的文件,因此您必须先刷新所有MERGE
表(使用FLUSH TABLES
)或删除MERGE
表,然后才能删除该表。当访问表(例如,作为
SELECT
或INSERT
语句的一部分)时,将检查MyISAM
表和MERGE
表的定义。这些检查通过比较列顺序、类型、大小和关联索引来确保表定义和父MERGE
表定义匹配。如果表之间存在差异,则会返回错误,并且语句将失败。由于这些检查在打开表时进行,因此对单个表的定义所做的任何更改,包括列更改、列顺序和引擎更改,都会导致语句失败。MERGE
表及其底层表中的索引顺序应相同。如果您使用ALTER TABLE
为MERGE
表中使用的表添加UNIQUE
索引,然后使用ALTER TABLE
为MERGE
表添加非唯一索引,如果底层表中已存在非唯一索引,则表的索引顺序将不同。(这是因为ALTER TABLE
将UNIQUE
索引放在非唯一索引之前,以方便快速检测重复键。)因此,对具有此类索引的表的查询可能会返回意外的结果。如果您遇到类似于 ERROR 1017 (HY000): Can't find file: '
tbl_name
.MRG' (errno: 2) 的错误消息,通常表明某些底层表未使用MyISAM
存储引擎。确认所有这些表都是MyISAM
。MERGE
表中的最大行数为 264(约为 1.844E+19;与MyISAM
表相同)。不可能将多个MyISAM
表合并到单个MERGE
表中,该表将拥有超过此数量的行。当前已知使用不同行格式的底层
MyISAM
表与父MERGE
表一起使用会失败。请参见 Bug #32364。当
LOCK TABLES
生效时,您无法更改非临时MERGE
表的并集列表。以下操作 无效CREATE TABLE m1 ... ENGINE=MRG_MYISAM ...; LOCK TABLES t1 WRITE, t2 WRITE, m1 WRITE; ALTER TABLE m1 ... UNION=(t1,t2) ...;
但是,您可以对临时
MERGE
表执行此操作。您无法使用
CREATE ... SELECT
创建MERGE
表,无论是作为临时MERGE
表,还是作为非临时MERGE
表。例如CREATE TABLE m1 ... ENGINE=MRG_MYISAM ... SELECT ...;
尝试执行此操作会导致错误:
tbl_name
不是BASE TABLE
。在某些情况下,如果底层表包含
CHAR
或BINARY
列,则MERGE
表和底层表之间不同的PACK_KEYS
表选项值会导致意外结果。作为解决方法,使用ALTER TABLE
确保所有涉及的表具有相同的PACK_KEYS
值。(错误 #50646)