[翻译]PostgreSQL中的WAL压缩以及版本15中的改进

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: [翻译]PostgreSQL中的WAL压缩以及版本15中的改进

[翻译]PostgreSQL中的WAL压缩以及版本15中的改进从以开始就一直在尝试对WAL进行不同级别的压缩。自2016年以来内置功能(wal_compression)就一直存在,几乎所有备份工具都会在传递到备机前对WAL进行压缩。但现在是时候再看看内置的wal_compression功能了。因为PG15提供了更多功能。如果我们将其与PG15中WAL归档的其他重大改进相结合,将会有相当大的收益,如之前贴子PG15中的新WAL归档模块/库:https://www.percona.com/blog/new-wal-archive-module-library-in-postgresql-15/以及PG15中的WAL归档加速:https://www.percona.com/blog/speed-up-of-the-wal-archiving-in-postgresql-15/这里并不打算通过备份工具查看WAL段文件压缩,因为它是一个PG外部工具,主要是备份工具的一个功能,即使我们不使用专门的备份工具,我们仍然可以将WAL段文件作为归档的一部分进行压缩,这可以获得很大回报。先看下PG内部为WAL压缩提供了什么。在将整页写入WAL时启动WAL压缩功能,这将节省大量IO开箱。减小WAL段文件大小在复制和备份方面有进一步的好处,毕竟需要传输的数据更少了嘛。


什么是全页写?


新手用户可能想了解啥是“Full Page Writes”PG默认使用8KB页面。


postgres=# show block_size ;
block_size
------------
8192
(1 row)

但是主机可能正在处理更小的页面,比如 4k 页面。

    $ getconf PAGESIZE
    4096

    PG将8KB页作为读写的“原子单位”来处理。但由于主机的页面较小,它会拆分8KB页面,并将每个OS页面视为一个原子单位。如果突然中断,会导致问题:8KB页面的一部分可能已保存,而另一部分可能会丢失。因为主机可能不会将后者视为原始部分的一部分。这就是通常说的“部分页面写入”或“撕裂页面”。从数据库的角度来看,这种“损坏的页面”是损坏的。如果存在具有这种撕裂页面的数据文件,PG将失去页面的一致性。当然,这不仅仅是PG的问题,每个数据库软件都需要处理整个问题。例如MySQL/InnoDB使用doublewrite缓冲区处理此问题,恢复时从doublewrite恢复未损坏页面的副本。PG解决这个问题的方法略有不同。该副本在检查点后首次修改时,PG将完整页面的副本写入WAL有日志中。由于WAL周期性同步,并且PG也可以决定在哪个点进行恢复,因此WAL是一个安全的地方用于保存“整页”副本。


    全页写的性能损失


    如上所述,当数据库页面在检查点之后第一次被修改时,需要将其安全地写入 WAL。因此在崩溃恢复期间,PostgreSQL 可以安全地应用来自 WAL 日志的一致页面。但这会带来相当大的性能影响。现在我们知道在一个检查点之后很有可能会立即进行过多的整页写入。这将在 PostgreSQL性能基准测试中清晰可见,作为Vadim 在他的测试中观察到的“锯齿波”模式:

    正如我们所看到的,由于大量 WAL 写入,吞吐量在每个检查点之后突然下降,然后逐渐回升,直到下一个检查点。


    全页压缩和改进


    PG14及其之前的版本全页更大并且包含所有内容。允许在写入WAL段文件之前压缩那些完整的页面。这个特性在PG9.5就出现了,使用内置的LZ压缩实现,通常称为“pglz”。但由于CPU开销,并不受欢迎。所以并不建议使用。可以使用如下命令启用:


    ALTER SYSTEM SET wal_compression=ON;
    SELECT pg_reload_conf();

    现在的压缩算法开始提供更好的压缩,同时占用更少的CPU周期。Lz4就是一个很好的例子。PG15针对wal_compression增加了枚举值:pglz、lz4、zstd。以及向后兼容的on和off。on,true,yes和1等布尔等效于“pglz”。 PostgreSQL中内置的压缩库 pglz 不同,新的压缩功能由外部库提供。因此需要在编译时启用它们。配置标志–with-lz4和–with-zstd分别用于 lz4 和 zstd。对于repositories中安装的预编译安装包,可以使用下面命令来检查:


    /usr/pgsql-15/bin/pg_config | grep "zstd\|lz4"
    CONFIGURE = '--enable-rpath' '--prefix=/usr/pgsql-15' '--includedir=/usr/pgsql-15/include' '--mandir=/usr/pgsql-15/share/man' '--datadir=/usr/pgsql-15/share' '--libdir=/usr/pgsql-15/lib' '--with-lz4' '--with-extra-version= - Percona Distribution' '--with-zstd' '--with-icu' '--with-llvm' '--with-perl' '--with-python' '--with-tcl' '--with-tclconfig=/usr/lib64' '--with-openssl' '--with-pam' '--with-gssapi' '--with-includes=/usr/include' '--with-libraries=/usr/lib64' '--enable-nls' '--enable-dtrace' '--with-uuid=e2fs' '--with-libxml' '--with-libxslt' '--with-ldap' '--with-selinux' '--with-systemd' '--with-system-tzdata=/usr/share/zoneinfo' '--sysconfdir=/etc/sysconfig/pgsql' '--docdir=/usr/pgsql-15/doc' '--htmldir=/usr/pgsql-15/doc/html' 'CFLAGS=-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' 'LDFLAGS=-Wl,--as-needed' 'LLVM_CONFIG=/usr/bin/llvm-config' 'CLANG=/usr/bin/clang' 'PKG_CONFIG_PATH=:/usr/lib64/pkgconfig:/usr/share/pkgconfig' 'PYTHON=/usr/bin/python3'
    LIBS = -lpgcommon -lpgport -lselinux -lzstd -llz4 -lxslt -lxml2 -lpam -lssl -lcrypto -lgssapi_krb5 -lz -lreadline -lpthread -lrt -ldl -lm

    为什么仅压缩全页写?


    各个进程产生WAL记录,延迟对于事务来说非常重要。因此压缩所有WAL可能不会增加太多价值。但是如果将来包含这样的功能,那么索引或者批量加载数据等领域可能会从WAL压缩中获得收益。


    压缩选项


    当谈到压缩时,自然而然地,问题将是关于 I/O 的节省。众所周知,压缩是以 CPU 使用为代价的。我的目标是快速检查当 CPU 利用率已经很高时是否有任何好处,以及是否对整体 TPS 有任何不利(负面)影响。如果有大量整页写入,则可以节省相当多的钱。我可以人为触发检查点以查看对总 WAL 生成的最终影响。

    Lz4以更少的CPU成本提供与默认pglz相当的压缩。Zstd可以提供最高的压缩率(比 lz4 多 30%)。在一个已经处于生成过多WAL边缘的系统中,未压缩的WAL可以触发更多的检查点,从而导致生成更多的WAL。


    总结


    1)老版本中的pglz压缩方法并不高效。使用更多CPU在指定工作负载和机器配置下影响TPS。2)现在的压缩算法和库非常优秀,相比pglz可以做更多的工作。3)测试中看不出对TPS有啥不利影响,相反,启用压缩后,观察到有10-15%的提升,可能因为更少的IO wait。4)如果数据库负载的瓶颈是CPU,那么建议使用lz4,因为该算法相对使用较少的CPU。压缩效果接近gplz但不会造成较高的CPU消耗5)如果服务器负载不受限制,可以使用zstd,可以以更多的CPU利用率为代价,为我们提供更好的压缩6)WAL压缩的一个间接好处是减少了由生成WAL量(max_wal_size)触发checkpoint的几率压缩的实际好处取决于许多因素。配置的检查点频率、WAL 生成触发检查点的机会、存储性能、可接受的 CPU 开销、CPU 架构类型以及许多其他因素。随着新选项的引入,进入壁垒显着降低。


    原文


    https://www.percona.com/blog/wal-compression-in-postgresql-and-recent-improvements-in-version-15/

    相关实践学习
    使用PolarDB和ECS搭建门户网站
    本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
    阿里云数据库产品家族及特性
    阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
    目录
    相关文章
    |
    26天前
    |
    关系型数据库 MySQL 数据库
    MySQL高级篇——MVCC多版本并发控制
    什么是MVCC、快照读与当前读、隐藏字段、Undo Log版本链、ReadView、举例说明、InnoDB 解决幻读问题
    MySQL高级篇——MVCC多版本并发控制
    |
    1月前
    |
    关系型数据库 分布式数据库 数据库
    开源云原生数据库PolarDB PostgreSQL 15兼容版本正式发布
    PolarDB进行了深度的内核优化,从而实现以更低的成本提供商业数据库的性能。
    |
    28天前
    |
    监控 关系型数据库 MySQL
    如何升级mysql的版本
    如何升级mysql的版本
    84 2
    |
    28天前
    |
    存储 监控 关系型数据库
    如何升级MySQL版本?
    如何升级MySQL版本?
    42 2
    |
    2月前
    |
    关系型数据库 MySQL Shell
    MySQL数据库一键安装脚本,适合任何版本
    MySQL数据库一键安装脚本,适合任何版本
    40 2
    |
    2月前
    |
    关系型数据库 MySQL Linux
    一文教会你如何在Linux系统中使用Docker安装Mysql 5.7版本 【详细过程+图解】
    这篇文章提供了在Linux系统中使用Docker安装Mysql 5.7版本的详细过程和图解,包括安装指定版本、创建实例、启动、使用Navicat连接测试、文件挂载与端口映射、进入容器、配置文件修改以及重新启动容器等步骤。
    一文教会你如何在Linux系统中使用Docker安装Mysql 5.7版本 【详细过程+图解】
    |
    2月前
    |
    关系型数据库 MySQL 数据库
    同一台电脑安装两个不同版本的mysql。简单暴力有效
    这篇文章介绍了在同一台电脑上安装并配置两个不同版本的MySQL数据库的过程,包括修改端口号、配置服务、修改连接端口和测试连接情况,以确保不同版本的MySQL能够正常运行而不相互干扰。
    同一台电脑安装两个不同版本的mysql。简单暴力有效
    |
    2月前
    |
    算法 关系型数据库 MySQL
    揭秘MySQL中的版本号排序:这个超级算法将颠覆你的排序世界!
    【8月更文挑战第8天】在软件开发与数据管理中,正确排序版本号对软件更新及数据分析至关重要。因MySQL默认按字符串排序版本号,可能出现'1.20.0'在'1.10.0'之前的不合理情况。解决办法是将版本号各部分转换为整数后排序。例如,使用`SUBSTRING_INDEX`和`CAST`函数从`software`表的`version`字段提取并转换版本号,再按这些整数排序。这种方法可确保版本号按逻辑正确排序,适用于'major.minor.patch'格式的版本号。对于更复杂格式,需调整处理逻辑。掌握此技巧可有效应对版本号排序需求。
    113 3
    |
    2月前
    |
    关系型数据库 MySQL 数据安全/隐私保护
    【MySQL】手把手教你MySQL各版本忘记密码如何处理
    【MySQL】手把手教你MySQL各版本忘记密码如何处理
    |
    3月前
    |
    关系型数据库 MySQL 数据库

    热门文章

    最新文章