当复制源服务器关闭并重新启动时,其 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.39 节,“复制和变量”)。max_heap_table_size
的更改将对使用 ALTER TABLE ... ENGINE = MEMORY
或 TRUNCATE TABLE
创建或更新的 MEMORY
表生效,或对服务器重启后所有 MEMORY
表生效。如果在源服务器上增加此变量的值,而不在副本服务器上增加,则源服务器上的表可能会比副本服务器上的表更大,从而导致在源服务器上成功插入但在副本服务器上失败,并出现 Table is full 错误。这是一个已知问题(Bug #48666)。在这种情况下,必须在副本服务器上以及源服务器上设置 max_heap_table_size
的全局值,然后重启复制。还建议重新启动源服务器和副本服务器,以确保新值在每个服务器上完全(全局)生效。
有关 MEMORY
表的更多信息,请参见 第 18.3 节,“MEMORY 存储引擎”。