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
语句。当使用
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
等事务存储引擎。使用STOP REPLICA
或STOP REPLICA SQL_THREAD
在关闭副本 MySQL 服务器之前有助于防止出现问题,并且始终建议这样做,无论您使用何种日志记录格式或存储引擎。