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