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