vlambda博客
学习文章列表

压缩 PostgreSQL WAL 归档日志变得越来越重要

随着硬件和软件的发展,数据库系统中的瓶颈也随之转移。许多旧问题可能会消失,新问题会出现。

之前的限制

十多年前CPU和内存是一个限制,四核服务器是“高端”服务器,作为一名DBA,可能最担心的是管理可用资源。Oracle尝试使用RAC架构将多台主机上的CPU和内存集中到一个数据库中,这是一个很好的办法。

接下来是存储速度受限的日子。它是由多核的出现引发的,多线程处理器变得越来越普遍,同时内存大小和总线速度也在增加。企业试图用复杂的SAN驱动器、带缓存的专用存储设备等来解决这个问题,但它已经存在了很多年,甚至现在企业开始越来越多地转向NVMe驱动器。

最近又出现一个新的瓶颈,这个瓶颈正成为许多数据库用户的痛点。随着单主机服务器性能的提高,它开始处理大量事务。有一些系统可以在几分钟内生成数千个WAL文件,有些人反馈,WAL归档到一个更便宜、速度较慢的磁盘系统无法赶上WAL的生成速度。为了增加复杂性,许多公司更喜欢在低带宽网络上存储WAL档案。(Postgres归档中存在一个固有的问题,如果它落后了,它往往会滞后更多,因为归档过程需要在.ready文件中进行搜索。这里不讨论。)

压缩WALs是很容易实现的,并且可以通过查询来监视归档前后的差距。

压缩PostgreSQL WALs 归档日志

压缩wal归档日志的需求与日俱增。幸运的是,大多数PostgreSQL备份工具,如pgbackrest/wal-g等,已经处理好了。

通过archive_command 调用这些工具,为用户提供默认的压缩归档。

比如:我们可以指定archive_command调用pgbackrest工具,实际后台使用的是gzip 压缩。

ALTER SYSTEM SET archive_command = 'pgbackrest --stanza=mystanza archive-push %p';

或者我们指定其调用WAL-G:(这将使用lz4压缩)

ALTER SYSTEM SET archive_command = 'WALG_FILE_PREFIX=/path/to/archive /usr/local/bin/wal-g wal-push %p';

但是如果我们不使用任何特定的备份工具来进行WAL压缩归档呢?我们仍然可以使用诸如gzip或bzip等Linux工具压缩WALs。默认情况下,gzip在大多数Linux安装中都是可用的,因此很容易配置它。

alter system set archive_command = '/usr/bin/gzip -c %p > /home/postgres/archived/%f.gz';

然而,在WAL的所有压缩选项中,可能7za压缩是你最感兴趣的,它尽可能快地提供最高的压缩,这对一个大量生成WAL日志系统来说非常重要。您可能必须显式安装7za。

在CentOS 7上:

sudo yum install epel-releasesudo yum install p7zip

在Ubuntu 上:

sudo apt install p7zip-full

安装好7za后,我们就可以在这样指定archive_command 命令:

postgres=# alter system set archive_command = '7za a -bd -mx2 -bsp0 -bso0 /home/postgres/archived/%f.7z %p';ALTER SYSTEM


通过测试7za,发现有小于200kb的归档WAL文件。大小可以根据WALs的内容而变化,这取决于数据库中事务的类型。

-rw-------. 1 postgres postgres <strong>197K</strong> Feb 6 12:13 0000000100000000000000AA.7z-rw-------. 1 postgres postgres <strong>197K</strong> Feb 6 12:13 0000000100000000000000AB.7z-rw-------. 1 postgres postgres <strong>198K</strong> Feb 6 12:13 0000000100000000000000AC.7z-rw-------. 1 postgres postgres <strong>196K</strong> Feb 6 12:13 0000000100000000000000AD.7z-rw-------. 1 postgres postgres <strong>197K</strong> Feb 6 12:13 0000000100000000000000AE.7z

将16MB的文件压缩到千字节级别肯定会节省网络带宽和存储空间,同时解决归档落后的问题。

从压缩的WALs归档日志恢复数据

通过归档并获得很高的压缩只是其中一方面,但我们也应该能够在需要时恢复它们。备份工具提供了自己的还原命令选项例如,pgbackrest 可以使用:

restore_command = 'pgbackrest --stanza=demo archive-get %f "%p"'

WAL-G提供Wal-fetch实现还原。

如果您选择使用gzip进行手动归档压缩,我们可以在恢复命令restore_command中使用gunzip实用程序,如下所示:

gunzip -c /home/postgres/archived/%f.gz > %p

如果已经开始使用PostgreSQL 12,则可以使用ALTER SYSTEM设置此参数:

postgres=# alter system set restore_command = 'gunzip -c /home/postgres/archived/%f.gz > %p';ALTER SYSTEM

或者

对于上面的7za压缩,您可以使用以下恢复命令:

postgres=# alter system set restore_command = '7za x -so /home/postgres/archived/%f.7z > %p';ALTER SYSTEM

注意:不像archive_command更改 ,restore_command 更改要求重新启动备用standby数据库。

监控归档进程

当前的WAL归档可以从pg_stat_archiver status获得,但是使用WAL文件名找出差距有点棘手。下面是用来查找WAL archive滞后的一个示例查询:

select pg_walfile_name(pg_current_wal_lsn()),last_archived_wal,last_failed_wal,('x'||substring(pg_walfile_name(pg_current_wal_lsn()),9,8))::bit(32)::int*256 +('x'||substring(pg_walfile_name(pg_current_wal_lsn()),17))::bit(32)::int -('x'||substring(last_archived_wal,9,8))::bit(32)::int*256 -('x'||substring(last_archived_wal,17))::bit(32)::intas diff from pg_stat_archiver;

注意:当前的WAL和要归档的WAL都具有相同的时间线,以便此查询能够执行,这是常见的情况。我们很少会遇到与生产中不同的情况。

本文翻译自:https://www.percona.com/blog/2020/02/13/compression-of-postgresql-wal-archives-becoming-more-important/