PG中使用pg_basebackup实现时间点恢复( Point-in-Time Recovery (PITR))

2    487    3

👉 本文共约5637个字,系统预计阅读时间或需22分钟。

pg_basebackup备份工具简介

参考:https://www.xmmup.com/pg_basebackupbubeifentemporary-tablehe-unlogged-table.html

该备份工具自动执行 pg_start_backup()和 pg_stop_backup()函数,而且备份速度和数据都比手动的备份快。

注意:

把数据库文件转储出来后,在启动数据库前 postgresql.conf 一定要添加恢复参数,否则只恢复到备份的时间点。

经过测试,第一次恢复后,数据库能够恢复到最新状态,t1 表的数据能够恢复到归档的最后位置。对数据库进行操作,切换几个日志后,再用之前的备份对数据库进行恢复,结果能够恢复到最新的状态,能够自动应用归档,此恢复方式比 mysql 要智能。

如果当前的日志丢失,pg 实际上做的是不完全恢复,但是恢复的时候没有提示,而且不需要显式进行 recovery,在启动数据库的时候自动运行,类似 oracle 的实例恢复。

PITR简介

1、什么是PITR ?

PITR: 全称是Point-In-Time-Recover (时间点恢复),是PG从8.0版本开始引入的一个特性,该特性可以使用基础备份连续归档日志将数据库集群恢复到任意时间点

2、什么是基础备份?怎么获取基础备份?

在pg中,也是从8.0版本中引入了在线物理全备份,运行中的整个数据库集群的快照(即物理备份数据)被称为基础备份。

在pg中可以由两种方法获取基础备份:

  • 使用系统low-level函数:pg_start_backup、pg_stop_backup以及一些shell命令(如cp、tar、rsync等)。
  • 使用pg_basebackup工具

3、pg_start_backup做了什么?

pg_start_backup和pg_stop_backup命令定义见这里:

src/backend/access/transam/xlogfuncs.c

链接:https://github.com/postgres/postgres/blob/master/src/backend/access/transam/xlogfuncs.c

pg_start_backup()是一个用来启动基本备份的函数。它是PostgreSQL 8.0中引入的原始物理备份API的一部分。

pg_start_backup主要执行以下几个操作:

  • 强制服务器进入全页写模式(即使你设置了full_page_writes=off)。
  • 执行checkpoint(我在前面checkpoint的文章中提过,数据库恢复的过程需要从一个REDO位置开始,所以pg_start_backup需要做checkpoint来创建一个REDO点)。
  • 创建一个backup_label文件。

4、backup_label文件的内容和作用什么?

一个backup_label示例:

其中:

CHECKPOINT LOCATION: 这是该函数创建的检查点被记录的LSN位置。当使用这个基础备份恢复数据库时,PostgreSQL从backup_label文件中获取“CHECKPOINT LOCATION”,并开始恢复过程。

BACKUP METHOD: 标示用于进行基础备份的方法(pg_start_backup或pg_basebackup)。

START TIME: 执行pg_start_backup时的时间戳。

LABEL: 这是在调用pg_start_backup(LABEL)中指定的标签。

5、此时你可能有疑问,为什么checkpoint的检查点的位置保存在了backup_label,而不是我们已知的pg_control里?

因为数据库的备份时间可能很长的,期间可能会多次执行常规checkpoint,如果放在pg_control里,那这个位置就可能会常规checkpoint被覆盖了。

6、pg_stop_backup做了什么?

pg_stop_backup主要完成以下工作:

如果pg_start_backup强制打开了full_page_write,pg_stop_backup将会将其重置为非全页写模式。

创建备份历史文件(timeline.hostory)。

删除backup_label文件。(注:从基础备份恢复时,需要backup_label文件,其被复制到归档目录之后,在原始数据库集中就不再需要了。)

7、什么是数据库归档?

一般情况下,PostgreSQL数据库将wal文件保存在$PGDATA的pg_wal下。但是这些wal文件可能会被回收。为了避免这种情况,我们可以将wal文件的副本保存在除$PGDATA之外的单独目录中。在PG中,将wal文件复制到其他位置被称为归档(让服务器读取wal文件并应用它称为恢复)。

8、怎么开启归档?

在pg中开启归档,依赖三个配置:archive_mode、archive_command和wal_level

archive_mode:表示是否要启用wal归档。

archive_command:指定如何归档。此选项接受shell命令或shell脚本。

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

wal_level:可选项:

Minimal:只添加崩溃服务或立即关闭所需的信息。它不能用于复制或归档目的。

Replica: 表示wal将有足够的信息用于wal归档和复制。

Logical:添加逻辑复制所需的信息。

一个配置示例:

其中:

%p: 被替换为WAL文件的路径名。

%f: 被替换为WAL文件的文件名。

9、怎么做PITR(按时间点恢复)?

PITR工作需要两个重要的先决条件:

  • 基础备份的可用性。

  • 连续归档日志。

有了这两个为前提,然后需要配置restore_command和recovery_target选项。

示例:

restore_command:指定从何处查找要在该服务器上重播的WAL文件。这个命令接受与archive_command相同的占位符。

recovery_target_time:该选项告诉服务器何时停止恢复或重放进程。一旦到达给定的时间戳,进程就会停止。

注:pg11.0以及之前,这两个参数在recovery.conf中进行设置。pg12.0以及之后在postgresql.conf中进行配置(12.0已经废除了recovery.conf,所有与recovery相关的参数都移到了postgresql.conf中)。除此之后,在版本12或更高版本中,当进行恢复时,还需要创建一个名为recovery.signal的空文件

10、PITR的工作流程?

(1)PostgreSQL从backup_label文件中读取CHECKPOINT LOCATION的值,即REDO点。

(2) PostgreSQL从recovery.conf(版本11或更早)或PostgreSQL .conf(版本12或更高)中读取restore_command和recovery_target_time参数值。

(3) PostgreSQL从REDO点开始重放WAL数据,通过参数resotere_command,从归档日志中读取WAL数据,将归档日志从归档区复制到临时区。(临时区域中复制的日志文件使用后会被删除。)

注:如果没有配置recovery_target_time,PG将重放日志直到归档结束。

(4)恢复过程结束后,生成时间线历史文件,如00000002.History,该文件被创建在pg_xlog子目录(在版本10或更高版本,pg_wal子目录),如果启用了归档日志特性,归档目录下也会创建相同的命名文件。

11、PITR与正常的数据库恢复有何不同?

正常复模式是从base目录下的pg_wal目录中获取wal文件,而PITR模式是从archive_command中设置的归档目录中获取。

正常恢复模式从pg_control文件获取检查点位置,而PITR模式从backup_label文件中获取检查点位置。

12、什么是时间线?什么时间线历史文件?

参考:PG中的时间线Timeline

PG中的时间线用于区分原始的数据库集群和恢复后的数据库集群,是PITR的核心概念。

每个数据库集群分配一个单独的timelineId。initdb实用程序创建的原始数据库集群的timelineId为1。当数据库集群恢复时,timelineId将增加1。

当我们启动PostgreSQL服务器时,初始时间线被设置为1,从pg_start_backup创建的REDO点到恢复目标,在归档日志中回放WAL数据,然后,一个新的timelineId 2被分配给恢复的数据库集,PostgreSQL将在新的时间线2上运行。如下图所示:

PG中使用pg_basebackup实现时间点恢复( Point-in-Time Recovery (PITR))

前面提到,当一个PITR进程完成时,会生时间线历史文件。这个文件的命名规则为:

“8位的新timelineid.history”,比如此例中,就是00000002.history。

该文件的内容:

第一列:timelineId—timelineId用于恢复的归档日志的id。

第二列:LSN WAL段发生切换的位置。

13、PITR有哪些参数可以配置?

默认情况下,恢复将会一直恢复到 WAL 日志的末尾。 在 recovery_target 、recovery_target_lsn、recovery_target_name、recovery_target_time 和 recovery_target_xid 中, 最多只能使用一个,如果在配置文件中使用了多个,将使用最后一个。

  • recovery_target = 'immediate' :这个参数指定恢复应该在达到一个一致状态后尽快结束, 即尽早结束。在从一个在线备份中恢复时,这意味着备份结束的那个点。
  • recovery_target_name (string) :指定(pg_create_restore_point()所创建)的已命名的恢复点,进行恢复。
  • recovery_target_time (timestamp) :这个参数指定按时间戳恢复。
  • recovery_target_xid (string) :这个参数指定按事务 ID 进行恢复。
  • recovery_target_lsn (pg_lsn) :这个参数指定按继续进行的预写日志位置的 LSN 进行恢复。
  • recovery_target_inclusive (boolean):指定我们是否仅在指定的恢复目标之后停止(true),
    或者仅在恢复目标之前停止(false)。 适用于 recovery_target_lsn、recovery_target_time 或者 recovery_target_xid 被指定的情况。 这个设置分别控制事务是否有准确的目标 WAL 位置(LAN)、提交时间或事务 ID 将被包括在该恢复中。 默认值为 true。
  • recovery_target_timeline (string) :指定恢复到一个特定的时间线中。默认值是沿着基础备份建立时的当前时间线恢复。将这个参数设置为 latest 会恢复到该归档中能找到的最新的时间线。
  • recovery_target_action (enum) :指定在达到恢复目标时服务器应该立刻采取的动作,包括 pause(暂停)、promote(接受连接)、shutdown(停止服务器),其中 pause 为默认动作。

14、PITR类型有哪些?

1、基于命名还原点恢复

数据库的 PITR 是一般数据库都必须满足的技术;

其原理是依据之前的物理备份文件加上 wal 的预写日志模式备份做的恢复; 该技术支持 8.*及以上版本。

recovery.conf 文件还原点控制参数 --12.0 版本以下的

postgresql.conf 文件还原点控制参数 12.0 版本以上

2、基于 recovery_target_name

3、基于 recovery_target_xid 恢复方式

基于 recovery_target_time 恢 复 方 式 与 基 于 recovery_target_name 以 及 基 于

recovery_target_lsn(在创建存储点的时候会显示 lsn 号)恢复的方式一样。

4、基于 time 恢复方式

(recovery_target_lsn='0/50000140')基于 lsn 恢复时的提示:PostgreSQL 快照方式备份与恢复

故障排除:

1) 由于之前做了一些恢复操作,日志太多,所以把 pg_wal 目录下的日志给删除了,但是进行备份的时候就报错,无法备份:

示例:按照recovery_target_time恢复

整个示例恢复流程:

PG中使用pg_basebackup实现时间点恢复( Point-in-Time Recovery (PITR))

配置归档

做基础备份

备份过程:

做增量数据

数据库故障

假定数据库故障,停止数据库,备份故障data并将基础备份的back替换为新data:

不完全恢复到表tl1_t2

创建recovery.signal

在$PGDATA 目录下创建空文件recovery.signal,表示数据库进入恢复模式,这一步是关键,恢复完成后会自动删除。

修改postgresql.auto.conf文件

recovery_target_time表示要恢复到的时间点。

我们先恢复到tl1_t1表,然后再恢复到tl1_t2表。

启动数据库并验证数据

查看数据,可知tl1_t1未被恢复。

告警日志内容:

继续增量恢复

由于备份文件中存在recovery.signal文件,所以,此时数据库仍然处于恢复状态,可以修改recovery_target_time继续恢复:

告警日志:

查看数据:

表tl1_t2已恢复,时间线处于1。

恢复到RW状态

数据库操作select pg_wal_replay_resume();结束恢复状态:

日志:

recovery.signal文件自动被删除了,时间线进入了2。

在timeline2回退到tl1_t1表

这时候,如果发现恢复错误,我又想回到tl1_t1表的时间:

告警日志:

时间线进入了3.

在timeline3恢复到tl2_t1表

此时,由于tl2_t1表在timeline2中,所以,必须配置recovery_target_timeline参数。

可以看到,成功恢复,时间线从2直接到4。

总结

1、做实验时,在删除$PGDATA目录时,最好选择mv操作,因为有一些在线日志来不急归档,那么恢复时就会报错。

2、建表之后的时间做一次checkpoint操作,确保相关表的操作的日志已经归档,否则恢复会报错

参考

https://pgfans.cn/a/1312

https://www.xmmup.com/pg_basebackupbubeifentemporary-tablehe-unlogged-table.html

    头像

    小麦苗

    学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

    您可能还喜欢...

    2 条回复

    1. 头像 小菜来了说道:

      麦老师请教一下,恢复后数据是有了

      但select pg_is_in_recovery();结果是t,
      select pg_wal_replay_resume();执行了表也还是只读状态,
      recovery.signal也还在

      不知道是不是我漏掉什么操作?还是哪个步骤搞错?

    发表评论

    您的电子邮箱地址不会被公开。

    5 × 4 =

     

    嘿,我是小麦,需要帮助随时找我哦
    • 18509239930
    • 个人微信

    • 麦老师QQ聊天
    • 个人邮箱
    • 点击加入QQ群
    • 个人微店

    • 回到顶部
    返回顶部