每种二进制日志记录格式都有优缺点。对于大多数用户来说,混合复制格式应提供数据完整性和性能的最佳组合。但是,如果您想在执行某些任务时利用语句式或基于行的复制格式的特定功能,您可以使用本节中的信息,其中总结了它们的相对优缺点,以确定哪种最适合您的需求。
语句式复制的优点
久经考验的技术。
写入日志文件的數據量更少。当更新或删除影响许多行时,这会导致 大量 减少日志文件所需的存储空间。这也意味着进行备份和从备份中恢复可以更快地完成。
日志文件包含所有进行了更改的语句,因此它们可用于审计数据库。
语句式复制的缺点
对 SBR 不安全的语句。 不是所有修改数据的语句(例如
INSERT
DELETE
、UPDATE
和REPLACE
语句)都可以使用语句式复制进行复制。使用语句式复制时,任何非确定性行为都很难复制。此类数据修改语言 (DML) 语句的示例包括以下内容依赖于非确定性可加载函数或存储程序的语句,因为此类函数或存储程序返回的值或依赖于除提供给它的参数之外的因素。(但是,基于行的复制只是复制函数或存储程序返回的值,因此它对表行和数据的影响在源和副本上都是相同的。)有关更多信息,请参见 第 19.5.1.16 节“被调用功能的复制”。
DELETE
和UPDATE
语句使用LIMIT
子句,但没有使用ORDER BY
子句,是不可确定的。请参见 第 19.5.1.18 节“复制和 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.29 节“复制期间的副本错误”。
存储函数以与调用语句相同的
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
选项时向 mysqlbinlog 输出添加一个包含语句的Rows_query
事件。对于使用
MyISAM
存储引擎的表,在将INSERT
语句作为基于行的事件应用到二进制日志时,副本上需要比将它们作为语句应用时更强的锁。这意味着使用基于行复制时,不支持MyISAM
表上的并发插入。