压缩MySQL二进制日志(译文)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 在一个繁忙的MySQL服务器上,二进制日志最终可能会成为使用磁盘空间的最大占用者之一。这意味着更高的I/O,更大的备份集(您正在备份二进制日志,对吗?)

在一个繁忙的MySQL服务器上,二进制日志最终可能会成为使用磁盘空间的最大占用者之一。这意味着更高的I/O,更大的备份集(您正在备份二进制日志,对吗?),当向从库传输二进制日志时,网络流量会增加,等等。所以长期以来一直希望有一个二进制日志压缩功能,允许对MySQL正在使用的二进制日志进行压缩。从MySQL 8.0.20开始,现在可以了。这篇文章将探讨这个新功能。

01

配置


二进制日志压缩功能由两个变量控制,一个用于启用该功能,另一个用于指定压缩级别。

变量名称 认值 允许值
binlog_transaction_compression OFF OFF/ON
binlog_transaction_compression_level_zstd 3 1-22


这两个变量的作用可以从它们的名称推断出来:

  • binlog_transaction_compression指定是否启用压缩,
  • binlog_transaction_compression_level_zstd指定压缩级别。原则上,高级别的压缩消耗更多的CPU。

这两个选项都可以在全局范围内和会话范围内动态设置。但是,不允许在事务中间更改。如果您这样做,您会收到这样的错误:



mysql> SET SESSION binlog_transaction_compression = ON;ERROR: 1766 (HY000): The system variable binlog_transaction_compression cannot be set when there is an ongoing transaction.

虽然配置二进制日志压缩很容易,但也需要注意一些限制。


02

限制


关于二进制日志压缩的限制简短地说就是只压缩事务行事件。基于语句的事件、GTID信息、旋转事件、非事务表的行事件等没有压缩。此外,如果您对事务添加非事务性更改,那么两者都不会被压缩。这也意味着每笔交易都是单独压缩的。有关这意味着什么的更多信息,请参阅本文中接下来的例子。

如果您对二进制日志使用所有默认值,并使用InnoDB存储引擎(默认值),则压缩可以起作用。有关限制的完整列表,请参阅官方文档中的二进制日志事务压缩(https://dev.mysql.com/doc/refman/8.0/en/binary-log-transaction-compression.html)。正如我通常所宣扬的,监控是了解您的系统的关键。下面说明如何监控二进制日志压缩功能。

03

监视


有两种方法可以监控二进制日志压缩功能的性能,一种是性能视图中的压缩统计,另一种是性能视图中的新增的两个阶段事件。性能视图中的binary_log_transaction_compression_stats表包括自上次重新启动MySQL(或上次截断表)以来用于压缩的统计信息。该表有与两个二进制日志相关的行,一行用于压缩事件,一行用于未压缩的事件。从库中同样将有两行用于中继日志。一个查询这个视图和二进制日志的例子是:



mysql> SELECT * FROM binary_log_transaction_compression_stats\G*************************** 1. row ***************************                            LOG_TYPE: BINARY                    COMPRESSION_TYPE: ZSTD                 TRANSACTION_COUNTER: 15321            COMPRESSED_BYTES_COUNTER: 102796461          UNCOMPRESSED_BYTES_COUNTER: 252705572              COMPRESSION_PERCENTAGE: 59                FIRST_TRANSACTION_ID: 74470a0c-8ea4-11ea-966e-080027effed8:30730  FIRST_TRANSACTION_COMPRESSED_BYTES: 313FIRST_TRANSACTION_UNCOMPRESSED_BYTES: 363         FIRST_TRANSACTION_TIMESTAMP: 2020-05-07 19:26:37.744437                 LAST_TRANSACTION_ID: 74470a0c-8ea4-11ea-966e-080027effed8:46058   LAST_TRANSACTION_COMPRESSED_BYTES: 712 LAST_TRANSACTION_UNCOMPRESSED_BYTES: 1627          LAST_TRANSACTION_TIMESTAMP: 2020-05-07 19:38:14.149782*************************** 2. row ***************************                            LOG_TYPE: BINARY                    COMPRESSION_TYPE: NONE                 TRANSACTION_COUNTER: 20            COMPRESSED_BYTES_COUNTER: 5351          UNCOMPRESSED_BYTES_COUNTER: 5351              COMPRESSION_PERCENTAGE: 0                FIRST_TRANSACTION_ID: 74470a0c-8ea4-11ea-966e-080027effed8:30718  FIRST_TRANSACTION_COMPRESSED_BYTES: 116FIRST_TRANSACTION_UNCOMPRESSED_BYTES: 116         FIRST_TRANSACTION_TIMESTAMP: 2020-05-07 19:26:37.508155                 LAST_TRANSACTION_ID: 74470a0c-8ea4-11ea-966e-080027effed8:31058   LAST_TRANSACTION_COMPRESSED_BYTES: 116 LAST_TRANSACTION_UNCOMPRESSED_BYTES: 116          LAST_TRANSACTION_TIMESTAMP: 2020-05-07 19:30:30.8407672 rows in set (0.0026 sec) mysql> SHOW BINARY LOGS;+---------------+-----------+-----------+| Log_name      | File_size | Encrypted |+---------------+-----------+-----------+| binlog.000142 |       240 | No        || binlog.000143 |      4933 | No        || binlog.000144 |  28238118 | No        || binlog.000145 |  24667167 | No        || binlog.000146 |  39221771 | No        || binlog.000147 |  11944631 | No        || binlog.000148 |       196 | No        |+---------------+-----------+-----------+7 rows in set (0.0005 sec)

该示例是在启用GTID的情况下生成的,除了binlog.000142,所有二进制日志都是在上次重新启动后创建的。这表明有15341个事务(74470a0c-8ea4-11ea-966e-080027effed8:30718-46058),其中15321个事务被压缩,平均压缩率是59%(将252,705,572字节压缩为102,796,461字节)。还有第一个和最近一次被压缩的事务的统计数据,也有20个事务无法压缩。另外一件事是要知道是在进行压缩和解压方面付出的代价。这可以使用性能模式中的两个阶段事件进行监控:

  • stage/sql/Compressing transaction changes.
  • stage/sql/Decompressing transaction changes. (是的,英文句号是名称的一部分。)


默认情况下,两者都不启用,要收集这些性能计量,您还需要启用events_stages_current消费者。例如,要在配置文件中启用这些配置参数:



[mysqld]performance-schema-instrument = "stage/sql/%Compressing transaction changes.=ON"performance-schema-consumer-events-stages-current = ON

需要注意,启用这些阶段计量会产生一些开销。如果您考虑在生产系统上启用这些影响,请确保首先测试影响。您可以将这两个阶段计量信息与wait/io/file/sql/binlog事件(默认启用)进行比较,后者是花在做I/O上的时间。例如:




mysql> SELECT EVENT_NAME, COUNT_STAR,              FORMAT_PICO_TIME(SUM_TIMER_WAIT) AS total_latency,              FORMAT_PICO_TIME(MIN_TIMER_WAIT) AS min_latency,              FORMAT_PICO_TIME(AVG_TIMER_WAIT) AS avg_latency,              FORMAT_PICO_TIME(MAX_TIMER_WAIT) AS max_latency         FROM performance_schema.events_stages_summary_global_by_event_name        WHERE EVENT_NAME LIKE 'stage/sql/%transaction changes.'\G*************************** 1. row ***************************   EVENT_NAME: stage/sql/Compressing transaction changes.   COUNT_STAR: 15321total_latency: 6.10 s  min_latency: 22.00 ns  avg_latency: 397.96 us  max_latency: 982.12 ms*************************** 2. row ***************************   EVENT_NAME: stage/sql/Decompressing transaction changes.   COUNT_STAR: 0total_latency:   0 ps  min_latency:   0 ps  avg_latency:   0 ps  max_latency:   0 ps2 rows in set (0.0008 sec) mysql> SELECT *         FROM sys.io_global_by_wait_by_latency        WHERE event_name = 'sql/binlog'\G*************************** 1. row ***************************   event_name: sql/binlog        total: 27537total_latency: 4.83 min  avg_latency: 10.51 ms  max_latency: 723.92 ms read_latency: 138.25 uswrite_latency: 290.69 ms misc_latency: 4.82 min   count_read: 37   total_read: 1002 bytes     avg_read:   27 bytes  count_write: 16489total_written: 99.26 MiB  avg_written: 6.16 KiB1 row in set (0.0015 sec)

这里sys视图输出的数据已经自动转换为人类可读的格式,而性能视图中的时间使用FORMAT_PICO_TIME()函数进行转换。在本例中,MySQL总计花了6.21秒进行二进制日志的压缩,每笔事务平均略低于400微秒。相比之下,MySQL总计花了4.8分钟在二进制日志文件上做I/O,这说明压缩在写日志的时间中占比很低。在启用压缩之前,您应该检查写入和读取二进制日志文件所花费的时间,以便确定性能的变化。您还应该检查CPU使用情况的变化。在上面的输出中,它显示压缩率为59%,但对于不同类型的工作负载来说,压缩率如何?

04

示例 – 工作负载为了测量压缩的效果,我运行了一系列任务,并比较了压缩或不压缩的二进制日志的大小。为了比较,我还尝试手动压缩这些测试中未压缩的二进制日志,以查看最佳压缩效果(而不是MySQL使用的每笔事务压缩)。除了必要的设置外,测试采用默认的配置。已经测试了以下工作负载:

  • 批量加载:加载employees示例数据库。
  • 批量更新:更新employees.salaries中所有行salary列:UPDATE employees.salaries SET salary = salary + 1
  • 批量加载:使用sysbench填充四个10万行的表,为oltp_read_write基准测试做准备。
  • OLTP 工作负载:使用前面创建的4个表,用 sysbench运行oltp_read_write基准测试,选项 --events=15000。
  • 单行删除:从sysbench测试中删除其中一个表中的所有10万行。这些行逐一删除,这是压缩的最坏情况,因为事务非常小,并且每个已删除行的二进制日志中只有前镜像。

使用MySQL Shell可以轻松执行单行删除,例如在Python语言模式下:



from datetime import datetime for i in range(100000):    if i % 5000 == 0:        print('{0}: i = {1}'.format(datetime.now(), i))    session.run_sql('DELETE FROM sbtest.sbtest1 WHERE id = {0}'.format(i+1))print('{0}: i = 1000000'.format(datetime.now()))

每个任务的大小生成25 MiB至82 MiB范围内的未压缩二进制日志。测试使用以下设置进行:

  • 没有压缩
  • 启用压缩
  • 加密但未压缩
  • 启用加密和压缩
  • MySQL中没有压缩,手动使用zstd进行压缩

选择zstd的压缩,因为MySQL使用Zstandard压缩算法。如果您想自己尝试,您可以从Facebook的GitHub存储库下载Zstandard源代码,其中还包括编译说明。下表列出了每个组合生成的二进制日志字节大小。

测试 标准 加密 加密+压缩 zstd
加载employees表 66378639 28237933 66379151 28238634 26892387
批量更新 85698320 24667051 85698832 24667677 24779953
sysbench准备 76367740 39221052 39221052 39221806 39775067
sysbench运行 26190200 11933713 26190712 11936561 8468625
单行删除 47300156 39492400 47300668 39637684 16525219

分析加密和压缩的数据,可以推断出加密是压缩后完成,因为加密后数据压缩效果不佳。由于启用加密对压缩的效果影响不大,因此将只讨论正常(未压缩)、压缩和zstd结果。二进制日志大小也可以在下图中看到:测试的结果并不让人吃惊,批量加载和批量更新的二进制压缩效果分别是51%和29%,sysbench OLTP压缩是46%,单行删除压缩是83%,比使用zstd压缩效果差很多。当将MySQL压缩的二进制日志与手动使用zstd压缩的二进制日志进行比较时,发现批量负载的文件大小大致相同,这说明对于大型事务,对每笔事务压缩和对整个文件压缩效果一样。随着事务大小变小,每笔事务压缩的相对效率降低,这对单行删除尤为明显。需要考虑的另一个因素是压缩级别。05

示例 – 压缩级别


关于压缩级别有一些奇怪之处,为读者省事的说法是没有必要修改默认设置。第一个奇怪的是,允许的值是1-22,但zstd只支持1-19级。MySQL文档中没有任何内容可以解释差异。第二个奇怪的是,通过更改binlog_transaction_compression_level_zstd的值,压缩二进制日志的大小实际上不会发生变化,这可以从表中看到:

测试压缩级别 MySQL加载 MySQL OLTP zstd 加载 zstd OLTP
1 28238142 11935450 34483207 8531545
3 28237933 11933713 26892387 8468625
11 28238128 11902669 24737194 6639524
19 28238246 11937664 18867187 5724300
22 28238125 11910022

  • 加载是加载employees数据库。
  • OLTP是使用sysbench进行oltp_read_write基准测试。

为了比较,1、3、11和19级的压缩包括使用zstd手动压缩二进制日志。数据也可以在下图中看到:从图中可以看到,无论MySQL中使用的哪种压缩级别,文件大小基本上都没有差异;而对于zstd,文件大小会随着压缩级别的增加而正常减少。对于加载测试的1级,MySQL的压缩甚至明显优于zstd,看起来就像在MySQL中从未设置压缩级别一样。一个可能的解释是,Zstandard对给定类型的数据进行算法训练(创建字典),这尤其有助于改善小数据的压缩(应为改善大数据的压缩—译者注)。我不知道MySQL是否使用字典,如果是的话,是否使所有压缩级别的效果大致相等。

06

结论


新的二进制日志事务压缩效果很好,可以成为减少I/O、磁盘使用量和网络使用量的好方法,建议您考虑启用它。除非您的CPU资源非常紧张,否则您很可能会从启用二进制日志压缩中受益。从这些测试中,二进制日志占用的磁盘空间可能大致减少一半。但实际情况还要看您的工作负载,您应该使用工作负载进行测试。建议:您还可以启用二进制日志传输压缩,但没有理由同时启用二进制日志事务压缩和传输压缩。另外,目前没有理由改变压缩级别。

相关文章
|
3天前
|
SQL 存储 关系型数据库
Mysql并发控制和日志
通过深入理解和应用 MySQL 的并发控制和日志管理技术,您可以显著提升数据库系统的效率和稳定性。
27 10
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
142 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
16天前
|
SQL 存储 缓存
MySQL进阶突击系列(02)一条更新SQL执行过程 | 讲透undoLog、redoLog、binLog日志三宝
本文详细介绍了MySQL中update SQL执行过程涉及的undoLog、redoLog和binLog三种日志的作用及其工作原理,包括它们如何确保数据的一致性和完整性,以及在事务提交过程中各自的角色。同时,文章还探讨了这些日志在故障恢复中的重要性,强调了合理配置相关参数对于提高系统稳定性的必要性。
|
1月前
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的全量日志文件
MySQL全量日志记录所有操作的SQL语句,默认禁用。启用后,可通过`show variables like %general_log%检查状态,使用`set global general_log=ON`临时开启,执行查询并查看日志文件以追踪SQL执行详情。
|
1月前
|
关系型数据库 MySQL 数据库
【赵渝强老师】MySQL的binlog日志文件
MySQL的binlog日志记录了所有对数据库的更改操作(不包括SELECT和SHOW),主要用于主从复制和数据恢复。binlog有三种模式,可通过设置binlog_format参数选择。示例展示了如何启用binlog、设置格式、查看日志文件及记录的信息。
|
1月前
|
SQL 关系型数据库 MySQL
【赵渝强老师】MySQL的慢查询日志
MySQL的慢查询日志用于记录执行时间超过设定阈值的SQL语句,帮助数据库管理员识别并优化性能问题。通过`mysqldumpslow`工具可查看日志。本文介绍了如何检查、启用及配置慢查询日志,并通过实例演示了慢查询的记录与分析过程。
120 3
|
1月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL的撤销日志文件和错误日志文件
本文介绍了MySQL的物理存储结构,重点讲解了InnoDB存储引擎中的撤销日志文件(undo log)和错误日志文件。从MySQL 8.0开始,默认生成两个10MB的undo表空间文件,并支持动态扩容和收缩。错误日志文件记录了MySQL启动、运行、关闭过程中的问题,通过示例展示了如何查看和使用这些日志。
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
286 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
10天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
318 3

推荐镜像

更多
下一篇
DataWorks