#### 5.4.4.2 设置二进制日志格式

您可以通过启动 MySQL 服务器来显式选择二进制日志记录格式[`--binlog 格式=*`类型`*`](replication-options-binary-log.html#sysvar_binlog_format).支持的值*`类型`*是：

-   `陈述`导致日志记录是基于语句的。

-   `排`导致日志记录是基于行的。这是默认设置。

-   `混合`导致日志记录使用混合格式。

    设置二进制日志记录格式不会激活服务器的二进制日志记录。该设置仅在服务器上启用二进制日志记录时生效，即[`log_bin`](replication-options-binary-log.html#sysvar_log_bin)系统变量设置为`在`.从 MySQL 8.0 开始，二进制日志记录默认启用，并且仅在您指定[`--skip-log-bin`](replication-options-binary-log.html#option_mysqld_log-bin)要么[`--disable-log-bin`](replication-options-binary-log.html#option_mysqld_log-bin)启动时的选项。

    日志格式也可以在运行时切换，但请注意，在许多情况下您不能这样做，如本节后面所述。设置全局值[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)系统变量指定更改后连接的客户端的格式：


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

单个客户端可以通过设置会话值来控制自己语句的日志记录格式[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)：

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

改变全球[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)value 需要足够的权限来设置全局系统变量。更改会话[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)value 需要足够的权限来设置受限会话系统变量。看[第 5.1.9.1 节，“系统变量权限”](system-variable-privileges.html).

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

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

-   执行与`在哪里`子句可能希望使用基于语句的日志记录，因为记录一些语句比记录许多行更有效。

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

    当您无法在运行时切换复制格式时有例外：

-   无法从存储的函数或触发器中更改复制格式。

-   如果[`新开发银行`](mysql-cluster.html)存储引擎已启用。

-   如果会话具有打开的临时表，则无法更改会话的复制格式 (`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 服务器都可以设置自己的并且只能设置自己的二进制日志记录格式（true 是否[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)设置为全局或会话范围）。这意味着更改复制源服务器上的日志记录格式不会导致副本更改其日志记录格式以匹配。使用时`陈述`模式[`binlog_format`](replication-options-binary-log.html#sysvar_binlog_format)系统变量不被复制。使用时`混合`要么`排`日志记录模式，它被复制但被副本忽略。

    副本无法转换接收到的二进制日志条目`排`记录格式为`陈述`在自己的二进制日志中使用的格式。因此副本必须使用`排`要么`混合的`如果源文件存在，则设置格式。从更改源上的二进制日志记录格式`陈述`到`一行`或`混合的`在复制到具有`陈述`格式化可能会导致复制失败，并出现错误，例如错误执行行事件：“无法执行语句：无法写入二进制日志，因为语句是行格式和BINLOG。”\_格式=语句。'将副本上的二进制日志记录格式更改为`陈述`当源仍在使用时格式化`混合的`或`一行`格式也会导致相同类型的复制失败。要安全地更改格式，必须停止复制，并确保在源和副本上进行相同的更改。

    如果你正在使用[`InnoDB`](innodb-storage-engine.html)表，事务隔离级别为[`阅读承诺`](innodb-transaction-isolation-levels.html#isolevel_read-committed)或[`阅读未提交`](innodb-transaction-isolation-levels.html#isolevel_read-uncommitted)，只能使用基于行的日志记录。它是*可能的*将日志记录格式更改为`陈述`，但在运行时这样做会很快导致错误，因为`InnoDB`无法再执行插入。

    二进制日志格式设置为`一行`，许多更改将使用基于行的格式写入二进制日志。但是，有些更改仍然使用基于语句的格式。示例包括所有DDL（数据定义语言）语句，例如[`创建表格`](create-table.html), [`改变桌子`](alter-table.html)或[`升降台`](drop-table.html).

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

    这个[`--binlog行事件最大大小`](replication-options-binary-log.html#option_mysqld_binlog-row-event-max-size)选项适用于能够进行基于行的复制的服务器。行以块的形式存储在二进制日志中，其字节大小不超过此选项的值。该值必须是256的倍数。默认值为8192。

警告

使用时*基于语句的日志记录*对于复制，如果语句的设计方式使数据修改不确定，则源和副本上的数据可能会有所不同；也就是说，它由查询优化器决定。一般来说，即使在复制之外，这也不是一个好的做法。有关此问题的详细说明，请参阅[B.3.7节，“MySQL中的已知问题”](known-issues.html).
