您可以通过启动 MySQL 服务器时使用 --binlog-format=
明确选择二进制日志格式。支持的 type
type
值为:
-
STATEMENT
导致基于语句的日志记录。 -
ROW
导致基于行的日志记录。这是默认值。 -
MIXED
导致混合格式的日志记录。
设置二进制日志格式不会激活服务器的二进制日志记录。该设置仅在服务器启用二进制日志记录时生效,即当 log_bin
系统变量设置为 ON
时。在 MySQL 8.3 中,默认启用二进制日志记录,除非您使用 --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 节,“系统变量权限”。
客户端可能想要在每个会话中设置二进制日志记录的原因有多种:
-
对数据库进行许多小修改的会话可能想要使用基于行的日志记录。
-
执行更新语句的会话可能想要使用基于语句的日志记录,因为记录少量语句比记录许多行更高效。
-
一些语句在源服务器上需要大量执行时间,但只修改了少量行。因此,使用基于行的日志记录来复制它们可能是有益的。
有一些情况下您不能在运行时切换复制格式:
-
不能从存储函数或触发器中更改复制格式。
-
如果启用了
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
更改为 ROW
或 MIXED
格式,而副本仍然使用 STATEMENT
格式时,可能会导致复制失败,例如 Error executing row event: 'Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT.' 将二进制日志记录格式从 MIXED
或 ROW
格式更改为 STATEMENT
格式时,也会导致同样的复制失败。要安全地更改格式,您必须停止复制并确保在源服务器和副本上都进行了相同的更改.
如果您使用 InnoDB
表格,并且事务隔离级别是 已提交读取
或 未提交读取
,那么只能使用基于行的日志记录。如果您尝试在运行时将日志格式更改为 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 已知问题”。