MySQL 使用基于语句的日志记录(SBL)、基于行的日志记录(RBL)或混合格式日志记录。二进制日志的类型对日志记录的大小和效率产生影响。因此,在复制中选择基于行的复制(RBR)或基于语句的复制(SBR)取决于您的应用程序和环境。本节描述了使用基于行格式日志时的已知问题,并描述了一些最佳实践。
有关更多信息,请参阅 第 19.2.1 节,“复制格式” 和 第 19.2.1.1 节,“基于语句和基于行的复制的优缺点”。
有关 NDB 集群复制(依赖基于行的复制)的特定问题,请参阅 第 25.7.3 节,“NDB 集群复制中的已知问题”。
-
临时表的基于行日志记录。 如 第 19.5.1.31 节,“复制和临时表” 所述,临时表在使用基于行或混合格式时不会被复制。有关更多信息,请参阅 第 19.2.1.1 节,“基于语句和基于行的复制的优缺点”。
临时表在使用基于行或混合格式时不会被复制,因为没有必要。此外,因为临时表只能从创建它们的线程中读取,因此即使使用基于语句的格式,也很少有益于复制它们。
您可以在运行时从基于语句到基于行的二进制日志格式切换,即使临时表已经创建了,但是您不能在运行时从基于行或混合格式切换到基于语句的格式,因为之前模式下的任何
CREATE TEMPORARY TABLE
语句都将从二进制日志中省略。MySQL 服务器跟踪每个临时表创建时的日志记录模式。当客户端会话结束时,服务器将记录一个
DROP TEMPORARY TABLE IF EXISTS
语句,以删除所有仍然存在的临时表,如果临时表是在基于语句的二进制日志记录模式下创建的,则不会记录DROP TEMPORARY TABLE IF EXISTS
语句。非事务性 DML 语句涉及临时表时,允许使用
binlog_format=ROW
,只要非事务性表受到影响的语句都是临时表。 -
RBL 和非事务性表的同步。 当许多行受到影响时,变化的集合将被分割成多个事件;当语句提交时,所有这些事件都将被写入二进制日志。在副本上执行时,将对所有涉及的表加锁,然后批量应用行。
-
延迟和二进制日志大小。 RBL 将每行的变化写入二进制日志,因此日志的大小可能会快速增加。这可能会显著增加副本上匹配源的更改所需的时间。您应该在应用程序中注意这种延迟的可能性。
-
读取二进制日志。 mysqlbinlog 使用
BINLOG
语句显示基于行的事件在二进制日志中的显示方式为 base 64 编码的字符串,该字符串的含义不明显。当使用--base64-output=DECODE-ROWS
和--verbose
选项时,mysqlbinlog 将二进制日志的内容格式化为人类可读的形式。当基于行格式的二进制日志事件被写入时,您可以使用该命令来读取或恢复复制或数据库故障时的二进制日志。有关更多信息,请参阅 第 6.6.9.2 节,“mysqlbinlog 行事件显示”。 -
二进制日志执行错误和副本执行模式。 使用
replica_exec_mode=IDEMPOTENT
通常仅在 MySQL NDB 集群复制中有用,为该模式的默认值。(见 第 25.7.10 节,“NDB 集群复制:双向和环形复制”)。当replica_exec_mode
为IDEMPOTENT
时,因无法找到原始行而无法应用 RBL 更改的失败不会触发错误或导致复制失败。这意味着可能不会在副本上应用更新,从而导致源和副本不同步。延迟问题和使用非事务表时 RBR 的replica_exec_mode
为IDEMPOTENT
可能会导致源和副本进一步分歧。有关replica_exec_mode
的更多信息,请参阅 第 7.1.8 节,“服务器系统变量”。对于其他场景,设置
replica_exec_mode
为STRICT
通常足够;这是除了NDB
之外的存储引擎的默认值。 -
不支持基于服务器 ID 的过滤。 您可以使用
IGNORE_SERVER_IDS
选项来过滤基于服务器 ID 的CHANGE REPLICATION SOURCE TO
。该选项适用于基于语句和基于行的日志记录格式,但不能与gtid_mode=ON
一起使用。另一种方法是使用WHERE
子句,包括关系@@server_id <>
子句与id_value
UPDATE
和DELETE
语句一起使用。例如,WHERE @@server_id <> 1
。然而,这不适用于基于行的日志记录。 -
RBL、非事务表和停止副本。 使用基于行的日志记录时,如果副本服务器在更新非事务表时停止,而副本线程正在更新非事务表,则副本数据库可能会达到不一致的状态。因此,建议使用事务存储引擎,如
InnoDB
,用于所有使用基于行格式的复制表。使用STOP REPLICA
或STOP REPLICA SQL_THREAD
在关闭副本 MySQL 服务器之前,可以防止问题的发生,并且无论使用何种日志记录格式或存储引擎,都建议这样做。