当复制源服务器关闭并重新启动时,其 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
表的副本的安全方法是,首先删除或删除源上所有 MEMORY
表中的所有行,并等待这些更改复制到副本。然后,可以安全地重新启动副本。
在某些情况下,可能可以使用替代的重启方法。当 binlog_format=ROW
时,您可以在再次启动副本之前设置 replica_exec_mode=IDEMPOTENT
来防止副本停止。这允许副本继续复制,但其 MEMORY
表仍然与源上的表不同。如果应用程序逻辑允许安全丢失 MEMORY
表的内容(例如,如果 MEMORY
表用于缓存),则这是可以接受的。 replica_exec_mode=IDEMPOTENT
全局应用于所有表,因此它可能会隐藏非 MEMORY
表中的其他复制错误。
(上述方法不适用于 NDB Cluster,在 NDB Cluster 中,replica_exec_mode
始终为 IDEMPOTENT
,并且无法更改。)
MEMORY
表的大小受 max_heap_table_size
系统变量的值限制,该值不会被复制(请参阅 第 19.5.1.40 节,“复制和变量”)。max_heap_table_size
的更改对使用 ALTER TABLE ... ENGINE = MEMORY
或 TRUNCATE TABLE
创建或更新的 MEMORY
表生效,或者在服务器重启后对所有 MEMORY
表生效。如果您在源上增加此变量的值,而在副本上没有这样做,则源上的表可能会比副本上的表增长得更大,导致在源上成功插入但在副本上失败,并出现 Table is full 错误。这是一个已知问题(错误 #48666)。在这种情况下,您必须在副本上以及源上设置 max_heap_table_size
的全局值,然后重启复制。还建议您重启源和副本 MySQL 服务器,以确保新值对它们中的每一个都产生完全(全局)影响。
有关 MEMORY
表的更多信息,请参阅 第 18.3 节,“MEMORY 存储引擎”。