[翻译]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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
    目录
    相关文章
    |
    13天前
    |
    关系型数据库 MySQL
    mysql 5.7.x版本查看某张表、库的大小 思路方案说明
    mysql 5.7.x版本查看某张表、库的大小 思路方案说明
    39 5
    |
    18天前
    |
    关系型数据库 MySQL
    mysql 5.7.x版本查看某张表、库的大小 思路方案说明
    mysql 5.7.x版本查看某张表、库的大小 思路方案说明
    28 1
    |
    1月前
    |
    Java 关系型数据库 MySQL
    【编程基础知识】Eclipse连接MySQL 8.0时的JDK版本和驱动问题全解析
    本文详细解析了在使用Eclipse连接MySQL 8.0时常见的JDK版本不兼容、驱动类错误和时区设置问题,并提供了清晰的解决方案。通过正确配置JDK版本、选择合适的驱动类和设置时区,确保Java应用能够顺利连接MySQL 8.0。
    133 1
    |
    1月前
    |
    SQL JSON 关系型数据库
    MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
    【10月更文挑战第3天】MySQL是一个广泛使用的开源关系型数据库管理系统,它有许多不同的版本
    133 5
    |
    18天前
    |
    SQL 关系型数据库 MySQL
    MySql5.6版本开启慢SQL功能-本次采用永久生效方式
    MySql5.6版本开启慢SQL功能-本次采用永久生效方式
    33 0
    |
    2月前
    |
    关系型数据库 MySQL 数据库
    MySQL高级篇——MVCC多版本并发控制
    什么是MVCC、快照读与当前读、隐藏字段、Undo Log版本链、ReadView、举例说明、InnoDB 解决幻读问题
    MySQL高级篇——MVCC多版本并发控制
    |
    2月前
    |
    关系型数据库 分布式数据库 数据库
    开源云原生数据库PolarDB PostgreSQL 15兼容版本正式发布
    PolarDB进行了深度的内核优化,从而实现以更低的成本提供商业数据库的性能。
    |
    2月前
    |
    监控 关系型数据库 MySQL
    如何升级mysql的版本
    如何升级mysql的版本
    463 2
    |
    2月前
    |
    存储 监控 关系型数据库
    如何升级MySQL版本?
    如何升级MySQL版本?
    132 2
    |
    3月前
    |
    关系型数据库 MySQL Shell
    MySQL数据库一键安装脚本,适合任何版本
    MySQL数据库一键安装脚本,适合任何版本
    82 2