16.2.1.1 基于语句的复制和基于行的复制的优缺点

每种二进制日志记录格式都有优点和缺点。对于大多数用户,混合复制格式应提供数据完整性和性能的最佳组合。但是,如果要在执行某些任务时利用特定于基于语句的复制格式或基于行的复制格式的功能,则可以使用本节中的信息,该信息概述了它们的相对优缺点,确定最适合您的需求。

基于语句的复制的优点

  • Proven technology.

  • 写入日志文件的数据更少。当更新或删除影响许多行时,这将导致日志文件所需的存储空间减少*少得多。这也意味着从备份中获取和还原可以更快地完成。

  • 日志文件包含所有进行了任何更改的语句,因此它们可用于审核数据库。

基于语句的复制的缺点

但是,所有其他功能都可以使用基于语句的复制正确地复制,包括NOW()等。

有关更多信息,请参见第 16.4.1.15 节,“复制和系统功能”

使用基于语句的复制无法正确复制的语句会记录一条警告,如下所示:

[Warning] Statement is not safe to log in statement format.

在这种情况下,也会向 Client 发出类似的警告。Client 端可以使用SHOW WARNINGS显示它。

  • 插入...选择比基于行的复制需要更多的行级锁。

  • 与基于行的复制相比,需要进行 table 扫描的UPDATE语句(因为WHERE子句中未使用索引)必须锁定更多的行。

  • 对于InnoDB:使用AUTO_INCREMENTINSERT语句将阻止其他不冲突的INSERT语句。

  • 对于复杂的语句,在更新或插入行之前,必须在副本上评估并执行该语句。对于基于行的复制,副本仅需修改受影响的行,而无需执行完整语句。

  • 如果对副本的评估存在错误,尤其是在执行复杂的语句时,基于语句的复制可能会随着时间的流逝缓慢地增加受影响行上的错误余量。参见第 16.4.1.27 节“复制过程中的复制错误”

  • 存储的函数以与调用语句相同的NOW()值执行。但是,存储过程不是这样。

  • 确定性 UDF 必须应用于副本。

  • table 定义在源和副本上必须(几乎)相同。有关更多信息,请参见第 16.4.1.10 节,“在源和副本上使用不同的 table 定义进行复制”

基于行的复制的优点

  • 可以复制所有更改。这是最安全的复制形式。

Note

更新mysql系统数据库中信息的语句(例如GRANTREVOKE以及触发器,存储例程(包括存储过程)和视图的操纵)都使用基于语句的复制复制到副本。

对于诸如创建 table...选择的语句,将从 table 定义中生成CREATE语句,并使用基于语句的格式复制,而使用基于行的格式复制行插入。

  • 对于以下类型的语句,源上需要较少的行锁,从而实现更高的并发性:

  • 插入...选择

    • INSERTAUTO_INCREMENT的 Statements

    • 带有WHERE子句的UPDATEDELETE语句不使用键或不更改大多数检查的行。

  • 对于任何INSERTUPDATEDELETE语句,副本上所需的行锁都更少。

基于行的复制的缺点

  • RBR 可以生成更多必须记录的数据。要复制 DML 语句(例如UPDATEDELETE语句),基于语句的复制仅将语句写入二进制日志。相比之下,基于行的复制会将每个更改的行写入二进制日志。如果该语句更改许多行,则基于行的复制可能会向二进制日志中写入大量数据;即使对于回滚的语句也是如此。这也意味着制作和还原备份可能需要更多时间。此外,二进制日志被锁定更长的时间以写入数据,这可能会导致并发问题。使用binlog_row_image=minimal可以大大减少不利之处。

  • 生成大BLOB值的确定性 UDF 与基于语句的复制相比,使用基于行的复制所花费的时间更长。这是因为记录了BLOB列的值,而不是记录生成数据的语句。

  • 您无法在副本上看到从源接收并执行了哪些语句。但是,您可以看到使用mysqlbinlog--base64-output=DECODE-ROWS--verbose选项更改了哪些数据。

或者,使用binlog_rows_query_log_events变量,如果启用了-vv选项,则启用该变量会向_输出添加带有该语句的Rows_query事件。

  • 对于使用MyISAM存储引擎的 table,将INSERT语句作为基于行的事件应用于二进制日志时,与副本中的语句相比,在副本上需要更强的锁定。这意味着在使用基于行的复制时,不支持在MyISAMtable 上并发插入。