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