随着硬件和软件的发展,数据库的瓶颈也发生了转移。很多老的问题可能消失了,也有新的问题出来了。
以前是CPU和内存受到限制。十多年前,4核服务器是“高端”服务器,作为DBA,我最担心的是管理可用资源。Oracle尝试使用RAC架构为单个数据库从多个主机集中CPU和内存是解决这个问题的一个很好的尝试。
然后是存储速度限制的日子。它是由多核多线程处理器变得普遍引发的,以及内存大小和总线速度的增加。企业试图通过复杂的SAN驱动器、带有缓存的专用存储等来解决它。但它已经存在很多年了,即使是现在企业开始越来越多地转向NVMe驱动器。
最近我们开始观察到一个新的瓶颈,它正在成为许多数据库用户的痛点。随着单主机服务器能力的提高,它开始处理大量事务。有些系统可以在几分钟内生成数千个WAL文件,并且有一些案例,其中WAL归档到更便宜、更慢的磁盘系统无法赶上WAL生成。许多组织更喜欢在低带宽网络上存储WAL档案,更增加了复杂性。(Postgres Archiving 有一个固有的问题,如果它落后,它往往会滞后更多,因为归档过程需要在.ready 文件中搜索。这里不讨论)
在本文中,我想提请你注意一个事实,如果还没有压缩 WAL的话,WAL压缩是很容易实现的。以及一个用于监控归档gap的查询。
归档前压缩WAL的需求与日俱增。幸运的是,大多数PostgreSQL备份工具(如pgbackrest/wal-g等)已经实现了。archive_command调用这些工具,为用户静默存档。
例如,在pg_backrest 中,我们可以指定archive_command,它在后台使用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';
如果我们没有使用任何备份工具,而想压缩归档呢?
我们仍然可以使用Linux提供的如gzip、bzip等进行压缩。比如:
alter system set archive_command = '/usr/bin/gzip -c %p > /home/postgres/archived/%f.gz';
然而,7za是所有WAL压缩选项中最有趣的,它尽可能快地提供最高压缩比。可以显式安装7za,它是来自7zip包的一部分。
在centos7上:
sudo yum install epel-releasesudo yum install p7zip
在ubuntu上:
sudo apt install p7zip-full
安装后就可以使用了:
postgres=# alter system set archive_command = '7za a -bd -mx2 -bsp0 -bso0 /home/postgres/archived/%f.7z %p'; ALTER SYSTEM
在我的测试系统中,可以看到小于200kb的归档WAL文件。大小根据WAL的内容而有所不同,这取决于数据库上的事务类型。
-rw-------. 1 postgres postgres 197K Feb 6 12:13 0000000100000000000000AA.7z -rw-------. 1 postgres postgres 197K Feb 6 12:13 0000000100000000000000AB.7z -rw-------. 1 postgres postgres 198K Feb 6 12:13 0000000100000000000000AC.7z -rw-------. 1 postgres postgres 196K Feb 6 12:13 0000000100000000000000AD.7z -rw-------. 1 postgres postgres 197K Feb 6 12:13 0000000100000000000000AE.7z
将16MB文件压缩到千字节范围内肯定会节省网络带宽和存储空间,同时解决归档落后的问题。
归档和获得最高压缩只是其中的一部分,但我们也应该能够在需要时恢复它们。备份工具提供自己的恢复命令选项。例如,pgbackrest可以使用 archive-get :
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
从postgresql12开始,可以使用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文件名找出gap有点棘手。我用来找出WAL归档滞后的示例查询是这样的:
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具有相同的时间线,以便此查询能够正常工作,这是常见的情况。我们很少会遇到与生产中不同的情况。因此,在监视PostgreSQL服务器的WAL归档时,此查询可能会有很好的帮助。