当复制源服务器关闭并重新启动时,其MEMORY
表变得为空。为了将此效果复制到副本中,源服务器在启动后第一次使用给定的MEMORY
表时,会记录一个事件,通知副本必须清空该表,通过将DELETE
或TRUNCATE TABLE
语句写入二进制日志中。该生成的事件可以通过二进制日志中的注释来识别,如果服务器使用GTID,该事件将分配一个GTID。该语句总是以语句格式记录,即使二进制日志格式设置为ROW
,并且即使服务器设置了read_only
或super_read_only
模式。注意,在源服务器重新启动和第一次使用表之间的间隔期间,副本仍然具有MEMORY
表中的过时数据。为了避免这种间隔,当直接查询副本可能返回过时数据时,可以将init_file
系统变量设置为包含语句的文件,以便在源服务器启动时填充MEMORY表。
当副本服务器关闭并重新启动时,其MEMORY
表变得为空。这将导致副本与源服务器不同步,并可能导致其他故障或导致副本停止:
-
从源服务器接收的行格式更新和删除可能会失败,错误信息为
Can't find record in '
。memory_table
' -
诸如
INSERT INTO ... SELECT FROM
的语句可能会在源服务器和副本上插入不同的行集。memory_table
副本还将DELETE
或TRUNCATE TABLE
语句写入其自己的二进制日志,然后传递给下游副本,导致它们清空自己的MEMORY
表。
安全地重新启动副本的方法是首先在源服务器上删除或删除MEMORY
表中的所有行,然后等待这些更改复制到副本上。然后,可以安全地重新启动副本。
在某些情况下,可能适用替代的重新启动方法。当binlog_format=ROW
时,可以通过设置replica_exec_mode=IDEMPOTENT
在重新启动副本之前,防止副本停止。这允许副本继续复制,但其MEMORY
表仍然与源服务器不同。这是可接受的,如果应用逻辑使得MEMORY
表的内容可以安全地丢失(例如,如果MEMORY
表用于缓存)。replica_exec_mode=IDEMPOTENT
对所有表都生效,因此可能会隐藏其他复制错误在非MEMORY
表中的错误。
(上述方法不适用于NDB Cluster,其中replica_exec_mode
总是IDEMPOTENT
,且无法更改。)
内存表的大小受限于MEMORY
系统变量max_heap_table_size
的值,该变量不被复制(见第19.5.1.39节,“复制和变量”)。对max_heap_table_size的更改将对使用ALTER TABLE ... ENGINE = MEMORY
或TRUNCATE TABLE
创建或更新的MEMORY表生效,或者在服务器重新启动后对所有MEMORY
表生效。如果您在源服务器上增加该变量的值,而不在副本服务器上这样做,那么源服务器上的表可能会增长得比副本服务器上的表大,从而导致插入操作在源服务器上成功,但在副本服务器上失败,出现“表已满”错误。这是一个已知的问题(Bug #48666)。在这种情况下,您必须在副本服务器上设置全局变量max_heap_table_size
的值,然后重新启动复制。同时,我们建议您重新启动源服务器和副本服务器的MySQL服务器,以确保新值在每个服务器上生效。
请参阅第18.3节,“MEMORY存储引擎”,以获取更多关于MEMORY
表的信息。