16.4.1.20 复制和 MEMORYtable

当复制源服务器关闭并重新启动时,其MEMORYtable 将为空。为了将此效果复制到副本中,源在启动后首次使用给定的MEMORYtable 时,会记录一个事件,该事件通知副本必须为此写DELETE或(从 MySQL 5.7.32 起)TRUNCATE TABLE语句来清空该 table。table 到二进制日志。可以通过二进制日志中的 Comments 来识别此生成的事件,如果服务器上正在使用 GTID,则会为其分配 GTID。即使二进制日志记录格式设置为ROW,该语句也始终以语句格式记录,即使在服务器上设置了read_onlysuper_read_only模式,该语句也将被写入。请注意,在源重新启动和首次使用 table 之间的时间间隔内,副本在MEMORYtable 中仍具有过时的数据。为了避免在直接查询副本可能返回陈旧数据时出现此间隔,可以设置init_file系统变量来命名一个文件,该文件包含在启动时填充源MEMORYtable 的语句。

当副本服务器关闭并重新启动时,其MEMORYtable 将为空。这会导致副本与源不同步,并可能导致其他故障或导致副本停止:

  • 从源接收到的行格式更新和删除可能会失败,并显示Can't find record in 'memory_table'

  • 诸如插入...从 memory_table 中选择之类的语句可能在源和副本上插入一组不同的行。

副本还向自己的二进制日志中写入DELETE或(从 MySQL 5.7.32 起)TRUNCATE TABLE语句,该语句将传递给任何下游副本,从而使它们清空自己的MEMORYtable。

重新启动正在复制MEMORYtable 的副本的安全方法是首先从源上的MEMORYtable 中删除或删除所有行,然后 await,直到这些更改已复制到副本。然后可以安全地重新启动副本。

在某些情况下,可以使用其他重新启动方法。在binlog_format=ROW时,如果在再次启动副本之前设置了slave_exec_mode=IDEMPOTENT,则可以防止副本停止。这允许副本 continue 复制,但是其MEMORYtable 仍将与源 table 中的 table 不同。如果应用程序逻辑可以安全地丢失MEMORYtable 的内容(例如,如果MEMORYtable 用于缓存),则可以这样做。 slave_exec_mode=IDEMPOTENT全局应用于所有 table,因此它可能会在非MEMORYtable 中隐藏其他复制错误。

(刚刚描述的方法不适用于slave_exec_mode始终为IDEMPOTENT且不能更改的 NDB Cluster。)

MEMORYtable 的大小受max_heap_table_size系统变量的值限制,该值不能复制(请参见第 16.4.1.37 节,“复制和变量”)。 max_heap_table_size的更改对使用更改后使用ALTER TABLE ...引擎=内存TRUNCATE TABLE创建或更新的MEMORYtable 生效,或在服务器重新启动后对所有MEMORYtable 生效。如果您在源副本上不执行此操作而在源文件上增加此变量的值,则源文件上的 table 可能变得大于副本服务器上的对应 table,从而导致插入在源文件上成功但在副本服务器上失败与 table 完全错误。这是一个已知的问题(错误#48666)。在这种情况下,必须在副本以及源上都设置max_heap_table_size的全局值,然后重新启动复制。还建议您重新启动源 MySQL 服务器和副本 MySQL 服务器,以确保新值对它们中的每个服务器具有完全的(全局)作用。

有关MEMORY个 table 的更多信息,请参见第 15.3 节“ MEMORY 存储引擎”