Documentation Home

5.4.4.2 设置二进制日志格式

您可以通过使用 启动 MySQL 服务器来显式选择二进制日志记录格式 。支持的值为: --binlog-format=typetype

  • STATEMENT导致日志记录是基于语句的。

  • ROW导致日志记录基于行。这是默认值。

  • MIXED导致日志记录使用混合格式。

设置二进制日志记录格式不会激活服务器的二进制日志记录。该设置仅在服务器上启用二进制日志记录时生效,即log_bin系统变量设置为时的情况ON。从 MySQL 8.0 开始,二进制日志记录默认启用,只有在启动时指定 --skip-log-bin--disable-log-bin 选项时才会禁用。

日志记录格式也可以在运行时切换,但请注意,在许多情况下您不能这样做,如本节后面所述。设置系统变量的全局值binlog_format 以指定更改后连接的客户端的格式:

mysql> SET GLOBAL binlog_format = 'STATEMENT';
mysql> SET GLOBAL binlog_format = 'ROW';
mysql> SET GLOBAL binlog_format = 'MIXED';

单个客户端可以通过设置以下会话值来控制其自己语句的日志记录格式 binlog_format

mysql> SET SESSION binlog_format = 'STATEMENT';
mysql> SET SESSION binlog_format = 'ROW';
mysql> SET SESSION binlog_format = 'MIXED';

更改全局 binlog_format值需要足够的权限来设置全局系统变量。更改会话binlog_format值需要足够的权限来设置受限会话系统变量。请参阅第 5.1.9.1 节,“系统变量权限”

客户端可能希望在每个会话的基础上设置二进制日志记录的原因有多种:

  • 对数据库进行许多小更改的会话可能需要使用基于行的日志记录。

  • 执行与子句中的许多行匹配的更新的会话 WHERE可能希望使用基于语句的日志记录,因为记录少量语句比记录许多行更有效。

  • 有些语句在源上需要大量执行时间,但只会修改几行。因此,使用基于行的日志记录来复制它们可能是有益的。

当您无法在运行时切换复制格式时会有例外情况:

  • 不能从存储函数或触发器中更改复制格式。

  • 如果NDB启用了存储引擎。

  • 如果会话有打开的临时表,则不能更改会话的复制格式 ( SET @@SESSION.binlog_format)。

  • 如果任何复制通道有打开的临时表,则不能全局更改复制格式(SET @@GLOBAL.binlog_formatSET @@PERSIST.binlog_format)。

  • 如果任何复制通道应用程序线程当前正在运行,则无法全局更改复制格式(SET @@GLOBAL.binlog_formatSET @@PERSIST.binlog_format)。

在任何这些情况下尝试切换复制格式(或尝试设置当前复制格式)都会导致错误。但是,您可以随时使用PERSIST_ONLY ( SET @@PERSIST_ONLY.binlog_format) 更改复制格式,因为此操作不会修改运行时全局系统变量值,并且仅在服务器重启后生效。

当存在任何临时表时,不建议在运行时切换复制格式,因为只有在使用基于语句的复制时才会记录临时表,而使用基于行的复制和混合复制时,它们不会被记录。

在复制过程中切换复制格式也会导致问题。每个 MySQL 服务器都可以设置自己的二进制日志记录格式(无论 binlog_format设置为全局范围还是会话范围,都为真)。这意味着更改复制源服务器上的日志记录格式不会导致副本更改其日志记录格式以匹配。使用 STATEMENT模式时, binlog_format不会复制系统变量。当使用MIXEDROW记录模式时,它被复制但被副本忽略。

副本无法将以 ROW日志记录格式 接收的二进制日志条目STATEMENT转换为在其自己的二进制日志中使用的格式。因此,副本必须使用ROWMIXED格式化(如果源这样做的话)。将源上的二进制日志记录格式从更改 STATEMENTROWMIXED在复制正在进行时更改为具有STATEMENT格式的副本可能会导致复制失败并出现错误,例如错误执行行事件:'无法执行语句:不可能写入二进制日志,因为语句在行中格式和 BINLOG_FORMAT = STATEMENT。将副本上的二进制日志记录格式更改为STATEMENT 当源仍在使用时格式化MIXEDROW格式化也会导致相同类型的复制失败。要安全地更改格式,您必须停止复制并确保对源和副本进行相同的更改。

如果您正在使用InnoDB表并且事务隔离级别为READ COMMITTEDREAD UNCOMMITTED,则只能使用基于行的日志记录。可以 将日志记录格式更改为 ,但在运行时这样做会很快导致错误,因为无法再执行插入。 STATEMENTInnoDB

将二进制日志格式设置为ROW,许多更改将使用基于行的格式写入二进制日志。但是,一些更改仍然使用基于语句的格式。示例包括所有 DDL(数据定义语言)语句,例如CREATE TABLEALTER TABLEDROP TABLE

使用基于行的二进制日志记录时, binlog_row_event_max_size 系统变量及其相应的启动选项 --binlog-row-event-max-size对行事件的最大大小设置软限制。默认值为 8192 字节,该值只能在服务器启动时更改。在可能的情况下,存储在二进制日志中的行被分组为大小不超过此设置值的事件。如果无法拆分事件,则可能会超过最大大小。

--binlog-row-event-max-size 选项适用于能够进行基于行的复制的服务器。行以不超过此选项值的字节大小的块存储到二进制日志中。该值必须是 256 的倍数。默认值为 8192。

警告

当使用基于语句的日志记录进行复制时,如果语句的设计方式使得数据修改是 不确定的,则源和副本上的数据可能会变得不同;也就是说,它留给了查询优化器。通常,即使在复制之外,这也不是一个好的做法。有关此问题的详细说明,请参阅 第 B.3.7 节,“MySQL 中的已知问题”