您可以通过使用 --binlog-format=
启动 MySQL 服务器来明确选择二进制日志记录格式。type
type
的支持值为
STATEMENT
使日志记录基于语句。ROW
使日志记录基于行。这是默认设置。MIXED
使日志记录使用混合格式。
设置二进制日志记录格式不会激活服务器的二进制日志记录。仅当服务器上启用了二进制日志记录时,该设置才会生效,即当 log_bin
系统变量设置为 ON
时。在 MySQL 9.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
值需要足以设置受限会话系统变量的权限。请参阅第 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 中的已知问题”。