每种二进制日志格式都有其优缺点。对于大多数用户,混合复制格式应该提供最佳的数据完整性和性能。如果您想在执行某些任务时利用基于语句或基于行的复制格式的特定功能,可以使用本节中的信息,该信息提供了它们的相对优缺点的总结,以确定哪种格式最适合您的需求。
基于语句的复制的优点
-
成熟的技术。
-
写入日志文件的数据较少。当更新或删除影响许多行时,这将导致日志文件所需的存储空间大大减少。这也意味着可以更快地创建和恢复备份。
-
日志文件包含所有更改数据库的语句,因此可以用于审核数据库。
基于语句的复制的缺点
-
不适合 SBR 的语句 并不是所有修改数据的语句(例如
INSERT
DELETE
,UPDATE
和REPLACE
语句)可以使用基于语句的复制。任何非确定性行为都难以使用基于语句的复制。例如:-
依赖于可加载函数或存储程序的语句,该函数或存储程序的值取决于参数以外的因素。(基于行的复制则简单地复制函数或存储程序的返回值,因此其对表行和数据的影响在源和副本上相同。)见 第 19.5.1.16 节,“复制调用的功能”,以获取更多信息。
-
DELETE
和UPDATE
语句使用LIMIT
子句但没有ORDER BY
子句是非确定性的。见 第 19.5.1.18 节,“复制和 LIMIT”。 -
锁定读取语句(
SELECT ... FOR UPDATE
和SELECT ... FOR SHARE
) 使用NOWAIT
或SKIP LOCKED
选项。见 锁定读取并发性 NOWAIT 和 SKIP LOCKED。 -
确定性加载函数必须在副本上应用。
-
使用以下函数的语句不能使用基于语句的复制:
然而,所有其他函数都可以使用基于语句的复制正确地复制,包括
NOW()
等。有关更多信息,请参阅 第 19.5.1.14 节,“复制和系统函数”。
无法使用基于语句的复制正确地复制的语句将被记录一个警告,如下所示:
[Warning] Statement is not safe to log in statement format.
客户端也将收到类似的警告,可以使用
SHOW WARNINGS
显示。 -
-
INSERT ... SELECT
需要比基于行的复制更多的行级锁。 -
UPDATE
语句需要表扫描(因为 WHERE 子句中没有使用索引)必须锁定比基于行的复制更多的行。 -
对于复杂的语句,副本必须在更新或插入行之前评估和执行语句。使用基于行的复制,副本只需要修改受影响的行,而不是执行完整的语句。
-
如果副本在评估时出现错误,特别是在执行复杂语句时,基于语句的复制可能会随着时间的推移逐渐增加错误的幅度。请参阅 第 19.5.1.29 节,“副本复制期间的错误”。
-
存储函数使用与调用语句相同的
NOW()
值。但是,这不适用于存储过程。 -
确定性可加载函数必须在副本上应用。
-
表定义必须在源和副本上几乎相同。请参阅 第 19.5.1.9 节,“源和副本上的表定义不同”,以获取更多信息。
-
DML 操作从 MySQL 授权表(通过连接列表或子查询)读取数据但不修改它们,将作为非锁定读取 MySQL 授权表执行,因此不适合基于语句的复制。有关更多信息,请参阅 授权表并发。
基于行的复制的优点
-
所有更改都可以被复制。这是最安全的复制形式。
Note更新 MySQL 系统架构信息的语句,例如
GRANT
、REVOKE
和触发器、存储过程(包括存储过程)和视图的操作,都将使用基于语句的复制复制到副本。对于诸如
CREATE TABLE ... SELECT
的语句,一个CREATE
语句从表定义生成,并使用基于语句的格式复制,而行插入使用基于行的格式复制。 -
对于以下类型的语句,源上需要的行锁较少,从而实现了更高的并发性:
-
INSERT
语句带有AUTO_INCREMENT
基于行的复制的缺点
-
RBR 可能生成更多需要记录的数据。要复制 DML 语句(例如
UPDATE
或DELETE
语句),基于语句的复制仅将语句写入二进制日志。相比之下,基于行的复制将每个更改的行写入二进制日志。如果语句更改了许多行,基于行的复制可能写入大量数据到二进制日志,即使语句被回滚。这也意味着制作和恢复备份需要更多时间。此外,二进制日志被锁定更长时间以写入数据,这可能会导致并发问题。使用binlog_row_image=minimal
可以大大减少这个缺点。 -
确定性可加载函数生成大量
BLOB
值时,使用基于行的复制比使用基于语句的复制需要更长时间。这是因为BLOB
列值被记录,而不是生成数据的语句。 -
您无法在副本上看到从源接收和执行的语句。但是,您可以使用 mysqlbinlog 选项
--base64-output=DECODE-ROWS
和--verbose
查看更改的数据。或者,使用
binlog_rows_query_log_events
变量,如果启用它将添加一个Rows_query
事件到 mysqlbinlog 输出中,当使用-vv
选项时。 -
对于使用
MyISAM
存储引擎的表,在副本上应用基于行的事件到二进制日志时,需要比应用语句时更强的锁定。这意味着在使用基于行的复制时,不支持MyISAM
表上的并发插入。