pg_rman 简介

pg_rman是一款专门为PostgreSQL数据库打造的优秀开源备份软件,其使用的思路类似Oracle的rman。此软件先前托管在sourceforge,现已移到了github上:
pg_rman的特点如下:

  • 使用简单,一个命令即可完成备份和恢复

  • 支持在线全备、增量备份、WAL日志的备份

  • 支持备份压缩,通过gzip工具实现压缩

  • 自动备份维护、自动删除过期的WAL备份文件

  • 支持备份验证,通过使用文件的大小和数据块CRC实现校验

  • 恢复期间无事务丢失,支持基于PITR的配置文件生成器

pg_rman最大的亮点就是实现了增量备份,注意不是基于WAL日志的增量备份,是基于上次全量备份之后发生的变化数据块的增量备份

pg_rman 部署

https://github.com/ossc-db/pg_rman/releases/

下载安装包,这里安装源码编译安装

unzip pg_rman-1.3.17.zip
cd pg_rman-1.3.17
vi .base_profie

参数说明

[postgres@lyp pg_rman-master]$ pg_rman --help
pg_rman manage backup/recovery of PostgreSQL database.

Usage:
  pg_rman OPTION init         				#初始化
  pg_rman OPTION backup								#备份
  pg_rman OPTION restore							#恢复
  pg_rman OPTION show [DATE]					#查看历史备份
  pg_rman OPTION show detail [DATE]		
  pg_rman OPTION validate [DATE]			#验证备份
  pg_rman OPTION delete DATE					#删除备份
  pg_rman OPTION purge								#从备份目录中删除已实际的备份文件

Common Options:
  -D, --pgdata=PATH         location of the database storage area
  -A, --arclog-path=PATH    location of archive WAL storage area
  -S, --srvlog-path=PATH    location of server log storage area
  -B, --backup-path=PATH    #备份路径
  -c, --check               show what would have been done
  -v, --verbose             show what detail messages
  -P, --progress            show progress of processed files

Backup options:
  -b, --backup-mode=MODE    #备份类型,在增量备份之前要有全量full, incremental, or archive
  -s, --with-serverlog      also backup server log files
  -Z, --compress-data       compress data backup with zlib
  -C, --smooth-checkpoint   do smooth checkpoint before backup
  -F, --full-backup-on-error   switch to full backup mode
                               if pg_rman cannot find validate full backup
                               on current timeline
      NOTE: this option is only used in --backup-mode=incremental or archive.
  --keep-data-generations=NUM keep NUM generations of full data backup
  --keep-data-days=NUM        keep enough data backup to recover to N days ago
  --keep-arclog-files=NUM   keep NUM of archived WAL
  --keep-arclog-days=DAY    keep archived WAL modified in DAY days
  --keep-srvlog-files=NUM   keep NUM of serverlogs
  --keep-srvlog-days=DAY    keep serverlog modified in DAY days
  --standby-host=HOSTNAME   standby host when taking backup from standby
  --standby-port=PORT       standby port when taking backup from standby

Restore options:
  --recovery-target-time    time stamp up to which recovery will proceed
  --recovery-target-xid     transaction ID up to which recovery will proceed
  --recovery-target-inclusive whether we stop just after the recovery target
  --recovery-target-timeline  recovering into a particular timeline
  --recovery-target-action    action the server should take once the recovery target is reached
  --hard-copy                 copying archivelog not symbolic link

Catalog options:
  -a, --show-all            #查看所有被删除的备份

Delete options:
  -f, --force               #强制删除,当全备只有一个时,不允许删除,该参数可以强制删除

Connection options:
  -d, --dbname=DBNAME       database to connect
  -h, --host=HOSTNAME       database server host or socket directory
  -p, --port=PORT           database server port
  -U, --username=USERNAME   user name to connect as
  -w, --no-password         never prompt for password
  -W, --password            force password prompt

Generic options:
  -q, --quiet               don't show any INFO or DEBUG messages
  --debug                   show DEBUG messages
  --help                    show this help, then exit
  --version                 output version information, then exit

1. 介绍

对于刚接触pg_rman的用户来说会有一些迷茫,使用上常常遇到一些问题,原因是对pg_rman的备份原理不是很清楚,所以这里把pg_rman的备份原理给介绍一下:

  • pg_rman不是使用流复制协议进行拷份的,而是使用文件拷贝,即先在主库上执行pg_start_backup()函数,然后拷贝整个数据库的数据目录,最后再执行 pg_stop_backup()函数来结束备份。

  • 所以pg_rman必须和数据库节点跑在一起。否则可以想的到是是无法拷贝数据库的数据文件,从而无法备份。所以通常备份时,需要使用NAS等NFS共享方法把备份机的文件系统mount到数据库机器上。

  • pg_rman可以在standby节点上做全库的备份,但需要通过网络连接到主库上执行pg_start_backup和pg_stop_backup。

  • pg_rman需要主库打开了归档才能更好的备份,所以需要在postgresql.conf中打开归档,以便让pg_rman判断出数据库的归档目录在哪里。pg_rman主要是读取postgresql.conf文件中archive_command参数的值。

  • pg_rman还能备份PostgreSQL数据库的一般程序日志,即pg_log目录的日志文件。所以pg_rman会读取postgresql.conf中的log_directory参数以确定这些日志在哪个目录下。当然这些程序日志通常不是太重要,可以不备份。

注意:因为pg_rman是用postgresql.conf中读取archive_command和log_directory参数的值,如果你在PostgreSQL的配置文件使用了include其他文件或者配置在postgresql.auto.conf中,pg_rman读取到的这两个值将不准确,会导致一些问题,所以建议你仅仅把参数配置在postgresql.conf中,而不要使用其他配置文件

这里再说点题外话,pg_rman需要主库打开了归档才能更好的备份,这是有点不太方便。虽然在生产上的Oracle数据库中都是打开归档的,但在PostgreSQL中通常是可以不用打开归档的,原因是PostgreSQL中的归档与Oracle中的归档有些不一样。PostgreSQL中没有严格区分在线redo日志和归档,在PostgreSQL中每写满一个WAL日志后,如果打开了归档,就会调用参数“archive_command”指定的命令,此通常此命令就是把此WAL日志拷贝到另一个目录中,其实就是相当于备份到其它目录中。而PostgreSQL中可以通过流复制更实时接收WAL日志,所以不一定要用归档的模式来备份WAL日志。所以这也是pg_rman没有使用流复制导致在备份上产生的不太方便的地方。

pg_rman与rman一样都是把数据库备份到一个统一的备份仓库中,这个备份仓库中可以有多个全备份、多个增量备份,通过pg_rman的备份可以方便的看到这个备份仓库中有哪些备份,在后面的内容中会详细讲解这一些部分,这里主要是为了让大家知道pg_rman能做什么。一个备份仓库实际上就是一个目录,但pg_rman在这个目录中存有每次备份的信息,如某一次备份是全量备份还是增量份份,备份的结果是占用了多少G的空间,备份开始时间和结束时间等等信息。

pg_rman不能完成跨机器的备份,也就是备份的空间需要在与要备份的数据库在同一台机器上,同时pg_rman没有WEB管理界面。如果想实现这些功能,可以使用CLup软件, 具体见 CLup数据备份

通过上面的介绍,想必大家对pg_rman有了一个初步的认识,如果想有更深的认识,就需要看下面的更详细的内容了。

安装

pg_rman官方已为大家准备了方便的rpm安装包,在Redhat6.X和Redhat7.X(当然CentOS6.X和Cent7.X是一样)可以直接使用此rpm包,rpm包的下载路径为:

安装之前最好使用PostgreSQL官方的rpm安装好了PostgreSQL数据库软件,当安装pg_rman时,会安装到相应PostgreSQL软件的相应目录中去。

安装过程很简单,直接用rpm命令进行安装即可,如下所示:

rpm -ivh pg_rman-1.3.7-1.pg10.rhel7.x86_64.rpm

2. 初次使用

使用之前,当然要先有一个PostgreSQL,笔者通常喜欢系统原先的操作系统用户postgres删除掉,原因这个用户的home目录不是在/home/postgres目录下,而是在/var/目录下,笔者不喜欢。

笔者的建用户命令为:

groupadd -g 701 postgres
useradd -m -g postgres -u 701 postgres

有人问为何gid和uid为701,因为在笔者的机器上Oracle的uid使用的是501,MySQL的uid使用的是601,所以PostgreSQL使用的是701。

笔者通常在postgres用户的.bash_profile做下面的配置:

export PGDATA=~/pgdata
export PATH=/usr/pgsql-10/bin:$PATH
export LD_LIBRARY_PATH=/usr/pgsql-10/lib:$LD_LIBRARY_PATH
export PGHOST=/tmp
export LANG=en_US.UTF-8

为何要设置export PGHOST=/tmp呢?原因是通过rpm包安装的PostgreSQL,会把socket doamin文件放到/var目录下,让psql不带任何命令行参数时无法直接登录数据库。当然在我的postgresql.conf中也有下面的配置:

unix_socket_directories = '/tmp'

注意原先的配置是unix_socket_directories = '/var/run/postgresql, /tmp,把“/var/run/postgresql”删除掉了。

在使用pg_rman之前,要打开归档,在笔者的postgresql.conf中的打开归档的配置为:

archive_mode = on
archive_command = 'test ! -f /home/postgres/pgarch/%f && cp %p /home/postgres/pgarch/%f'

整个pg_rman就是一个命令行的工具,此程序的名称就是“pg_rman”,

[postgres@pg01 ~]$ which pg_rman
/usr/pgsql-10/bin/pg_rman

[postgres@pg01 ~]$ pg_rman --help
pg_rman manage backup/recovery of PostgreSQL database.

Usage:
  pg_rman OPTION init
  pg_rman OPTION backup
  pg_rman OPTION restore
  pg_rman OPTION show [DATE]
  pg_rman OPTION show detail [DATE]
  pg_rman OPTION validate [DATE]
  pg_rman OPTION delete DATE
  pg_rman OPTION purge
  ...
  ...
  ...

使用pg_rman之前需要先初始化一个备份仓库,所谓的备份仓库就是一个路径,当然我们需要保证这个路径下的文件系统有足够的空间。

可以设置一个环境变量BACKUP_PATH指向这个备份仓库的路径,如下所示:

export BACKUP_PATH=~/backups

当然也可以不设置BACKUP_PATH环境变量。如果此环境变量没有设置不指定,每次就需要用“-B”参数来指定这个路径,所有稍有点麻烦,建议还是设置上比较好,同样也设置在.bash_profile文件中。

在备份之前需要初使化一个备份仓库,用命令pg_rman init完成备份仓库的初始化,如下所示:

[postgres@pg01 ~]$ pg_rman init -B ~/backups
INFO: ARCLOG_PATH is set to '/home/postgres/pgarch'
INFO: SRVLOG_PATH is set to '/home/postgres/pgdata/log'

当然因为我们设置了环境变量export BACKUP_PATH=~/backups,所以上面的命令中不指定“-B”参数也是可以的。

初始化备份仓库实际上是在备份仓库下面建一些目录和元数据文件:

[postgres@pg01 ~]$ ll ~/backups/
total 8
drwx------ 4 postgres postgres 34 Nov 23 15:02 backup
-rw-rw-r-- 1 postgres postgres 77 Nov 23 15:02 pg_rman.ini
-rw-rw-r-- 1 postgres postgres 40 Nov 23 15:02 system_identifier
drwx------ 2 postgres postgres 6 Nov 23 15:02 timeline_history

这些元数据文件包括备份的配置文件“pg_rman.ini”、数据库的systemid、时间线文件历史等等,当然我们最需要关心的是配置文件“pg_rman.ini”,目前此文件的内容如下:

[postgres@pg01 ~]$ cat ~/backups/pg_rman.ini
ARCLOG_PATH='/home/postgres/pgarch'
SRVLOG_PATH='/home/postgres/pgdata/log'

下面我们就可以执行一次全备份了:

[postgres@pg01 ~]$ pg_rman backup --backup-mode=full
INFO: copying database files
INFO: copying archived WAL files
INFO: backup complete
INFO: Please execute 'pg_rman validate' to verify the files are correctly copied.

我们用pgbench对数据库产生一些变更,然后再做一次增量备份:
pgbench做一些变更:

[postgres@pg01 pgdata]$ pgbench -i
creating tables...
100000 of 100000 tuples (100%) done (elapsed 0.16 s, remaining 0.00 s)
vacuum...
set primary keys...
done.

执行增量备份的命令:

[postgres@pg01 ~]$ pg_rman backup --backup-mode=incremental --with-serverlog -B ~/backups
INFO: copying database files
ERROR: cannot take an incremental backup
DETAIL: There is no validated full backup with current timeline.

哎呀,增量备份怎么不成功,看日志信息“There is no validated full backup”是没有有效的全量备份,前面才做完全量备份怎么没有有效的全量备份呢?

原来pg_rman做完备份后,需要再用命令pg_rman validate校验备份,检验备份没有问题之后,这个备份才成为有效的备份,在前面的全备份执行完后也有这方面的提示INFO: Please execute 'pg_rman validate' to verify the files are correctly copied.

这时我们可以用pg_rman show查看备份情况,看看当前备份的状态是多少:

[postgres@pg01 ~]$ pg_rman show
=====================================================================
 StartTime EndTime Mode Size TLI Status
=====================================================================
2018-11-23 17:45:36 2018-11-23 17:45:36 INCR 0B 1 ERROR
2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 DONE

可以看到我们的全量备份的状态目前是DONE的,这表示备份完成了,还没有校验,我们执行校验命令:

[postgres@pg01 ~]$ pg_rman validate
INFO: validate: "2018-11-23 17:45:07" backup and archive log files by CRC
INFO: backup "2018-11-23 17:45:07" is valid

然后用pg_rman show查看状态:

[postgres@pg01 ~]$ pg_rman show
=====================================================================
 StartTime EndTime Mode Size TLI Status
=====================================================================
2018-11-23 17:45:36 2018-11-23 17:45:36 INCR 0B 1 ERROR
2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

这时可以看到那个全量备份的状态从DONE变成了OK,这时就可以做增量备份了:

[postgres@pg01 ~]$ pg_rman backup --backup-mode=incremental --with-serverlog
INFO: copying database files
INFO: copying archived WAL files
INFO: copying server log files
INFO: backup complete
INFO: Please execute 'pg_rman validate' to verify the files are correctly copied.
[postgres@pg01 ~]$ pg_rman show
=====================================================================
 StartTime EndTime Mode Size TLI Status
=====================================================================
2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 DONE
2018-11-23 17:45:36 2018-11-23 17:45:36 INCR 0B 1 ERROR
2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

每次备份完成,不要忘了做pg_rman validate:

[postgres@pg01 ~]$ pg_rman validate
INFO: validate: "2018-11-23 17:47:44" backup, archive log files and server log files by CRC
INFO: backup "2018-11-23 17:47:44" is valid
[postgres@pg01 ~]$ pg_rman show
=====================================================================
 StartTime EndTime Mode Size TLI Status
=====================================================================
2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 OK
2018-11-23 17:45:36 2018-11-23 17:45:36 INCR 0B 1 ERROR
2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

我们也可以用pg_rman delete把之前的备份删除旧:

[postgres@pg01 ~]$ pg_rman delete '2018-11-23 17:45:36'
INFO: delete the backup with start time: "2018-11-23 17:45:36"
WARNING: cannot delete backup with start time "2018-11-23 17:45:07"
DETAIL: This is the latest full backup necessary for successful recovery.
[postgres@pg01 ~]$ pg_rman show
=====================================================================
 StartTime EndTime Mode Size TLI Status
=====================================================================
2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 OK
2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

注意:删除备份时指定的时间点“2018-11-23 17:45:36”,并不是表示把这个时间点的备份删除掉,而是删除掉不需要的备份,让剩下的备份集能恢复这个时间点,一定要记住!!!,所以上面的命令的意思是在执行完删除操作之后,保证剩下的备份集能够恢复到“2018-11-23 17:45:36”这个时间点。

实际上,pg_rman delete虽然把备份删除掉了,但是一些备份信息仍然遗留在元数据中,这些信息用pg_rman show -a还能看到:

[postgres@pg01 backups]$ pg_rman show -a ===================================================================== StartTime EndTime Mode Size TLI Status ===================================================================== 2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 OK 2018-11-23 17:45:36 2018-11-23 17:45:36 INCR 0B 1 DELETED 2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

这时需要用pg_rman purge命令清除掉已删除的备份的元信息:
[postgres@pg01 backups]$ pg_rman purge INFO: DELETED backup "2018-11-23 17:45:36" is purged [postgres@pg01 backups]$ pg_rman show -a ===================================================================== StartTime EndTime Mode Size TLI Status ===================================================================== 2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 OK 2018-11-23 17:45:07 2018-11-23 17:45:09 FULL 50MB 1 OK

pg_rman.ini 文件

pg_rman初始化之后会在备份目录中产生 pg_rman.ini 文件,基于该文件可以制定备份策略,在进行备份操作时会自动检查

KEEP_ARCLOG_FILES = 10      --保存归档文件个数
KEEP_SRVLOG_FILES = 10			--保存日志文件个数
KEEP_DATA_GENERATIONS=4     --保留4份全备数量
KEEP_DATA_DAYS=30						--数据保留30天,
KEEP_ARCLOG_DAYS=35					--WAL日志保留60天
KEEP_SRVLOG_DAYS=180				--LOG日志保留180天数

参考文章

http://pgsql.tech/project_300_10000041