技术开发 频道

李昊:PostgreSQL PITR 技术讲解

  【IT168 技术】本文编辑整理自【微学堂】第十期活动实录

   嘉宾介绍

   李昊,山东瀚高基础软件股份有限公司产品测试与支持经理。日常主要负责PostgreSQL和HighGo Database产品相关测试及运维支持工作。

   直播实录

   大家好,今天想跟大家分享的是postgresql数据库的PITR技术,主要是根据平日的使用,并结合了一些理论补充。

   在介绍PITR技术之前,先对postgresql结构做下简单的说明,数据库服务器下的所有数据库是以ID进行标识,存放在初始化的data/base目录下,其实例与database是一对N的关系。同时服务器下所有数据库的wal事务日志,统一放在初始化的data/pg_xlog目录下,是不分库的。wal事务日志,大家可以理解为oracle中的online redo log,这个后面会有说明。因此,postgresql数据库无法分库分文件,进而进行一些类似oracle方面的精细的操作。

   那么现在开始进入正题。PITR,Point-In-Time-Recovery,是postgresql数据库的增量备份恢复技术,类似于oracle的增量备份。pitr它的原理是利用:基础热备 + wal预写日志 + wal归档日志进行的备份恢复。结合刚刚的postgresql结构的说明,可以看出,PITR技术是作用于“服务器”级的,同时postgresql中没有scn的概念,因此在进行PITR恢复时会将整个服务器,包括服务器的所有对象,恢复到指定时刻,而非某个具体的数据库对象。同样的,结合oracle中的完全与不完全恢复来说,在postgresql中,由于写wal与写归档是基于不同触发条件的进程,因此也会出现宕机时,wal未归档的情形。那么此时,就需要类似oracle的不完全恢复手段。

【微学堂】PostgreSQL PITR 技术讲解

   接下来,会逐步对wal事务日志、归档进行一些简单的说明,wal全称是write ahead log,是postgresql中的online redo log,是为了保证数据库中数据的一致性和事务的完整性而在PostgreSQL 7中引入的技术。它的中心思想是“先写日志后写数据”,即要保证对数据库文件的修改应放生在这些修改已经写入到日志之后,同时,在PostgreSQL 8.3以后又加入了WalWriter日志写进程,可以保证事务提交记录不是在提交时同步写入到磁盘,而是异步写入,这样就极大的减轻了I/O的压力。

【微学堂】PostgreSQL PITR 技术讲解

   下面这个图,是wal日志的物理存储结构:

【微学堂】PostgreSQL PITR 技术讲解

   其中pg_xlog目录就是wal的目录,它的上一级data目录就是初始化的服务器存储目录,在这个Pg_xlog目录下,大家可以看到一些类似于这样的文件:000000010000000000000002。

   这种3部分8位十六进制字符组成的文件,即为具体的日志文件,其中,第一部分表示时间线 timeline;第二部分表示日志文件标号;第三部分表示日志文件的段标号。刚刚这个图片中的.history文件,就是timeline时间线文件,后面也会有说明,而这个目录下的archive_status目录,则存储wal日志的归档状态标记文件,.ready表示可以进行归档,.done则表示成功归档,同样的,类似于oracle,在postgresql中,当wal_buffer满了,或者有脏页需要交换时,会触发wal的写进程。

   补充一下,在oracle中是手动commit,在postgresql中是自动commit。commit时,也会触发wal写,它的自动commit是指,不需要开启begin,输入命令,回车后,自动提交。当然,也可以手动开启begin事务,那么,接下来就对timeline文件(.history),及timeline进行一些说明。

   首先,说一下timeline,它在初始化完数据库之后,就标记为1,然后逐渐递增,当从归档中进行启动恢复时,会生成新的timeline,否则,会一直沿着原来的timeline走,如下图:

【微学堂】PostgreSQL PITR 技术讲解

   然后,当生成新的timeline时,就会在归档目录下,生成一个对应的时间线文件.history,这个文件内,以明文的形式记录:父时间线 | 分出时的日志文件 | 分出的时间。需要注意的是,history文件产生时,会立即进行归档,归档文件中会存在完成的时间线历史文件的序列,至于归档,在配置好数据库参数之后,其会自动进行归档。wal日志跟online redo log一样,其个数,也不是无限的,一般可以这么计算,(2+checkpoint_completion_target)*checkpoint_segment+1,缺省值计算为8.5,超过之后,也是会覆盖。上面计算公式中的两个参数,是数据库的配置参数,这里就不做说明了。

   postgresql的归档,是自动进行归档,其是在data目录下的postgresql.conf文件中进行配置,如下:

   wal_level = archive

   archive_mode = on

   archive_command = 'cp %p /usr/local/pgsql/archive/%f'

   第三个参数就是归档命令,%p表示wal是的绝对路径+文件名,%f表示wal日志对应的归档文件命令,二者同名。配置完成之后,需要重启下数据库,而基础备份的过程如下:

   --开启热备

   psql -c "select pg_start_backup('label');"

   --基础备份

   tar -cvf data.tar data/

   --关闭热备

   psql -c "select pg_stop_backup();"

   psql是postgresql的客户端命令,类似与sqlplus,psql是postgresql的客户端命令,类似与sqlplus,两条select语句表示开启、关闭热备,其中的tar,就是进行备份,至此,postgresql的pitr备份,及一些说明就结束了,下面,结合使用,对完全、不完全恢复进行说明。

【微学堂】PostgreSQL PITR 技术讲解

   这是我自己的一个简单环境,安装及初始化在这就跳过了,直接进入主题,生成基础数据,创建lineitem表,手动checkpoint(写磁盘文件),并执行select pg_switch_xlog();切换下归档,调用insert脚本,预先插入2248条数据,再次checkpoint;switch_xlog,如图:

【微学堂】PostgreSQL PITR 技术讲解

   之后,进行基础备份:

【微学堂】PostgreSQL PITR 技术讲解

    此处进行基础备份,将data在线拷贝为data1,然后,查看此时的wal和归档。

【微学堂】PostgreSQL PITR 技术讲解

   二者是一致的。

   再次checkpoint;switch_xlog之后,wal比归档多两个【微学堂】PostgreSQL PITR 技术讲解

   将脏块刷入到wal了,然后,继续批量insert,任意时刻移除lineitem表的物理文件后中断insert。

   这个就是查看物理文件的命令。【微学堂】PostgreSQL PITR 技术讲解

   之后,查看wal和归档。

【微学堂】PostgreSQL PITR 技术讲解

   并根据数据库日志,确认了再次执行的insert条数。

【微学堂】PostgreSQL PITR 技术讲解

   这里,我是先备份并清空了原日志之后,在继续进行的insert,然后:利用data1手动cp出data2,利用现在的archive目录手动cp生成:archive1、archive2,并做了简单的配置。

【微学堂】PostgreSQL PITR 技术讲解

 【微学堂】PostgreSQL PITR 技术讲解

   之后,分别启动data1、data2并进行数据量验证,data1下:2248条(没有用到未归档的wal),进行了不完全恢复;data2下:5382条(利用了未归档的wal,2248+3134),进行了完全恢复。

   其中在恢复时,需要在data目录下,创建一个recovery.conf文件,主要写入:

   restore_command = 'cp /home/postgres/archive/%f %p',这是转储命令。

   recovery_target_time = ‘2016-06-02 12:12:12’,恢复到这个时间戳。

   recovery_target_timeline = ‘2’,恢复到指定的timeline

   也可以这样配置recovery.conf:

   restore_command =

   recovery_target_timeline =

   recovery_target_time =

   同时用这个参数。

   其中,target_time得是在timeline之前的时刻,之前做了次小实验,可以这么进行恢复。

   互动筛选:

   Q:pg_rewind机制是不是基于pitr的?

   A:关于pg_rewind,只是刚出来时使用了一下,不算是pitr, 个人认为它主要是根据checkpoint进行数据块比对, 然后当备库与主库不一致时, 进行比对同步的. 这是我的个人理解。

0
相关文章