压缩 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-release
sudo 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)::int
as diff from pg_stat_archiver;
注意:当前的WAL和要归档的WAL都具有相同的时间线,以便此查询能够执行,这是常见的情况。我们很少会遇到与生产中不同的情况。
本文翻译自:https://www.percona.com/blog/2020/02/13/compression-of-postgresql-wal-archives-becoming-more-important/