MySQL 使用基于语句的日志记录 (SBL)、基于行的日志记录 (RBL) 或混合格式日志记录。使用的二进制日志类型会影响日志记录的大小和效率。因此,选择基于行的复制 (RBR) 还是基于语句的复制 (SBR) 取决于您的应用程序和环境。本节描述了使用基于行的格式日志时的已知问题,并描述了在复制中使用它的一些最佳实践。
有关其他信息,请参阅 第 17.2.1 节,“复制格式”和 第 17.2.1.1 节,“基于语句和基于行的复制的优点和缺点”。
有关特定于 NDB Cluster 复制(取决于基于行的复制)的问题的信息,请参阅 第 23.7.3 节,“NDB Cluster 复制中的已知问题”。
临时表的基于行的日志记录。 如 第 17.5.1.31 节“复制和临时表”所述,使用基于行的格式或(从 MySQL 8.0.4 开始)混合格式时不会复制临时表。有关详细信息,请参阅第 17.2.1.1 节,“基于语句和基于行的复制的优点和缺点”。
使用基于行或混合格式时不会复制临时表,因为没有必要。此外,因为临时表只能从创建它们的线程读取,所以即使使用基于语句的格式,复制它们也几乎没有任何好处。
即使创建了临时表,您也可以在运行时从基于语句的二进制日志记录格式切换到基于行的二进制日志记录格式。
CREATE TEMPORARY TABLE
但是,在 MySQL 8.0 中,由于在以前的模式下二进制日志中省略了 任何语句,因此您无法在运行时从基于行或混合格式的二进制日志记录切换为基于语句的格式 。MySQL 服务器跟踪创建每个临时表时生效的日志记录模式。当给定的客户端会话结束时,服务器会
DROP TEMPORARY TABLE IF EXISTS
为每个仍然存在的临时表记录一条语句,这些临时表是在使用基于语句的二进制日志记录时创建的。如果在创建表时使用了基于行或混合格式的二进制日志记录,DROP TEMPORARY TABLE IF EXISTS
则不会记录该语句。在 MySQL 8.0.4 和 5.7.25 之前的版本中,DROP TEMPORARY TABLE IF EXISTS
不管有效的日志记录模式如何,都会记录该语句。使用 时允许涉及临时表的非事务性 DML 语句
binlog_format=ROW
,只要受语句影响的任何非事务性表都是临时表(缺陷 #14272672)。RBL 和非事务表的同步。 当许多行受到影响时,更改集会分成几个事件;当语句提交时,所有这些事件都被写入二进制日志。在副本上执行时,会对所有涉及的表进行表锁定,然后以批处理模式应用行。根据用于副本的表副本的引擎,这可能有效也可能无效。
延迟和二进制日志大小。 RBL 将每一行的更改写入二进制日志,因此它的大小会迅速增加。这会显着增加对副本进行更改以匹配源上的更改所需的时间。您应该意识到您的应用程序可能会出现这种延迟。
读取二进制日志。 mysqlbinlog
BINLOG
使用 语句在二进制日志中显示基于行的事件(请参阅第 13.7.8.1 节,“BINLOG 语句”)。此语句将事件显示为基本 64 位编码的字符串,其含义不明显。当使用--base64-output=DECODE-ROWS
and--verbose
选项调用时, mysqlbinlog将二进制日志的内容格式化为人类可读。当二进制日志事件以基于行的格式写入并且您想从复制或数据库故障中读取或恢复时,您可以使用此命令读取二进制日志的内容。有关详细信息,请参阅第 4.6.9.2 节,“mysqlbinlog 行事件显示”。二进制日志执行错误和副本执行模式。 Using
slave_exec_mode=IDEMPOTENT
通常仅对 MySQL NDB Cluster 复制有用,这IDEMPOTENT
是默认值。(参见 第 23.7.10 节,“NDB 集群复制:双向和循环复制”)。当系统 变量replica_exec_mode
或是slave_exec_mode
IDEMPOTENT
,由于找不到原始行而无法应用 RBL 的更改不会触发错误或导致复制失败。这意味着可能没有在副本上应用更新,因此源和副本不再同步。延迟问题以及在 RBR中 使用非事务性表replica_exec_mode
可能 会导致源和副本进一步分离。有关 和的更多信息,请参阅 第 5.1.8 节,“服务器系统变量”。slave_exec_mode
IDEMPOTENT
replica_exec_mode
slave_exec_mode
对于其他场景,设置
replica_exec_mode
或slave_exec_mode
到STRICT
通常就足够了;这是除 . 以外的存储引擎的默认值NDB
。不支持基于服务器 ID 的过滤。 您可以使用语句(来自 MySQL 8.0.23)或 语句(MySQL 8.0.23 之前)的
IGNORE_SERVER_IDS
选项 基于服务器 ID 进行过滤 。此选项适用于基于语句和基于行的日志记录格式,但在 设置时不推荐使用。过滤掉某些副本上的更改的另一种方法是使用包含关系子句 with and 语句的子句。例如,CHANGE REPLICATION SOURCE TO
CHANGE MASTER TO
GTID_MODE=ON
WHERE
@@server_id <>
id_value
UPDATE
DELETE
WHERE @@server_id <> 1
. 但是,这不适用于基于行的日志记录。要使用server_id
系统变量进行语句过滤,请使用基于语句的日志记录。RBL、非事务表和停止的副本。 使用基于行的日志记录时,如果在副本线程更新非事务表时副本服务器停止,则副本数据库可能会达到不一致状态。出于这个原因,建议您使用事务存储引擎,例如
InnoDB
对使用基于行的格式复制的所有表。在关闭副本 MySQL 服务器之前 使用STOP REPLICA
或 (或在 MySQL 8.0.22 之前,使用 SLAVE 而不是 REPLICA)有助于防止问题的发生,无论您使用何种日志记录格式或存储引擎,始终建议这样做。STOP REPLICA SQL_THREAD