二进制日志事务压缩

来自泡泡学习笔记
跳到导航 跳到搜索

从MySQL 8.0.20开始,您可以在MySQL服务器实例上启用二进制日志事务压缩。当启用二进制日志事务压缩时,事务负载将使用zstd算法压缩,然后作为单个事件(Transaction_payload_event)写入服务器的二进制日志文件。

压缩的事务负载在发送到副本、其他Group Replication组成员或客户端(如mysqlbinlog)的复制流中保持压缩状态。接收线程不会对压缩事务负载进行解压缩,而是以其压缩状态将其写入中继日志。因此,二进制日志事务压缩既可以在事务发起方和接收方(以及它们的备份)节省存储空间,又可以在服务器实例之间发送事务时节省网络带宽。

当需要检查其中包含的各个事件时,压缩的事务负载将被解压缩。例如,接收端将解压缩Transaction_payload_event以应用其中包含的事件。在恢复过程中,通过mysqlbinlog重放事务时也会进行解压缩,并且通过SHOW BINLOG EVENTS和SHOW RELAYLOG EVENTS语句进行解压缩。

您可以使用binlog_transaction_compression系统变量在MySQL服务器实例上启用二进制日志事务压缩,默认值为OFF。您还可以使用binlog_transaction_compression_level_zstd系统变量设置用于压缩的zstd算法的级别。此值确定压缩的努力程度,范围从1(最低努力)到22(最高努力)。随着压缩级别的增加,压缩比例增加,从而减少了事务负载所需的存储空间和网络带宽。然而,数据压缩所需的努力也会增加,占用发起服务器上的时间、CPU和内存资源。压缩努力的增加与压缩比例的增加之间没有线性关系。

注意事项:

在NDB 8.0.31之前:可以在NDB Cluster中启用二进制日志事务压缩,但只能在启动服务器时使用–binlog-transaction-compression选项(可能还包括–binlog-transaction-compression-level-zstd选项);在运行时更改binlog_transaction_compression和binlog_transaction_compression_level_zstd系统变量的值对NDB表的日志记录没有影响。

NDB 8.0.31及更高版本:您可以在运行时使用引入的ndb_log_transaction_compression系统变量启用使用NDB存储引擎的表的压缩事务的二进制日志记录,并使用ndb_log_transaction_compression_level_zstd控制压缩级别。在命令行或my.cnf文件中使用–binlog-transaction-compression启动mysqld会自动启用ndb_log_transaction_compression,并忽略–ndb-log-transaction-compression选项的任何设置;要仅针对NDB存储引擎禁用二进制日志事务压缩,在启动mysqld后,在客户端会话中将ndb_log_transaction_compression设置为OFF。

以下类型的事件不包括在二进制日志事务压缩中,因此始终以未压缩的方式写入二进制日志:

  • 与事务的GTID相关的事件(包括匿名GTID事件)。
  • 其他类型的控制事件,如视图变更事件和心跳事件。
  • 事件事件和包含它们的任何事务。
  • 非事务性事件和包含它们的任何事务。涉及非事务性和事务性存储引擎混合的事务不会被压缩。
  • 使用基于语句的二进制日志记录的事件。二进制日志事务压缩仅适用于基于行的二进制日志记录格式。

可以在包含压缩事务的二进制日志文件上使用二进制日志加密。

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

具有压缩负载的事务可以像其他事务一样回滚,并且可以通过常规的过滤选项在副本上进行过滤。二进制日志事务压缩可以应用于XA事务。

当启用二进制日志事务压缩时,服务器仍然适用于max_allowed_packet和replica_max_allowed_packet或slave_max_allowed_packet限制,并且这些限制是基于Transaction_payload_event的压缩大小以及事件头部的字节数进行计算。

重要提示

压缩的事务负载作为单个数据包发送,而不是在不使用二进制日志事务压缩时,事务的每个事件被作为单独的数据包发送。如果您的复制拓扑处理大型事务,请注意,当使用二进制日志事务压缩时,一个大型事务在不使用二进制日志事务压缩时可以成功复制,但由于其大小,在使用二进制日志事务压缩时可能会导致复制停止。

对于多线程工作线程,每个事务(包括其GTID事件和Transaction_payload_event)被分配给一个工作线程。工作线程对事务负载进行解压缩,并逐个应用其中的各个事件。如果在Transaction_payload_event中应用任何事件时发现错误,则将完整的事务报告给协调者,表示失败。当将replica_parallel_type或slave_parallel_type设置为DATABASE时,在调度事务之前,将映射受事务影响的所有数据库。与未压缩的事务相比,使用数据库策略的二进制日志事务压缩可以减少并行性,未压缩的事务会针对每个事件进行映射和调度。

对于半同步复制,在接收到完整的Transaction_payload_event时,副本确认该事务。

当启用二进制日志校验和(默认情况下)时,复制源服务器不会为压缩事务负载中的单个事件编写校验和。相反,为完整的Transaction_payload_event编写一个校验和,为未压缩的任何事件编写单独的校验和,例如与GTID相关的事件。

对于SHOW BINLOG EVENTS和SHOW RELAYLOG EVENTS语句,首先将Transaction_payload_event作为一个单元打印,然后解压缩它并打印其中的每个事件。

对于引用事件结束位置的操作,例如带有UNTIL子句的START REPLICA(或在MySQL 8.0.22之前的版本中为START SLAVE),SOURCE_POS_WAIT()或MASTER_POS_WAIT(),以及sql_replica_skip_counter或sql_slave_skip_counter,您必须指定压缩事务负载(Transaction_payload_event)的结束位置。在使用sql_replica_skip_counter或sql_slave_skip_counter跳过事件时,压缩的事务负载被计为单个计数器值,因此其中的所有事件将作为一个单元被跳过。

处理压缩和未压缩的事务负载的混合

在支持二进制日志事务压缩的MySQL Server版本中,可以处理压缩和未压缩的事务负载的混合。

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

如果启用了事务压缩,然后在服务器上禁用了它,将不会对未来在该服务器上发起的事务应用压缩,但已经压缩的事务负载仍然可以处理和显示。

如果通过设置binlog_transaction_compression会话值为个别会话指定事务压缩,则二进制日志可以包含压缩和未压缩的事务负载的混合。

  • 当复制拓扑中的源和其副本都启用了二进制日志事务压缩时,副本接收压缩的事务负载并将其压缩写入中继日志。它解压缩事务负载以应用事务,然后在将其写入二进制日志之前再次进行压缩。任何下游副本都会收到压缩的事务负载。
  • 当复制拓扑中的源启用了二进制日志事务压缩,但其副本没有启用时,副本接收压缩的事务负载并将其压缩写入中继日志。它解压缩事务负载以应用事务,然后将其未压缩地写入自己的二进制日志(如果有的话)。任何下游副本都会收到未压缩的事务负载。
  • 当复制拓扑中的源未启用二进制日志事务压缩,但其副本启用了压缩时,如果副本有二进制日志,它会在应用事务后对事务负载进行压缩,并将压缩的事务负载写入其二进制日志。任何下游副本都会收到压缩的事务负载。

当MySQL Server实例没有二进制日志时,如果它是MySQL 8.0.20版本之后的版本,无论binlog_transaction_compression的值如何,它都可以接收、处理和显示压缩的事务负载。这些服务器实例接收到的压缩事务负载会以压缩状态写入中继日志,因此间接受益于复制拓扑中其他服务器进行的压缩操作。

MySQL 8.0.20版本之前的副本无法从启用了二进制日志事务压缩的源进行复制。MySQL 8.0.20版本及以上的副本可以从不支持二进制日志事务压缩的早期版本源进行复制,并在将其写入自己的二进制日志时对从源接收的事务进行自己的压缩操作。

监控二进制日志事务压缩

您可以使用性能模式表binary_log_transaction_compression_stats来监控二进制日志事务压缩的效果。统计数据包括在监控期间的数据压缩比率,您还可以查看压缩对服务器上最后一个事务的影响。您可以通过截断表来重置统计数据。二进制日志和中继日志的统计数据是分开的,因此您可以看到每种日志类型的压缩影响。MySQL服务器实例必须有二进制日志才能生成这些统计数据。

性能模式表events_stages_current显示了事务在解压缩或压缩阶段的情况,并显示了该阶段的进度。压缩是由处理事务的工作线程在事务提交之前进行的,前提是在最终的捕获缓存中没有排除该事务的事件(例如,incident事件)。当需要解压缩时,将逐个事件地对负载进行解压缩。

使用–verbose选项的mysqlbinlog命令会包含注释,注明压缩事务负载的压缩大小和未压缩大小,以及使用的压缩算法。

您可以在复制连接的协议级别启用连接压缩,使用CHANGE REPLICATION SOURCE TO语句(MySQL 8.0.23之后)或CHANGE MASTER TO语句(MySQL 8.0.23之前)的SOURCE_COMPRESSION_ALGORITHMS | MASTER_COMPRESSION_ALGORITHMS和SOURCE_ZSTD_COMPRESSION_LEVEL | MASTER_ZSTD_COMPRESSION_LEVEL选项,或者使用replica_compressed_protocol或slave_compressed_protocol系统变量。如果在启用连接压缩的系统中启用了二进制日志事务压缩,连接压缩的影响会减小,因为可能很少有机会进一步压缩已经压缩的事务负载。然而,连接压缩仍然可以用于未压缩的事件和消息头。如果您需要节省存储空间和网络带宽,可以同时启用二进制日志事务压缩和连接压缩。

对于Group Replication,默认情况下启用了超过group_replication_compression_threshold系统变量设置的阈值的消息的压缩。您还可以通过使用group_replication_recovery_compression_algorithms和group_replication_recovery_zstd_compression_level系统变量,为从捐赠者的二进制日志进行状态传输的分布式恢复发送的消息配置压缩。如果在配置了这些功能的系统中启用了二进制日志事务压缩,Group Replication的消息压缩仍然可以用于未压缩的事件和消息头,但其影响会减小。