7.4.4.2 设置二进制日志格式
您可以通过使用--binlog-format=
明确地选择二进制日志格式。支持的type
type
值是:
-
STATEMENT
使logging基于语句。 -
ROW
使logging基于行。这是默认的。 -
MIXED
使logging使用混合格式。
设置二进制日志格式不激活服务器的二进制日志功能。该设置只在服务器启用了二进制日志时生效,而不是默认情况下启用,除非您以--skip-log-bin
或--disable-log-bin
启动服务器。在 MySQL 8.4 中,二进制日志默认启用,只有在您以这两个选项启动服务器时才会禁用。
logging格式也可以在运行时切换,但是注意有一些情况下不能这样做,后面这个部分将讨论。将全局值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 服务器都可以设置自己的二进制日志格式(无论是全局或会话范围),这意味着在源服务器更改日志格式时,副本不一定会相应地更改其日志格式。使用 STATEMENT
模式时,binlog_format
系统变量不会被复制。使用 MIXED
或 ROW
日志模式时,它将被复制,但副本会忽略它。
从属服务器不能将接收到的二进制日志记录转换为STATEMENT
格式用于其自己的二进制日志。因此,必须在源服务器上使用ROW
或MIXED
格式。如果在从属服务器正在进行 replication 到一个使用STATEMENT
格式的服务器,而源服务器正在更改为ROW
或MIXED
格式,可能会导致 replication 失败,出现错误,如Error executing row event: 'Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT.'。要安全地更改格式,必须停止 replication,并确保在源服务器和从属服务器上都进行相同的更改。
如果您使用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中的已知问题”。