#### 5.4.4.5 二进制日志事务压缩

从 MySQL 8.0.20 开始，您可以在 MySQL 服务器实例上启用二进制日志事务压缩。启用二进制日志事务压缩时，事务有效负载使用 zstd 算法进行压缩，然后作为单个事件写入服务器的二进制日志文件（a`Transaction_payload_event`）。

压缩的事务有效负载在复制流中发送到副本、其他组复制组成员或客户端（例如[**mysqlbinlog**](mysqlbinlog.html).它们不会被接收线程解压缩，并且仍以压缩状态写入中继日志。因此，二进制日志事务压缩节省了事务发起方和接收方（以及它们的备份）的存储空间，并在服务器实例之间发送事务时节省了网络带宽。

当需要检查其中包含的单个事件时，压缩的事务有效负载会被解压缩。例如，`Transaction_payload_event`由应用程序线程解压缩，以便将其包含的事件应用于接收者。在恢复过程中也进行减压，通过[**mysqlbinlog**](mysqlbinlog.html)在重放交易时，并由[`显示 BINLOG 事件`](show-binlog-events.html)和[`显示中继日志事件`](show-relaylog-events.html)陈述。

您可以使用以下命令在 MySQL 服务器实例上启用二进制日志事务压缩[`binlog_transaction_compression`](replication-options-binary-log.html#sysvar_binlog_transaction_compression)系统变量，默认为`离开`.您还可以使用[`binlog_transaction_compression_level_zstd`](replication-options-binary-log.html#sysvar_binlog_transaction_compression_level_zstd)系统变量设置用于压缩的 zstd 算法的级别。此值确定压缩力，从 1（最低力）到 22（最高力）。随着压缩级别的提高，压缩比也随之提高，从而减少了事务负载所需的存储空间和网络带宽。但是，数据压缩所需的工作量也会增加，占用源服务器上的时间和 CPU 和内存资源。压缩力的增加与压缩比的增加没有线性关系。

以下类型的事件被排除在二进制日志事务压缩之外，因此始终未压缩地写入二进制日志：

-   与交易的 GTID 相关的事件（包括匿名 GTID 事件）。

-   其他类型的控制事件，例如视图更改事件和心跳事件。

-   事件事件以及包含它们的所有交易。

-   非交易事件和包含它们的所有交易。涉及混合非事务性和事务性存储引擎的事务不会对其有效负载进行压缩。

-   使用基于语句的二进制日志记录的事件。二进制日志事务压缩仅适用于基于行的二进制日志格式。

    二进制日志加密可用于包含压缩事务的二进制日志文件。

##### 5.4.4.5.1 启用二进制日志事务压缩时的行为

具有压缩负载的事务可以像任何其他事务一样回滚，也可以通过通常的过滤选项在副本上过滤掉。二进制日志事务压缩可以应用于 XA 事务。

启用二进制日志事务压缩后，[`max_allowed_pa​​cket`](server-system-variables.html#sysvar_max_allowed_packet)和[`replica_max_allowed_pa​​cket`](replication-options-replica.html#sysvar_replica_max_allowed_packet)要么[`slave_max_allowed_pa​​cket`](replication-options-replica.html#sysvar_slave_max_allowed_packet)服务器的限制仍然适用，并且是根据压缩的大小来衡量的`Transaction_payload_event`，加上用于事件标头的字节。

重要的

压缩的事务有效负载作为单个数据包发送，而不是在单个数据包中发送事务的每个事件，就像不使用二进制日志事务压缩时的情况一样。如果您的复制拓扑处理大型事务，请注意，在不使用二进制日志事务压缩时可以成功复制的大型事务可能会在使用二进制日志事务压缩时由于其大小而停止复制。

对于多线程工作者，每个事务（包括其 GTID 事件和`Transaction_payload_event`) 分配给工作线程。工作线程解压缩事务有效负载并一一应用其中的各个事件。如果在应用程序中的任何事件时发现错误`Transaction_payload_event`，完整的事务被报告给协调器失败。什么时候[`副本并行类型`](replication-options-replica.html#sysvar_replica_parallel_type)要么[`slave_parallel_type`](replication-options-replica.html#sysvar_slave_parallel_type)被设定为`数据库`，所有受事务影响的数据库都在事务调度之前被映射。使用二进制日志事务压缩与`数据库`与为每个事件映射和安排的未压缩事务相比，策略可以降低并行度。

对于半同步复制（请参阅[第 17.4.10 节，“半同步复制”](replication-semisync.html))，副本在完成时确认事务`Transaction_payload_event`已经收到。

启用二进制日志校验和（这是默认设置）时，复制源服务器不会在压缩的事务有效负载中写入单个事件的校验和。相反，为完整的写入校验和`Transaction_payload_event`，并且为任何未压缩的事件写入单独的校验和，例如与 GTID 相关的事件。

为了[`显示 BINLOG 事件`](show-binlog-events.html)和[`显示中继日志事件`](show-relaylog-events.html)声明，`Transaction_payload_event`首先作为一个单元打印，然后将其解包并打印其中的每个事件。

对于引用事件结束位置的操作，例如[`开始复制`](start-replica.html)（或在 MySQL 8.0.22 之前，[`启动奴隶`](start-slave.html)) 与`直到`条款，[`SOURCE_POS_WAIT()`](miscellaneous-functions.html#function_source-pos-wait)要么[`MASTER_POS_WAIT()`](miscellaneous-functions.html#function_master-pos-wait)， 和[`sql_replica_skip_counter`](replication-options-replica.html#sysvar_sql_replica_skip_counter)要么[`sql_slave_skip_counter`](replication-options-replica.html#sysvar_sql_slave_skip_counter)，您必须指定压缩事务有效负载的结束位置（`Transaction_payload_event`）。使用跳过事件时[`sql_replica_skip_counter`](replication-options-replica.html#sysvar_sql_replica_skip_counter)要么[`sql_slave_skip_counter`](replication-options-replica.html#sysvar_sql_slave_skip_counter)，压缩的事务有效负载被计为单个计数器值，因此其中的所有事件都被作为一个单元跳过。

##### 5.4.4.5.2 组合压缩和未压缩的事务负载

支持二进制日志事务压缩的 MySQL 服务器版本可以处理压缩和未压缩事务有效负载的混合。

-   与二进制日志事务压缩相关的系统变量不需要在所有 Group Replication 组成员上设置相同，并且不会从源复制到复制拓扑中的副本。您可以决定二进制日志事务压缩是否适用于每个具有二进制日志的 MySQL 服务器实例。

-   如果在服务器上启用然后禁用事务压缩，则压缩不会应用于源自该服务器的未来事务，但仍然可以处理和显示已压缩的事务有效负载。

-   如果通过设置会话值为单个会话指定事务压缩[`binlog_transaction_compression`](replication-options-binary-log.html#sysvar_binlog_transaction_compression)，二进制日志可以包含压缩和未压缩的事务有效负载的混合。

    当复制拓扑中的源及其副本都启用了二进制日志事务压缩时，副本接收压缩的事务有效负载并将它们压缩写入其中继日志。它解压缩事务有效负载以应用事务，然后在申请写入其二进制日志后再次压缩它们。任何下游副本都会接收压缩的事务有效负载。

    当复制拓扑中的源启用了二进制日志事务压缩但其副本未启用时，副本将接收压缩的事务有效负载并将其压缩写入其中继日志。它解压缩事务有效负载以应用事务，然后将它们解压缩后写入自己的二进制日志（如果有的话）。任何下游副本都会收到未压缩的事务有效负载。

    当复制拓扑中的源未启用二进制日志事务压缩但其副本启用时，如果副本具有二进制日志，它会在应用它们后压缩事务有效负载，并将压缩的事务有效负载写入其二进制日志。任何下游副本都会接收压缩的事务有效负载。

    当 MySQL 服务器实例没有二进制日志时，如果它是 MySQL 8.0.20 的版本，它可以接收、处理和显示压缩的事务有效负载，而不管它的值[`binlog_transaction_compression`](replication-options-binary-log.html#sysvar_binlog_transaction_compression).此类服务器实例接收的压缩事务​​有效负载以其压缩状态写入中继日志，因此它们间接受益于复制拓扑中其他服务器执行的压缩。

    MySQL 8.0.20 之前版本的副本无法从启用了二进制日志事务压缩的源复制。MySQL 8.0.20 或更高版本的副本可以从不支持二进制日志事务压缩的早期版本的源复制，并且可以在将来自该源的事务写入自己的二进制日志时对其进行自己的压缩。

##### 5.4.4.5.3 监控二进制日志事务压缩

您可以使用 Performance Schema 表监控二进制日志事务压缩的效果[`binary_log_transaction_compression_stats`](performance-schema-binary-log-transaction-compression-stats-table.html).统计包括监控期间的数据压缩率，还可以查看压缩对服务器上最后一个事务的影响。您可以通过截断表来重置统计信息。二进制日志和中继日志的统计信息被拆分出来，因此您可以看到压缩对每种日志类型的影响。MySQL 服务器实例必须具有二进制日志才能生成这些统计信息。

性能模式表[`events_stages_current`](performance-schema-events-stages-current-table.html)显示事务何时处于对其事务有效负载的解压缩或压缩阶段，并显示其在此阶段的进度。压缩由处理事务的工作线程在事务提交之前执行，前提是最终捕获缓存中没有将事务从二进制日志事务压缩中排除的事件（例如，事件事件）。当需要解压时，每次从有效载荷中执行一个事件。

[**mysqlbinlog**](mysqlbinlog.html)与[`--详细`](mysqlbinlog.html#option_mysqlbinlog_verbose)选项包括说明压缩事务有效负载的压缩大小和未压缩大小以及使用的压缩算法的注释。

您可以在协议级别为复制连接启用连接压缩，使用`SOURCE_COMPRESSION_ALGORITHMS`\|`MASTER_COMPRESSION_ALGORITHMS`和`SOURCE_ZSTD_COMPRESSION_LEVEL`\|`MASTER_ZSTD_COMPRESSION_LEVEL`的选项[`将复制源更改为`](change-replication-source-to.html)语句（来自 MySQL 8.0.23）或[`将主更改为`](change-master-to.html)语句（在 MySQL 8.0.23 之前），或[`副本压缩协议`](replication-options-replica.html#sysvar_replica_compressed_protocol)要么[`slave_compressed_protocol`](replication-options-replica.html#sysvar_slave_compressed_protocol)系统变量。如果在同时启用了连接压缩的系统中启用二进制日志事务压缩，则连接压缩的影响会降低，因为可能几乎没有机会进一步压缩压缩的事务有效负载。但是，连接压缩仍然可以对未压缩的事件和消息头进行操作。如果您需要节省存储空间和网络带宽，可以结合使用连接压缩来启用二进制日志事务压缩。有关复制连接的连接压缩的更多信息，请参阅[第 4.2.8 节，“连接压缩控制”](connection-compression-control.html).

对于组复制，默认情况下会为超过由设置的阈值的消息启用压缩[`group_replication_compression_threshold`](group-replication-options.html#sysvar_group_replication_compression_threshold)系统变量。您还可以通过从捐赠者的二进制日志中传输状态的方法为发送的用于分布式恢复的消息配置压缩，使用[`group_replication_recovery_compression_algorithms`](group-replication-options.html#sysvar_group_replication_recovery_compression_algorithms)和[`group_replication_recovery_zstd_compression_level`](group-replication-options.html#sysvar_group_replication_recovery_zstd_compression_level)系统变量。如果在配置了这些的系统中启用二进制日志事务压缩，Group Replication 的消息压缩仍然可以对未压缩的事件和消息头进行操作，但其影响会降低。有关组复制的消息压缩的更多信息，请参阅[第 18.7.4 节，“消息压缩”](group-replication-message-compression.html).
