每个二进制日志记录格式都有优缺点。对于大多数用户来说,混合复制格式应该提供数据完整性和性能的最佳组合。但是,如果你想在执行某些任务时利用语句式或行式复制格式的特定功能,你可以使用本节中的信息,其中总结了它们的相对优缺点,以确定哪种格式最适合你的需求。
语句式复制的优点
成熟的技术。
写入日志文件的数据更少。当更新或删除影响许多行时,这会导致 大大 减少日志文件所需的存储空间。这也意味着备份和还原操作可以更快地完成。
日志文件包含所有进行了任何更改的语句,因此它们可以用于审计数据库。
语句式复制的缺点
对 SBR 不安全的语句。 并非所有修改数据的语句(例如
INSERT
DELETE
、UPDATE
和REPLACE
语句)都可以使用语句式复制进行复制。任何非确定性行为在使用语句式复制时都很难复制。此类数据修改语言 (DML) 语句的示例包括以下内容依赖于非确定性可加载函数或存储程序的语句,因为此类函数或存储程序返回的值或依赖于其提供的参数以外的其他因素。(但是,行式复制只是复制函数或存储程序返回的值,因此它对表行和数据的影响在源和副本上是相同的。)有关更多信息,请参阅 第 19.5.1.16 节,“已调用功能的复制”。
DELETE
和UPDATE
语句在没有ORDER BY
的情况下使用LIMIT
子句是非确定性的。请参阅 第 19.5.1.19 节,“复制和 LIMIT”。使用
NOWAIT
或SKIP LOCKED
选项的锁定读取语句(SELECT ... FOR UPDATE
和SELECT ... FOR SHARE
)。请参阅 使用 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.30 节“复制过程中副本错误”。
存储函数使用与调用语句相同的
NOW()
值执行。但是,这并不适用于存储过程。必须在副本上应用确定性可加载函数。
源服务器和副本服务器上的表定义必须(几乎)相同。有关更多信息,请参见第 19.5.1.9 节“源服务器和副本服务器上表定义不同的复制”。
从 MySQL 授权表(通过联接列表或子查询)读取数据但未修改数据的 DML 操作以非锁定读取的方式在 MySQL 授权表上执行,因此对于基于语句的复制来说是不安全的。有关更多信息,请参见授权表并发。
基于行的复制的优点
所有更改都可以复制。这是最安全的复制形式。
注意更新
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
变量,如果启用,则在使用-vv
选项时,将包含语句的Rows_query
事件添加到mysqlbinlog 输出。对于使用
MyISAM
存储引擎的表,在将INSERT
语句作为基于行的事件应用到二进制日志时,副本上需要比将它们作为语句应用时更强的锁。这意味着在使用基于行的复制时,不支持对MyISAM
表进行并发插入。