一、 恢复配置详解
1. 归档恢复配置
主库 postgresql.conf
- archive_mode:是否开启归档,若要用归档方式搭建从库则必须开启
- archive_command:归档命令,通常是cp
- archive_timeout:在指定秒数后强制切换一个wal文件,注意被切换的文件会跟正常文件一样大,所以这个参数设置过小会导致wal大量占用空间
从库 recovery.conf
- restore_command:告诉从库如何获取归档WAL文件段的命令,通常是cp
restore_command = 'cp /data/PRD/postgres/10.7/pg5432/pg_archlog/%f %p'
- archive_cleanup_command:从库清理已不需要的wal日志,避免磁盘空间撑满
archive_cleanup_command='pg_archivecleanup /data/PRD/postgres/10.7/pg5432/pg_archlog %r'
- recovery_end_command:恢复完成后执行指定命令
2. recovery target设置
下列选项进指定恢复目标
recovery_target:目前只能为immediate,指定恢复在达到一致状态后尽快结束,打开DB
recovery_target_name:由pg_create_restore_point()创建的还原点,用于恢复到指定还原点
recovery_target_time:恢复到指定时间点,最常用
recovery_target_xid:恢复到指定事务ID,在指定事务之前提交的事务将被恢复。注意事务ID是顺序分配的,但后分配的事务ID可能先完成。精确的停止点受recovery_target_inclusive影响。
recovery_target_lsn:恢复到WAL的指定LSN,精确的停止点也受 recovery_target_inclusive的影响。
下列选项进一步指定恢复目标,并且影响到达目标时会发生什么
recovery_target_inclusive:布尔值,指定恢复到恢复目标之后还是之前,默认为之后(true)
recovery_target_timeline:指定恢复的时间线。默认只沿着基础备份建立时时间线恢复而不会切换到新的时间线。通常设置为latest,这样便可恢复到该离当前最近的时间线。
recovery_target_action:指定在达到恢复目标时服务器采取的动作。
- pause:默认值,表示恢复将被暂停
- promote:表示恢复结束且服务器将开始接受连接
- shutdown:表示在达到恢复目标之后停止服务器。
使用pause的目的是恢复到最想要的位置。当确定已恢复到最想要的位置,可以使用pg_wal_replay_resume()结束暂停的状态,这会让恢复终结。如果恢复的位置不是想要的,那么关闭服务器,重新设置恢复目标,然后启动DB继续恢复。
注意在recovery_target_action被设置为shutdown时,recovery.conf将不会被重命名,任何后续的启动都将会以立刻关闭为终结,除非该配置被改变或者recovery.conf文件被手工移除。
如果没有设置恢复目标,这个设置没有效果。如果没有启用hot_standby,pause设置的动作将和shutdown一样。
http://postgres.cn/docs/10/recovery-target-settings.html
二、 时间线——pg中的平行世界
这个概念感觉类似Oracle的化身(Incarnation)和小说电影里的平行世界。虽然可以通过PITR恢复到之前的时间点,相当于小说里时光倒流主角重生了,但回到的不再是原来的世界,而是去到了一个平行世界。
1. 为什么需要时间线
还是拿小说举例子,重生的主角通常都担心自己做了一点什么事情会影响历史的进程,当然小说电视剧里主角的影响最后总是会被历史修复。那pg能够修复回退后的更改吗?
比如某天17点开发来找你说误操作了,要恢复到15点的数据。好的,我们给他恢复了。恢复之后业务运行了半个小时,开发又来找你说,刚才搞错了应该恢复到16点的数据,能够做到吗?
如果没有时间线的概念而在15点后又没另外做备份,能用之前的备份+归档恢复到16点的数据吗?显然是不能的,因为在DB运行过程中产生了与旧WAL文件重名的文件,归档时覆盖原来的日志,导致恢复到16点需要的WAL文件丢失。
阿里云的博客有张图挺形象的
2. 时间线的作用
为了解决这个问题,PostgreSQL引入了时间线的概念。每当归档文件恢复完成,创建一个新的时间线用来区别新生成的WAL记录。区别的方式很简单,就在WAL文件名里加入了时间线ID,由时间线和日志序号来组成WAL文件名,不会覆盖由以前的时间线生成的WAL。
$ ls -1
00000002.history
00000003.history
00000003000000000000001A
00000003000000000000001B
源码实现如下:
#define XLogFileName(fname, tli, log, seg) \snprintf(fname, XLOG_DATA_FNAME_LEN + 1, "%08X%08X%08X", tli, log, seg)
有了时间线,只要备份和归档还在,我们小说的主角就能够重生到任意时间点了,但每次其实都相当于去到了一个平行世界,保证主角重生之后的所作所为不影响原来的世界。每个时间线也类似一个分支,在当前时间线的操作不会对其他时间线WAL造成影响。
3. 何时会产生新时间线
-
利用归档进行恢复,完整恢复和PITR都会
-
从库激活为主库,即执行 pg_ctl promote –D $PGDATA
4. history文件
- 何时产生:与时间线相同,每当创建一个新的时间线,pg都会创建一个“时间线历史”文件,文件名类似.history。
- 内容:原时间线history文件的内容+一条当前时间线切换记录。
假设数据库恢复启动后,切换到新的时间线ID=5,那么文件名就是00000005.history ,该文件记录了自己是从什么时间哪个时间线什么原因分出来的(相当于主角重生之后还有记忆),该文件可能含有多行记录,每个记录的内容格式如下:
* <parentTLI> <switchpoint> <reason>** parentTLI ID of the parent timeline* switchpoint XLogRecPtr of the WAL position where the switch happened* reason human-readable explanation of why the timeline was changed
例如:
$ cat 00000004.history
1 0/140000C8 no recovery target specified
2 0/19000060 no recovery target specified
3 0/1F000090 no recovery target specified
当数据库在从包含多个时间线的归档中恢复时,这些history文件允许系统选取正确的WAL文件,当然,它也能像WAL文件一样被归档到WAL归档目录里。历史文件只是很小的文本文件,所以保存它们的代价很小。
当我们在recovery.conf指定目标时间线tli进行恢复时,程序首先寻找.history文件,根据.history文件里面记录的时间线分支关系,找到从pg_control里面的startTLI到tli之间的所有时间线对应的日志文件,再进行恢复。
参考
http://mysql.taobao.org/monthly/2015/07/03/
待补充