您可以通过使用 --binlog-format=
启动 MySQL 服务器来显式选择二进制日志记录格式。支持的 类型
类型
值为:
STATEMENT
使日志记录基于语句。ROW
使日志记录基于行。这是默认值。MIXED
使日志记录使用混合格式。
设置二进制日志记录格式不会激活服务器的二进制日志记录。该设置仅在服务器上启用二进制日志记录时才生效,即当 log_bin
系统变量设置为 ON
时。在 MySQL 8.4 中,默认情况下启用二进制日志记录,并且仅当您使用 --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
值需要足以设置受限会话系统变量的权限。请参阅 第 7.1.9.1 节“系统变量权限”。
客户端可能希望在每个会话的基础上设置二进制日志记录,这有几个原因:
对数据库进行许多小改动的会话可能希望使用基于行的日志记录。
执行与
WHERE
子句中的许多行匹配的更新的会话可能希望使用基于语句的日志记录,因为记录几条语句比记录许多行更有效。某些语句在源上需要大量执行时间,但只会导致修改几行。因此,使用基于行的日志记录来复制它们可能是有益的。
在某些情况下,您不能在运行时切换复制格式:
无法从存储函数或触发器中更改复制格式。
如果启用了
NDB
存储引擎。如果会话打开了临时表,则无法为该会话更改复制格式 (
SET @@SESSION.binlog_format
)。如果任何复制通道打开了临时表,则无法全局更改复制格式 (
SET @@GLOBAL.binlog_format
或SET @@PERSIST.binlog_format
)。如果任何复制通道应用线程当前正在运行,则无法全局更改复制格式 (
SET @@GLOBAL.binlog_format
或SET @@PERSIST.binlog_format
)。
在任何这些情况下尝试切换复制格式(或尝试设置当前复制格式)都会导致错误。但是,您可以随时使用 PERSIST_ONLY
(SET @@PERSIST_ONLY.binlog_format
) 更改复制格式,因为此操作不会修改运行时全局系统变量值,并且仅在服务器重新启动后才生效。
不建议在存在任何临时表时在运行时切换复制格式,因为仅当使用基于语句的复制时才会记录临时表,而使用基于行的复制和混合复制时,不会记录临时表。
在复制正在进行时切换复制格式也会导致问题。每个 MySQL 服务器都可以设置自己的且只能设置自己的二进制日志记录格式(无论 binlog_format
是使用全局范围还是会话范围设置的)。这意味着更改复制源服务器上的日志记录格式不会导致副本更改其日志记录格式以匹配。当使用 STATEMENT
模式时,binlog_format
系统变量不会被复制。当使用 MIXED
或 ROW
日志记录模式时,它会被复制,但会被副本忽略。
副本无法将其接收到的 ROW
格式的二进制日志条目转换为 STATEMENT
格式以供其自身的二进制日志使用。因此,如果源使用 ROW
或 MIXED
格式,则副本也必须使用这两种格式。如果在复制正在进行到使用 STATEMENT
格式的副本时,将源上的二进制日志记录格式从 STATEMENT
更改为 ROW
或 MIXED
,则会导致复制失败并出现错误,例如 执行行事件时出错: '无法执行语句: 无法写入二进制日志,因为语句为行格式,而 BINLOG_FORMAT = STATEMENT。' 当源仍在使用 MIXED
或 ROW
格式时,将副本上的二进制日志记录格式更改为 STATEMENT
格式也会导致相同类型的复制失败。要安全地更改格式,必须停止复制,并确保在源和副本上进行相同的更改。
如果您使用的是 InnoDB
表,并且事务隔离级别是 READ COMMITTED
或 READ UNCOMMITTED
,则只能使用基于行的日志记录。虽然可以将日志记录格式更改为 STATEMENT
,但在运行时这样做会导致很快出现错误,因为 InnoDB
将无法再执行插入操作。
如果将二进制日志格式设置为 ROW
,则许多更改将使用基于行的格式写入二进制日志。但是,某些更改仍使用基于语句的格式。例如,所有 DDL(数据定义语言)语句,如 CREATE TABLE
、ALTER TABLE
或 DROP TABLE
。
使用基于行的二进制日志记录时,binlog_row_event_max_size
系统变量及其对应的启动选项 --binlog-row-event-max-size
设置了行事件最大大小的软限制。默认值为 8192 字节,并且该值只能在服务器启动时更改。如果可能,存储在二进制日志中的行将分组到大小不超过此设置值的事件中。如果无法拆分事件,则可能会超过最大大小。
--binlog-row-event-max-size
选项适用于能够进行基于行复制的服务器。行以块的形式存储到二进制日志中,块的大小(以字节为单位)不超过此选项的值。该值必须是 256 的倍数。默认值为 8192。
当对复制使用基于语句的日志记录时,如果语句的设计方式使得数据修改是非确定性的(也就是说,由查询优化器决定),则源和副本上的数据可能会变得不同。通常,即使在复制之外,这也不是一个好的做法。有关此问题的详细说明,请参阅第 B.3.7 节 “MySQL 中的已知问题”。