7.4.4.5 二进制日志事务压缩
MySQL 支持二进制日志事务压缩;当启用时,事务负载使用 zstd
算法进行压缩,然后将其写入服务器的二进制日志文件中作为单个事件(一个 Transaction_payload_event
)。
压缩的事务负载在被发送到副本、其他 Group Replication 组成员或客户端,如mysqlbinlog,仍然保持压缩状态。它们不会在接收线程中解压缩,而是在relay日志中以压缩状态写入。二进制日志事务压缩因此在事务的发起者和接受者(及其备份)上保存存储空间,并且在服务器实例之间发送事务时节省网络带宽。
压缩的事务负载在其中包含的事件需要被检查时解压缩。例如,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
存储引擎可以在运行时启用压缩事务日志,通过系统变量ndb_log_transaction_compression
和控制压缩级别使用ndb_log_transaction_compression_level_zstd
。从命令行或my.cnf
文件中使用 --binlog-transaction-compression
启用ndb_log_transaction_compression
,忽略--ndb-log-transaction-compression
选项;要禁用NDB
存储引擎的压缩事务日志,设置客户端会话中的 ndb_log_transaction_compression=OFF
。
以下类型的事件总是写入未压缩形式到二进制日志:
-
与事务关联的 GTID 事件(包括匿名 GTID 事件)。
-
其他控制事件,例如视图更改事件和心跳事件。
-
事件事件和包含它们的事务的整个事务。
-
非事务性事件和包含它们的所有事务。混合使用非事务性和事务性存储引擎的事务不压缩其载荷。
-
使用语句基于二进制日志记录的事件。二进制日志事务压缩仅适用于行基于二进制日志格式。
可以在包含压缩事务的二进制日志文件上启用二进制日志加密。
7.4.4.5.1 二进制日志事务压缩时的行为
可以像其他事务一样回滚压缩载荷的事务,并且也可以使用通常的过滤选项在复制服务器上过滤它们。二进制日志事务压缩可以应用于XA事务。
max_allowed_packet
和 replica_max_allowed_packet
仍然适用于服务器,并且是对压缩后的Transaction_payload_event
加上事件头部字节的大小测量。
压缩事务载荷作为单个包发送,而不是像不使用二进制日志事务压缩时那样,每个事件作为单个包发送。如果您的复制拓扑结构处理大事务,注意当启用二进制日志事务压缩时可能会由于事务大小而停止复制。
对于多线程工作人员,每个事务(包括其GTID事件和Transaction_payload_event
)都被分配给一个工作线程。工作线程解压缩事务负载并逐一应用其中的事件。如果在Transaction_payload_event
中找到错误,整个事务将被报告给协调器为失败。当replica_parallel_type
或replica_parallel_type
设置为DATABASE
时,事务影响的所有数据库都将被映射,然后再进行调度。使用二进制日志事务压缩与DATABASE
策略可以减少相比于未压缩的事务,后者在每个事件中映射和调度。
对于半同步复制(见第19.4.10节,“半同步复制”),副本在接收完整的Transaction_payload_event
后确认事务。
当启用二进制日志校验(这是默认值)时, replication 源服务器不为压缩的事务负载中的每个事件写入校验和,而是写入完整的Transaction_payload_event
,并且写入未压缩事件的校验和,如GTID相关事件。
SHOW BINLOG EVENTS
和 SHOW RELAYLOG EVENTS
语句中,Transaction_payload_event
首先被打印为单个单位,然后它被解包,每个事件都被打印。
对于引用事件末尾位置的操作,如START REPLICA
中的 UNTIL
子句、SOURCE_POS_WAIT()
和sql_replica_skip_counter
,必须指定压缩事务负载的末尾位置(Transaction_payload_event
)。当使用sql_replica_skip_counter
跳过事件时,压缩事务负载被计数为单个计数值,所以它内部所有事件都被跳过。
支持二进制日志事务压缩的 MySQL 服务器版本可以处理混合压缩和未压缩的事务负载。
-
群组复制中关于二进制日志事务压缩的系统变量不需要在所有成员上设置相同,并且不会从源服务器到副本中传播。你可以决定每个 MySQL 服务实例是否启用二进制日志事务压缩。
-
如果在服务器上启用了事务压缩,然后禁用,未来的事务将不再被压缩,但已经压缩的事务负载仍然可以处理和显示。
-
如果通过设置
binlog_transaction_compression
会话值来指定事务压缩,二进制日志可以包含压缩和未压缩的事务负载。
在复制拓扑结构中,如果源服务器和副本都启用了二进制日志事务压缩,副本接收压缩的事务负载,然后将其解压、应用事务后再次压缩写入自己的二进制日志。下游副本也会接收压缩的事务负载。
在复制拓扑结构中,如果源服务器启用了二进制日志事务压缩,但副本没有,副本接收压缩的事务负载,然后将其解压、应用事务后写入自己的二进制日志(如果有),下游副本也会接收未压缩的事务负载。
在复制拓扑结构中,如果源服务器不启用二进制日志事务压缩,但其副本启用了,且副本有二进制日志,那么副本将对已应用的事务负载进行压缩,并将压缩后的事务负载写入其二进制日志。下游副本接收到的也是压缩后的事务负载。
如果 MySQL 服务器实例没有二进制日志,它可以无论其 binlog_transaction_compression
值的设置,接收、处理和显示压缩的事务负载。接收到的服务器实例将写入压缩后的事务负载到中继日志,因此可以间接地从拓扑结构中的其他服务器执行的压缩中获益。
7.4.4.5.3 二进制日志事务压缩监控
您可以使用性能chema表binary_log_transaction_compression_stats
监控二进制日志事务压缩的效果。统计信息包括监控期间的数据压缩比率,您也可以查看服务器上最后一个事务的压缩效果。您可以通过清空表来重置统计信息。对于二进制日志和中继日志,统计信息将分开,以便您可以看到每种日志类型的压缩影响。MySQL 服务器实例必须有二进制日志才能生产这些统计信息。
性能_schema 表events_stages_current
显示事务在解压或压缩阶段,并显示该阶段的进度。压缩由处理事务的工作线程在事务提交前执行,条件是没有 finalized 捕获缓存事件排除事务从二进制日志中压缩(例如,incident 事件)。当需要解压时,每次解压一个事件的负载。
mysqlbinlog 使用--verbose
选项,包括压缩大小和未压缩大小的注释,对于压缩的事务负载,以及使用的压缩算法。
您可以在复制连接的协议级别启用压缩,使用CHANGE REPLICATION SOURCE TO
语句中的SOURCE_COMPRESSION_ALGORITHMS
和SOURCE_ZSTD_COMPRESSION_LEVEL
选项,或者replica_compressed_protocol
系统变量。如果在启用二进制日志事务压缩的系统中也启用连接压缩,连接压缩的影响将减少,因为可能没有更多机会来进一步压缩已经压缩的事务负载。然而,连接压缩仍然可以操作未压缩事件和消息头。二进制日志事务压缩可以与连接压缩组合使用,以保存存储空间和网络带宽。如果您想了解复制连接的压缩控制,请参阅第6.2.8节,“连接压缩控制”。
对于群组复制,压缩默认情况下对超过由group_replication_compression_threshold
系统变量设置的阈值的消息启用。您也可以使用group_replication_recovery_compression_algorithms
和group_replication_recovery_zstd_compression_level
系统变量来配置压缩消息发送给分布式恢复的方法。启用二进制日志事务压缩在这些已配置的系统中,群组复制的消息压缩仍然可以操作未压缩事件和消息头,但其影响减少。关于群组复制消息压缩的更多信息,请参见第20.7.4节,“消息压缩”。