您现在的位置是:首页 >学无止境 >PostgreSQL实战之增量备份网站首页学无止境

PostgreSQL实战之增量备份

auspicious航 2023-07-13 16:00:02
简介PostgreSQL实战之增量备份

目录

PostgreSQL实战之增量备份

1 开启WAL 归档

2 创建基础备份

2.1 使用低级API创建基础备份


PostgreSQL实战之增量备份

        PostgreSQL在做写入操作时,对数据文件做的任何修改信息,首先会写入WAL日志(预写日志),然后才会对数据文件做物理修改。当数据库服务器掉电或意外宕机,PostgreSQL在启动时会首先读取WAL日志,对数据文件进行恢复。因此,从理论上讲,如果我们有一个数据库的基础备份(也称为全备),再配合WAL日志,是可以将数据库恢复到任意时间点的。但是WAL日志的文件个数并不是无限增长的,当增长到第N个(理论上N=2×checkpoint_segment+1)文件时,PostgreSQL会重复利用已生成的WAL日志文件。例如,当前数据库中已产生256个WAL日志,就会开始重复利用第1个、第2个或第3个产生的WAL日志文件,WAL日志将会被改写。这时就会产生问题:此时如果我们想恢复到第1个WAL日志的状态时,因为WAL日志已被改写,注定是无法恢复了。因此我们要根据自身的业务情况,定时对WAL日志进行归档。
        但是新的问题又产生了:当我们根据很早以前的基础备份和WAL的归档日志进行恢复时,因为需要做的回滚操作非常多,导致恢复时间很长,这也会严重影响到生产性能。为了解决这个问题,我们可以通过定期对数据库做基础备份,再配合WAL的归档日志,就可以在较短的时间将数据库恢复。具体到定期备份的周期,需要根据自身的业务需求制定合理的备份策略,在数据完整性和恢复所需时间之间达到最佳的平衡点。例如第一周的星期一,DBA对数据库做了一次全备,生产在持续进行,本周没有发生故障;第二周的星期一,DBA对数据库又做了一次全备,直到星期五数据库都工作正常,但在星期六和星期天,数据发生了异常,DBA需要将数据恢复到星期五的状态,这时就可以通过第一周星期一或第二周星期一的全备文件配合归档日志进行恢复。显然,如果通过第一周星期一的全备文件进行恢复,恢复时间会较长,通过第二周星期一的全备文件进行恢复则会快很多。

1 开启WAL 归档

(1)创建归档目录
        我们在创建数据目录的同时,除了创建data目录,还创建了backups,scripts,archive_wals这几个目录,如下所示:

[root@pghost1 ~]$ mkdir -p /pgdata/10/{data,backups,scripts,archive_wals}
[root@pghost1 ~]$ chown -R postgres.postgres /pgdata/10

  其中,data目录是我们数据库的数据目录,backups目录则可以用来存放基础备份,scripts目录可以用来存放一些任务脚本,archive_wals目录自然用来存放归档了。归档目录也可以是挂载的NFS目录或者磁带,注意这个目录的属主为postgres 用户即可。
(2)修改wal_level参数
        wal_level参数可选的值有minimal、replica和 logical,从minimal到replica再到logical级别,WAL的级别依次增高,在WAL中包含的信息也越多。由于minimal这一级别的WAL不包含从基本的备份和WAL日志中重建数据的足够信息,在minimal模式下无法开启 archive_mode,所以开启 WAL归档wal_level至少设置为replica,如下所示:

mydb=# ALTER SYSTEM SET wal_level = 'replica';
ALTER SYSTEM

(3)修改archive_mode参数
        archive_mode参数可选的值有on、off和 always,默认值为off,开启归档需要修改为on,如下所示:

mydb=# ALTER SYSTEM SET archive_mode = 'on ';
ALTER SYSTEM

修改此参数需要重新启动数据库使之生效。
(4)修改archive_command参数
        archive_command参数的默认值是个空字符串,它的值可以是一条shell 命令或者一个复杂的shell脚本。在archive_command的shell 命令或脚本中可以用“%p”表示将要归档的WAL文件的包含完整路径信息的文件名,用“%f”代表不包含路径信息的WAL文件的文件名。
一个最简单的archive_command的例子是:

archive_command = 'cp%p/pgdata/10/archive_wals/%f"

  修改wal_level和archive_mode参数都需要重新启动数据库才可以生效,修改archive_command不需要重启,只需要reload即可。但有一点需要注意,当开启了归档,应该注意archive_command设定的归档命令是否成功执行,如果归档命令未成功执行,它会周期性地重试,在此期间已有的WAL文件将不会被复用,新产生的WAL文件会不断占用pg_wal的磁盘空间,直到pg_wal所在的文件系统被占满后数据库关闭。由于wal_level和 archive_mode参数都需要重新启动数据库才可以生效,所以在安装结束,启动数据库之前,可以先将这些参数开启,将archive_command的值设置为永远为真的值,例如/bin/true,当需要真正开启归档时,只需要修改archive_command 的值,reload即可,而不需要由于参数调整而重启数据库。
如果考虑到归档占用较多的磁盘空间,配置归档时可以将WAL压缩之后再归档,可以用gzip、bzip2或1z4等压缩工具进行压缩。当前的例子中,把 archive_command设置为在pg_wal目录使用1z4压缩WAL,并将压缩后的文件归档到/pgdata/10/archive_wals/目录:
 

mydb=#  ALTER SYSTEM SET archive_command = '/usr/bin/1z4 -q -z %p /pgdata/10/archive_wals/%f.1z4 ';

ALTER SYSTEM

mydb=# SELECT pg_reload_conf ();
pg_reload_conf
----------------
t
(l row)

mydb=# show archive_command ;
archive_command
---------------------------
/usr/bin/lz4 -q-z %p /pgdata/10/archive_wals/%f.lz4
(1 row)

2 创建基础备份

        在较低的PostgreSQL版本中,使用pg_start_backup和pg_stop_backup这些低级API创建基础备份,从PostgreSQL9.1版开始有了pg_basebackup实用程序,使得创建基础备份更便捷,pg_basebackup用普通文件或创建tar包的方式进行基础备份,它在内部也是使用pg_start_backup和pg_stop_backup低级命令。如果希望用更灵活的方式创建基础备份,例如希望通过rsync、 scp等命令创建基础备份,依然可以使用低级API的方式。同时,使用低级API创建基础备份也是理解PIRT的关键和基础。


2.1 使用低级API创建基础备份

        使用低级API创建基础备份主要有三个步骤:执行pg_start_backup命令开始执行备份,使用命令创建数据目录的副本和执行pg_stop_backup命令结束备份。
步骤1 执行pg_start_backup命令。
pg_start_backup 的作用是创建一个基础备份的准备,这些准备工作包括:
1)判断WAL归档是否已经开启。
如果WAL归档没有开启,备份依然会进行,但在备份结束后会显示提醒信息:
NOTICE: WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup
意思是说WAL归档未启用,必须确保通过其他方式复制所有必需的WAL以完成备份。复制所有必需的WAL听上去似乎可行,但是对于一个较大的、写入频繁的生产环境数据库来说实际是不现实的,等pg_start_backup命令结束了再去复制必需的WAL,可能那些WAL文件已经被重用了,所以务必按照2.1节的内容提前开启归档。
2)强制进入全页写模式。
判断当前配置是否为全页写模式,当full_page_writes 的值为off时表示关闭了全页写模式,如果当前配置中 full_page_writes 的值为off,则强制更改,full_page_writes的值为on,进入全页写模式;
3)创建一个检查点。
4)排他基础备份的情况下还会创建backup_label文件,一个backup_label文件包含以下五项:

  • START WAL LOCATION:25/2B002118 (file 00000001000000250000002B);
  • CHECKPOINT LOCATION:记录由命令创建的检查点的LSN位置;
  • BACKUP METHOD:做基础备份的方法,值为pg_start_backup或是pg_basebackup,如果只是配置流复制,BACK up METHOD的值是streamed;
  • BACKUP FROM:备份来源,指是从master或standby做的基础备份;START TIME:执行pg_start_backup 的时间戳;
  • LABEL:在pg_start_backup中指定的标签。

系统管理函数pg_start_backup 的定义如下:

pg_start_backup(label text [, fast boolean [, exclusive boolean ]])

        该函数有一个必需的参数和两个可选参数,label参数是用户定义的备份标签字符串,一般使用备份文件名加日期作为备份标签。执行pg_start_backup会立即开始一个CHECKPOINT操作,fast参数默认值是false,表示是否尽快开始备份。exclusive参数决定pg_start_backup是否开始一次排他基础备份,也就是是否允许其他并发的备份同时进行,由于排他基础备份已经被废弃,最终将被去除,所以通常设置为false。在系统管理函数中,有一个pg_is_in_backup函数,不能想当然地认为它是用于判断当前数据库是否有一个备份在进行,它只是检查是否在执行一个排他的备份,也就是是否有exclusive参数设置为TRUE的备份,不能用它检查是否有非排他的备份在进行。

步骤2 使用命令创建数据目录的副本。
使用rsync、tar、cp、scp等命令都可以创建数据目录的副本。在创建过程中可以排除pg_wal和 pg_replslot目录、postmaster.opts文件、postmaster.pid文件,这些目录和文件对恢复并没有帮助。

步骤3 执行pg_stop_backup命令。
在执行pg_stop_backup命令时,进行五个操作来结束备份:

  • 如果在执行pg_start_backup命令时,full-page-writes 的值曾被强制修改,则恢复到执行pg-stop-backup命令之前的值。
  • 写一个备份结束的XLOG记录。切换WAL段文件。
  • 创建一个备份历史文件,该文件包含backup_label文件的内容以及执行pg_stop_backup的时间截。
  • 删除backup_label文件,backup_label文件对于从基本备份进行恢复是必需的,一旦进行复制,原始数据库集群中就不需要了该文件了。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。