1. 介绍

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

  • https://github.com/ossc-db/pg_rman
    pg_rman的特点如下:
  • 使用简单,一个命令即可完成备份和恢复
  • 支持在线全备、增量备份、WAL日志的备份
  • 支持备份压缩,通过gzip工具实现压缩
  • 自动备份维护、自动删除过期的WAL备份文件
  • 支持备份验证,通过使用文件的大小和数据块CRC实现校验
  • 恢复期间无事务丢失,支持基于PITR的配置文件生成器

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

对于刚接触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命令进行安装即可,如下所示:

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

2. 初次使用

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

笔者的建用户命令为:

  1. groupadd -g 701 postgres
  2. useradd -m -g postgres -u 701 postgres

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

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

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

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

  1. unix_socket_directories = '/tmp'

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

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

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

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

  1. [postgres@pg01 ~]$ which pg_rman
  2. /usr/pgsql-10/bin/pg_rman
  3. [postgres@pg01 ~]$ pg_rman --help
  4. pg_rman manage backup/recovery of PostgreSQL database.
  5. Usage:
  6. pg_rman OPTION init
  7. pg_rman OPTION backup
  8. pg_rman OPTION restore
  9. pg_rman OPTION show [DATE]
  10. pg_rman OPTION show detail [DATE]
  11. pg_rman OPTION validate [DATE]
  12. pg_rman OPTION delete DATE
  13. pg_rman OPTION purge
  14. ...
  15. ...
  16. ...

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

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

  1. export BACKUP_PATH=~/backups

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

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

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

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

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

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

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

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

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

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

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

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

执行增量备份的命令:

  1. [postgres@pg01 ~]$ pg_rman backup --backup-mode=incremental --with-serverlog -B ~/backups
  2. INFO: copying database files
  3. ERROR: cannot take an incremental backup
  4. 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查看备份情况,看看当前备份的状态是多少:

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

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

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

然后用pg_rman show查看状态:

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

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

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

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

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

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

  1. [postgres@pg01 ~]$ pg_rman delete '2018-11-23 17:45:36'
  2. INFO: delete the backup with start time: "2018-11-23 17:45:36"
  3. WARNING: cannot delete backup with start time "2018-11-23 17:45:07"
  4. DETAIL: This is the latest full backup necessary for successful recovery.
  5. [postgres@pg01 ~]$ pg_rman show
  6. =====================================================================
  7. StartTime EndTime Mode Size TLI Status
  8. =====================================================================
  9. 2018-11-23 17:47:44 2018-11-23 17:47:46 INCR 67MB 1 OK
  10. 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 restore就完成了恢复,下面我们把备份恢复到新目录“/data/datapg/newpgdata”:

  1. [postgres@pg01 ~]$ pg_rman restore -D /data/datapg/newpgdata
  2. WARNING: pg_controldata file "/data/datapg/newpgdata/global/pg_control" does not exist
  3. INFO: the recovery target timeline ID is not given
  4. INFO: use timeline ID of latest full backup as recovery target: 1
  5. INFO: calculating timeline branches to be used to recovery target point
  6. INFO: searching latest full backup which can be used as restore start point
  7. INFO: found the full backup can be used as base in recovery: "2018-11-23 15:09:36"
  8. INFO: copying online WAL files and server log files
  9. INFO: clearing restore destination
  10. INFO: validate: "2018-11-23 17:48:36" backup and archive log files by SIZE
  11. INFO: backup "2018-11-23 17:48:36" is valid
  12. INFO: restoring database files from the full mode backup "2018-11-23 15:09:36"
  13. INFO: searching incremental backup to be restored
  14. INFO: validate: "2018-11-23 17:52:43" backup, archive log files and server log files by SIZE
  15. INFO: backup "2018-11-23 17:52:43" is valid
  16. INFO: restoring database files from the incremental mode backup "2018-11-23 16:52:43"
  17. INFO: searching backup which contained archived WAL files to be restored
  18. INFO: backup "2018-11-23 17:52:43" is valid
  19. INFO: restoring WAL files from backup "2018-11-23 16:52:43"
  20. INFO: restoring online WAL files and server log files
  21. INFO: generating recovery.conf
  22. INFO: restore complete
  23. HINT: Recovery will start automatically when the PostgreSQL server is started.

这时我们可以到下恢复的目录/data/datapg/newpgdata中有一个recovery.conf文件,内容如下:

  1. # recovery.conf generated by pg_rman 1.3.7
  2. restore_command = 'cp /home/postgres/pgarch/%f %p'
  3. recovery_target_timeline = '1'

从上面的的内容可以看到这个文件中没有standby_mode = 'on',所以当在这个目录中启动数据库时,会先从归档目录恢复数据库,恢复完之后,数据库就会变成主库。如果在这个文件中加上standby_mode = 'on',恢复完成后,数据库还是只读备库。

下面我们再试一试备份归档的功能:

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

备份完之后,查看归档目录,发现归档目录下的WAL日志文件并不会删除:

3. 进一步的学习

首先学习官方手册

通过官方手册可以学习到pg_rman命令中更多参数的使用方法。这里把pg_rman命令的使用方法再解释一睛,pg_rman命令的使用方法如下:

  1. pg_rman [ OPTIONS ] { init |
  2. backup |
  3. restore |
  4. show [ DATE | detail ] |
  5. validate [ DATE ] |
  6. delete DATE |
  7. purge }

对上面的使用方法解释一下,pg_rman有一些命令类型,如“init”、“backup”、“restore”等等,这些命令不需要加“-”或,“—”,而这些命令可以跟一些参数选项,这些参数选项都是以“-”或“—”开头的,如下面的命令:

  1. pg_rman backup -B /home/postgres/backups

命令中“backup”是命令类型,而“-B /home/postgres/backups”的参数选项。

对于不同的命令类型,可以跟不同的参数,下面列出常用命令的参数选项,如果下面没有列出的更多的参数选项可以参见:

3.1 通用选项

所备通用选项就是所有命令类型都可以跟的参数选项,这些参数选项如下:

  • -D PATH / --pgdata=PATH
    • 指定数据库的绝对路径,记住是绝对路径,一定不能是相对路径。
  • -A PATH / --arclog-path=PATH
    • 指定数据库的归档路径,记住是绝对路径,一定不能是相对路径。在做pg_rman init时这个路径会自动从postgresql.conf中的参数archive_command中获得
  • -S PATH / --srvlog-path=PATH
    • 指定PG的程序日志路径,记住是绝对路径,一定不能是相对路径。在做pg_rman init时这个路径会自动从postgresql.conf中的参数log_directory参数中获得
  • -B PATH / --backup-path=PATH
    • 指定备份仓库的绝对路径,记住是绝对路径,一定不能是相对路径。总是需要提供(命令行参数指定或用环境变量中获得)
  • -c / --check
    • 如果指定了此选项,执行命令时其实只是做一个检查,并不真的执行所做的操作。这通常在我们不确定命令是否正确时,可以加此选项测试一下。这个此选项通常与 --verbose 选项一起使用。
  • -v / --verbose
    • 执行中出输出更多的详细信息
  • -P / --progress
    • 如果指定了,将显示备份或恢复的进度(用当前的文件数/总文件数来显示进度 )

3.2 备份命令的选项

即在pg_rman backup命令中可以跟的选项:

  • -b { full | incremental | archive } / --backup-mode={ full | incremental | archive }
    • Specify backup target files. Available options are: full backup, incremental backup, and archive backup. Abbreviated forms (prefix match) are also available. For example, -b f means full backup.
      • full : Whole database backup and archive backup
      • incremental : Incremental backup and archive backup
      • archive : Only archive backup
  • -s / --with-serverlog
    • 如果指定此参数,则把PostgreSQL的程序日志也备份了,即9.x下的$PGDATA/pg_log目录下的日志,在10.X版本是在$PGDATA/log目录下日志文件。这些日志文件相对来说不是很重要,通常可以不备份,但在有时查问题时,这些程序日志文件可能会用用。
  • -Z / --compress-data
    • 如果指定了,备份将使用压缩(zlib)
  • -C / --smooth-checkpoint
    • 如果指定了,在备份时将做比较温柔的checkpoint,实际上就是pg_start_backup()的第二个参数fast设置为false,这样的checkpoint对IO的冲击比较小一些。
  • --keep-data-generations / --keep-data-days
    • 这两个参数指定在备份仓库保留多少的备份数据。--keep-data-generations指定保留数据几代,即在备份集中保留几个全备份。--keep-data-days指示保留多少天的数据。如果这两个参数都设置了,保留的数据需要符合这两个参数的共同要求。
  • --keep-arclog-files / --keep-arclog-days
    • 这两个参数设置在备份仓库中保留多少的WAL日志。--keep-arclog-files 指定保留多少个WAL日志文件,--keep-arclog-days 设置保留多少天的WAL日志。如果这两个参数都设置了,保留的数据需要符合这两个参数的共同要求。
  • --keep-srvlog-files / --keep-srvlog-days
    • 这两个参数设置在备份仓库中保留多少的PG程序日志。--keep-srvlog-files 指定保留多少个程序日志文件,--keep-srvlog-days 设置保留多少天的程序日志文件。如果这两个参数都设置了,保留的数据需要符合这两个参数的共同要求。

需要说明的是,在pg_rman中会根据--keep-data-generations / --keep-data-days、 --keep-arclog-files / --keep-arclog-days、--keep-srvlog-files / --keep-srvlog-days这些参数的要求,在执行pg_rman backup时就自动删除掉一些不需要的备份文件。

3.3 恢复命令的选项

即在pg_rman restore命令中可以跟的选项。

下面这些选项与PostgreSQL数据库的recovery.conf文件中的参数的意思是一致的:

  • --recovery-target-timeline TIMELINE
    • 指定恢复的时间线,如果没有指定,则用$PGDATA/global/pg_control)中的时间线。
  • --recovery-target-time TIMESTAMP
    • 指定恢复到哪个时间。如果没有指定,则一直恢复到最后的时间。
  • --recovery-target-xid XID
    • 指定恢复到哪个事务ID(XID),如果没有指定,则一直恢复到最后的XID。
  • --recovery-target-inclusive
    • 前面指定的恢复点(recovery-target-time、recovery-target-xid),恢复时是刚好超过这个点,还是刚好在这个点之前停掉,默认是超过这个点(即设置为true的情况)

下面这个参数确定恢复的行为:

  • --hard-copy
    • 如果没有指定这个参数,pg_rman实际上是把在归档目录中建一个软链接指向恢复中要用到的WAL日志文件。如果指定了这个参数,则执行真的拷贝。

更一步的内容,待增加,敬请期待。

3.4 命令选项放到环境变量中或配置文件中

实际上各个命令的选项参数中多数都可以放到环境变量或配置文件中,配置文件是指前面我们提过的“pg_rman.init”,下面把这些参数的使用方法列出来:

短参数 长参数 环境变量 配置文件 描述 备注
-h --host PGHOST database server host or socket directory
-p --port PGPORT database server port
-d --dbname PGDATABASE database to connect
-U --username PGUSER user name to connect as
PGPASSWORD password used to connect
-w --no-password never prompt for password
-W --password force password prompt
-D --pgdata PGDATA Yes location of the database storage area
-B --backup-path BACKUP_PATH Yes location of the backup storage area
-A --arclog-path ARCLOG_PATH Yes location of archive WAL storage area
-S --srvlog-path SRVLOG_PATH Yes location of server log storage area
-b --backup-mode BACKUP_MODE Yes backup mode (full, incremental, or archive)
-s --with-serverlog WITH_SERVERLOG Yes also backup server log files specify boolean type in environmental variable or configuration file
-Z --compress-data COMPRESS_DATA Yes compress data backup with zlib specify boolean type in environmental variable or configuration file
-C --smooth-checkpoint SMOOTH_CHECKPOINT Yes do smooth checkpoint before backup specify boolean type in environmental variable or configuration file
--standby-host STANDBY_HOST Yes standby server host or socket directory
--standby-port STANDBY_PORT Yes standby server port
--keep-data-generations KEEP_DATA_GENERATIONS Yes keep GENERATION of full data backup
--keep-data-days KEEP_DATA_DAYS Yes keep enough data backup to recover to DAY days age
--keep-srvlog-files KEEP_SRVLOG_FILES Yes keep NUM of serverlogs
--keep-srvlog-days KEEP_SRVLOG_DAYS Yes keep serverlog modified in DAY days
--keep-arclog-files KEEP_ARCLOG_FILES Yes keep NUM of archived WAL
--keep-arclog-days KEEP_ARCLOG_DAYS Yes keep archived WAL modified in DAY days
--recovery-target-timeline RECOVERY_TARGET_TIMELINE Yes recovering into a particular timeline
--recovery-target-xid RECOVERY_TARGET_XID Yes transaction ID up to which recovery will proceed
--recovery-target-time RECOVERY_TARGET_TIME Yes time stamp up to which recovery will proceed
--recovery-target-inclusive RECOVERY_TARGET_INCLUSIVE Yes whether we stop just after the recovery target
--hard-copy HARD_COPY Yes how to restore archive WAL specify boolean type in environmental variable or configuration file

如我们前面提过的环境变量“BACKUP_PATH”,设置了此参数,就可以不用在命令行中指定“-B”了。

4. 实战

4.1 备份策略规划

我们以一个例子来说明:总共保留两周的数据,即14天的数据,每周进行一次全备,每周一和周三的2:00做一次增量备份,每天进行一次归档备份,这样我们需要对pg_rman.init中做如下配置:

  1. KEEP_DATA_GENERATIONS=2
  2. KEEP_DATA_DAYS=14
  3. KEEP_ARCLOG_DAYS=15
  4. KEEP_ARCLOG_FILES=1000
  5. KEEP_SRVLOG_DAYS=180
  • 因为我们需要两个全备份,所以KEEP_DATA_GENERATIONS=2
  • 两周的数据所以KEEP_DATA_DAYS=14,而可以把WAL日志多保留一天,所以KEEP_ARCLOG_DAYS=15
  • 至少保留1000个WAL文件,每个WAL为16M,所以大约16G,占用空间不算大。
  • KEEP_SRVLOG_DAYS=180,通常程序日志不太,所以保留180天的日志,即3个月。

做这样的配置之后,我们就不需要再用pg_rman delete是删除不需要的备份数据了,只需要按上面的备份策略把备份操作放到crontab中定期执行就可以了,在执行pg_rman backup时会自动的把不需要的备份数据给删除掉。

5 一些最佳实践

5.1 备份参数-C

备份参数 -C 表示平滑checkpoint。在备份开始时,会先执行checkpoint。当执行温柔型的checkpoint对线上的性能影响较小,但可能导致备份变得很慢(慢多少与参数checkpoint_completion_target和segment_size的配置有关系)。 如果你发现pg_rman开始时很慢,可以把-C去掉,速度就会快了,但可能对业务产生影响,所以不管怎样在业务高峰时不要备份。

5.2 关于块大小(BLCKSZ)

因为要需要做块的校验,读取LSN等,都与块大小有关,所以pg_rman的二进制版本要与PostgreSQL中的块大小相一致,即BLCKSZ and XLOG_BLCKSZ的大小必须匹配。对于已编译好的版本,pg_rman针对不现的数据库版本发布了不同的二进制版本,需要作用正确的版本。

如果你是编译pg_rman时,最好使用启动数据库实例的PostgreSQL软件下pg_config,这样编译能确保块大小是一致的。

5.3 一些备份或恢复时的注意点

如果你在数据库实例的PGDATA目录下有一些不可读的文件或目录会导致备份或恢复失败,这一点需要注意。

因为pg_rman使用的是独占型备份(exclusive bakcup,这个参数是在函数pg_start_backup中),所以当pg_rman正在备份时,不能启动其它的备份。

5.4 在备库的节点上做备份

pg_rman支持在备库的节点做备份,这样可以减少对主库的IO压力。pg_rman在备库上做备份,也需要连接主库中,执行一些操作。另需要在备库中打开归档,即在postgresql.conf文件中做如下配置:

  1. archive_mode = always
  2. archive_command = 'test ! -f /home/postgres/pgarch/%f && cp %p /home/postgres/pgarch/%f'

注意在备库中打开归档需要archive_mode = always,而不是archive_mode = on,因为archive_mode=on只在主库上生效,在备库上不生效。

因为在备库上做备份,在执行pg_rman的命令时,需要用“-h ”等参数指定主库的IP地址,有可能还需要手工输入密码,如下面的初始化备份仓库的操作:

  1. [postgres@pg10_tang02 ~]$ pg_rman init -d template1 -h 192.168.6.15 -p 5432 -B ~/backups
  2. INFO: ARCLOG_PATH is set to '/home/postgres/pgarch'
  3. INFO: SRVLOG_PATH is set to '/home/postgres/pgdata/log'

为了避免每次输入密码,可以把密码设置到环境变量中:

  1. export PGPASSWORD=*******
  1. pg_rman backup --backup-mode=full -B /home/postgres/backups --host=192.168.6.15 --standby-host=192.168.6.16 --standby-port=5432

上面的命令与在主库上不一样的地方主要是加了以下的参数:

  • --standby-host=192.168.6.16 :这是指定了备库的IP地址
  • --standby-port=5432:这是指定了备库的端口
  • --host=192.168.6.15:这是指定的主库的IP地址。这个参数在主库上执行时也是可以使用,只是前面在主库上操作时,是通过unix domain的本地验证,所以可以不需要输入此参数。因为现在中跨机器连接主库,所以这个参数是必须的。

当然也可以把 --standby-host=192.168.6.16 --standby-port=5432放到pg_rman.ini配置文件中,如在pg_rman.ini中添加如下内容:

  1. STANDBY_HOST=192.168.6.16
  2. STANDBY_PORT=5432

这样我们备份只需要输入下面的命令就可以了:

  1. pg_rman backup --backup-mode=full -B /home/postgres/backups --host=192.168.6.15

我们在备库中做备份时,如果发现pg_rman一直hang住,一直不完成,通常是主备库之间的流复制出问题了,其中一种情况是主库上的postgresql.conf中的参数min_wal_size设置太小,当主库上有大的更新时,备库没有跟上,导致备库所需要的WAL日志文件在主库上已被删除掉了,所以通过我们可以把max_wal_sizemin_wal_size这两个参数设置的大一些,如当不缺乏空间时,把min_wal_size设置成20G,如下所示:

  1. max_wal_size = 25GB
  2. min_wal_size = 20GB

5.5 恢复实战

恢复时,有两种选择可以选择原地恢复,或者恢复到新的目录下。但如果使用了表空间,最好还是原地恢复。

需要特别注意,不管是哪种恢复方式,如果在本机恢复,即使指定恢复到新的目录下,但一些归档目录等目录还是会被覆盖,如果你要保留原数据,建议先将原数据目录重命名外,一些归档目录也需要重命名。

所以一个比较好的方法是把备份仓库放到NFS上,恢复时可以恢复到新的一台机器上,这样就避免了原数据被覆盖的风险。

如果是在原机器上恢复,建议至少重命令以下的目录:

  • 数据库实例的数据目录$PGDATA
  • 数据库的WAL目录,在9.X版本一般为pg_xlog,而10版本之后是pg_wal
  • 各个表空间所在的目录
  • 归档目录

最简单的原目录恢复,命令如下:

  1. [postgres@pg10_tang02 ~]$ pg_rman restore -B /home/postgres/backups
  2. INFO: the recovery target timeline ID is not given
  3. INFO: use timeline ID of current database cluster as recovery target: 1
  4. INFO: calculating timeline branches to be used to recovery target point
  5. INFO: searching latest full backup which can be used as restore start point
  6. INFO: found the full backup can be used as base in recovery: "2018-11-28 18:06:27"
  7. INFO: copying online WAL files and server log files
  8. INFO: clearing restore destination
  9. INFO: validate: "2018-11-28 18:06:27" backup and archive log files by SIZE
  10. INFO: backup "2018-11-28 18:06:27" is valid
  11. INFO: restoring database files from the full mode backup "2018-11-28 18:06:27"
  12. INFO: searching incremental backup to be restored
  13. INFO: validate: "2018-11-28 18:08:55" backup and archive log files by SIZE
  14. INFO: backup "2018-11-28 18:08:55" is valid
  15. INFO: restoring database files from the incremental mode backup "2018-11-28 18:08:55"
  16. INFO: searching backup which contained archived WAL files to be restored
  17. INFO: backup "2018-11-28 18:08:55" is valid
  18. INFO: restoring WAL files from backup "2018-11-28 18:08:55"
  19. INFO: restoring online WAL files and server log files
  20. INFO: generating recovery.conf
  21. INFO: restore complete
  22. HINT: Recovery will start automatically when the PostgreSQL server is started.

这时我们看归档目录:

  1. [postgres@pg10_tang02 ~]$ ll pgarch
  2. total 98304
  3. -rw-------. 1 postgres postgres 16777216 Nov 28 18:05 00000001000000000000001B
  4. -rw-------. 1 postgres postgres 16777216 Nov 28 17:59 00000001000000000000001C
  5. -rw-------. 1 postgres postgres 16777216 Nov 28 18:00 00000001000000000000001D
  6. -rw-------. 1 postgres postgres 16777216 Nov 28 18:06 00000001000000000000001E
  7. -rw-------. 1 postgres postgres 16777216 Nov 28 18:06 00000001000000000000001F
  8. -rw-------. 1 postgres postgres 16777216 Nov 28 18:07 000000010000000000000020
  9. lrwxrwxrwx. 1 postgres postgres 70 Nov 28 18:14 000000010000000000000021 -> /home/postgres/backups/20181128/180855/arclog/000000010000000000000021
  10. lrwxrwxrwx. 1 postgres postgres 70 Nov 28 18:14 000000010000000000000022 -> /home/postgres/backups/20181128/180855/arclog/000000010000000000000022

发现归档目录下,怎么有了一些链接文件?看pg_rman生成的recovey.conf中的内容:

  1. [postgres@pg10_tang02 pgdata]$ cat recovery.conf
  2. # recovery.conf generated by pg_rman 1.3.7
  3. restore_command = 'cp /home/postgres/pgarch/%f %p'
  4. recovery_target_timeline = '1'

这样就明白了,实际上pg_rman会把归档目录下的同名的WAL日志文件清理掉,然后建一个链接文件到原先的备份目录下,这时恢复时就会自动应用这些WAL日志文件进行恢复了。

当然我们也可以加参数\-\-hard-copy,这样就是把WAL从备份仓库中拷贝出来,而不是这样软链接,如下所示:

  1. [postgres@pg10_tang02 ~]$ pg_rman restore -B /home/postgres/backups --hard-copy
  2. INFO: the recovery target timeline ID is not given
  3. INFO: use timeline ID of current database cluster as recovery target: 1
  4. INFO: calculating timeline branches to be used to recovery target point
  5. INFO: searching latest full backup which can be used as restore start point
  6. INFO: found the full backup can be used as base in recovery: "2018-11-28 18:06:27"
  7. INFO: copying online WAL files and server log files
  8. INFO: clearing restore destination
  9. INFO: validate: "2018-11-28 18:06:27" backup and archive log files by SIZE
  10. INFO: backup "2018-11-28 18:06:27" is valid
  11. INFO: restoring database files from the full mode backup "2018-11-28 18:06:27"
  12. INFO: searching incremental backup to be restored
  13. INFO: validate: "2018-11-28 18:08:55" backup and archive log files by SIZE
  14. INFO: backup "2018-11-28 18:08:55" is valid
  15. INFO: restoring database files from the incremental mode backup "2018-11-28 18:08:55"
  16. INFO: searching backup which contained archived WAL files to be restored
  17. INFO: backup "2018-11-28 18:08:55" is valid
  18. INFO: restoring WAL files from backup "2018-11-28 18:08:55"
  19. INFO: restoring online WAL files and server log files
  20. INFO: generating recovery.conf
  21. INFO: restore complete
  22. HINT: Recovery will start automatically when the PostgreSQL server is started.

这时再看归档目录:

  1. [postgres@pg10_tang02 ~]$ ll pgarch/
  2. total 131072
  3. -rw-------. 1 postgres postgres 16777216 Nov 28 18:05 00000001000000000000001B
  4. -rw-------. 1 postgres postgres 16777216 Nov 28 17:59 00000001000000000000001C
  5. -rw-------. 1 postgres postgres 16777216 Nov 28 18:00 00000001000000000000001D
  6. -rw-------. 1 postgres postgres 16777216 Nov 28 18:06 00000001000000000000001E
  7. -rw-------. 1 postgres postgres 16777216 Nov 28 18:06 00000001000000000000001F
  8. -rw-------. 1 postgres postgres 16777216 Nov 28 18:07 000000010000000000000020
  9. -rw-------. 1 postgres postgres 16777216 Nov 28 18:37 000000010000000000000021
  10. -rw-------. 1 postgres postgres 16777216 Nov 28 18:37 000000010000000000000022

就没有链接文件了。

我们也可以加上参数--recovery-target-time='XXX'让数据库恢复到一个指定的时间:

  1. [postgres@pg10_tang02 ~]$ pg_rman restore -B /home/postgres/backups --recovery-target-time='2018-11-28 18:09:10'
  2. INFO: the recovery target timeline ID is not given
  3. INFO: use timeline ID of current database cluster as recovery target: 1
  4. INFO: calculating timeline branches to be used to recovery target point
  5. INFO: searching latest full backup which can be used as restore start point
  6. INFO: found the full backup can be used as base in recovery: "2018-11-28 18:06:27"
  7. INFO: copying online WAL files and server log files
  8. INFO: clearing restore destination
  9. INFO: validate: "2018-11-28 18:06:27" backup and archive log files by SIZE
  10. INFO: backup "2018-11-28 18:06:27" is valid
  11. INFO: restoring database files from the full mode backup "2018-11-28 18:06:27"
  12. INFO: searching incremental backup to be restored
  13. INFO: validate: "2018-11-28 18:08:55" backup and archive log files by SIZE
  14. INFO: backup "2018-11-28 18:08:55" is valid
  15. INFO: restoring database files from the incremental mode backup "2018-11-28 18:08:55"
  16. INFO: searching backup which contained archived WAL files to be restored
  17. INFO: backup "2018-11-28 18:08:55" is valid
  18. INFO: restoring WAL files from backup "2018-11-28 18:08:55"
  19. INFO: restoring online WAL files and server log files
  20. INFO: generating recovery.conf
  21. INFO: restore complete
  22. HINT: Recovery will start automatically when the PostgreSQL server is started.

从上在可以看到先从全备中恢复INFO: restoring database files from the full mode backup "2018-11-28 18:06:27",然后再从增量备份中恢复restoring database files from the incremental mode backup "2018-11-28 18:08:55"
我们再看这次恢复生成的recovery.conf文件的内容:

  1. [postgres@pg10_tang02 pgdata]$ cat recovery.conf
  2. # recovery.conf generated by pg_rman 1.3.7
  3. restore_command = 'cp /home/postgres/pgarch/%f %p'
  4. recovery_target_time = '2018-11-28 18:09:10'
  5. recovery_target_timeline = '1'

发现多了一行:recovery_target_time = '2018-11-28 18:09:10'

实际上在每次备份中都会生成一个文件backup.ini :

  1. [postgres@pg10_tang02 ~]$ cat /home/postgres/backups/20181128/180855/backup.ini
  2. # configuration
  3. BACKUP_MODE=INCREMENTAL
  4. FULL_BACKUP_ON_ERROR=false
  5. WITH_SERVERLOG=false
  6. COMPRESS_DATA=false
  7. # result
  8. TIMELINEID=1
  9. START_LSN=0/22000028
  10. STOP_LSN=0/220000f8
  11. START_TIME='2018-11-28 18:08:55'
  12. END_TIME='2018-11-28 18:09:06'
  13. RECOVERY_XID=762
  14. RECOVERY_TIME='2018-11-28 18:09:00'
  15. TOTAL_DATA_BYTES=40584549
  16. READ_DATA_BYTES=18720584
  17. READ_ARCLOG_BYTES=33554432
  18. WRITE_BYTES=50573783
  19. BLOCK_SIZE=8192
  20. XLOG_BLOCK_SIZE=8192
  21. STATUS=OK

这个文件中记录了一些重要的信息,如开始和结束的LSN,这个LSN将用于比对增量备份时对比数据块的LSN是否发生了变化,是否需要备份。RECOVERY_XID=762记录了xid,这时我们可以用这个xid做为恢复点,如下所示:

  1. [postgres@pg10_tang02 ~]$ pg_rman restore -B /home/postgres/backups --recovery-target-xid=762
  2. INFO: the recovery target timeline ID is not given
  3. INFO: use timeline ID of current database cluster as recovery target: 1
  4. INFO: calculating timeline branches to be used to recovery target point
  5. INFO: searching latest full backup which can be used as restore start point
  6. INFO: found the full backup can be used as base in recovery: "2018-11-28 18:06:27"
  7. INFO: copying online WAL files and server log files
  8. INFO: clearing restore destination
  9. INFO: validate: "2018-11-28 18:06:27" backup and archive log files by SIZE
  10. INFO: backup "2018-11-28 18:06:27" is valid
  11. INFO: restoring database files from the full mode backup "2018-11-28 18:06:27"
  12. INFO: searching incremental backup to be restored
  13. INFO: validate: "2018-11-28 18:08:55" backup and archive log files by SIZE
  14. INFO: backup "2018-11-28 18:08:55" is valid
  15. INFO: restoring database files from the incremental mode backup "2018-11-28 18:08:55"
  16. INFO: searching backup which contained archived WAL files to be restored
  17. INFO: backup "2018-11-28 18:08:55" is valid
  18. INFO: restoring WAL files from backup "2018-11-28 18:08:55"
  19. INFO: restoring online WAL files and server log files
  20. INFO: generating recovery.conf
  21. INFO: restore complete
  22. HINT: Recovery will start automatically when the PostgreSQL server is started.
0 评论  
添加一条新评论