1.1基本原理
正常情况下,数据库是沿着一条时间线一直延伸的,但是如果中途,用户期望从归档中进行恢复,则这时数据库的时间线就会产生分支,沿着新的时间线延伸。如下图所示:
1.2基本流程
使用时间线进行恢复的基本流程是:
1.确定recoveryTargetTLI
即要恢复到的那个时间线
2.确定时间线集合expectedTLIs
3.Redo
根据expectedTLIs,确定正确的WAL文件
4.Redo结束,确定新的时间线
下面分别介绍这几部中在PG中是如何实现的。
1.3实现
1.3.1时间线的表示
使用TimeLineID表示一个时间线,实际上就是一个无符号的整型。时间线从1开始,然后依次递增。
1.3.2产生新的时间线
1.新时间线产生的时机
只有在启动时,从归档中进行恢复,才会产生新的时间线,否则一直沿着原来的时间线走。
2.History文件
在产生新的时间线时,会创建一个历史文件,叫做history文件:
? 命名规则:
NewTimeLine.history
? 内容:
父亲时间线|分出时的日志文件名|分出的原因
? 作用:
在归档恢复时,如果该归档中包含多个时间线,则可以帮助系统在恢复时找到正确的WAL文件。
? 生命周期:
每个history文件,在创建新的时间线时会被删除,但是其内容则会copy到新的history文件的开头。如下所示:
00000002.history的内容如下:
则00000003.history的内容如下:
? 归档
History文件在产生会,会“立即”进行归档,所以在归档目录中会存在完整的时间线历史文件的序列。
1.3.3恢复期间的时间线
在数据库正常运行期间,时间线是不会发生变化的,只有在归档恢复时才会发生时间线的变化,下面说明在恢复期间时间线时如何变化,以及如何使用时间线恢复到正确的位置。
1.3.3.1时间线的确定
恢复期间时间线的选择有如下的几种情况:
1.从控制文件里面记录的checkpoint记录得到时间线:
recoveryTargetTLI =ControlFile->checkPointCopy.ThisTimeLineID;
2.从recovery.conf中读取用户配置的时间线
a)如果用户没有设置时间线,则时间线不变;
b)如果用户设置的时间线为0,则表示用户期望回复到最新的时间线
确定最新时间线的方法是:
从recoveryTargetTLI记录的时间线开始,这个扫描history文件,直到找到不存在history文件的那个时间线。
c)如果用户设置的时间线大于 0 ,则使用该时间线;
确定好恢复时要恢复到的时间线后,我们需求验证该时间线的有效性:
判断是否存在history文件,如果不存在,则是无效的时间线,系统退出;
时间线为1的时间线是没有history文件的,因为它没有parent时间线。
1.3.3.2时间线的使用
1.使用history文件确定expectedTLIs
a)expectedTLIs是恢复期间可能需要扫描的时间线的集合,它记录的在恢复期间可能的会使用到的WAL文件所在的时间线。
b)扫描history文件,把history文件中的每个parent时间线添加到expectedTLIs链表头部,最后把recoveryTargetTLI加到链表头部
2.使用expectedTLIs
a)WAL日志文件的名字是由TLI+logid+segment组成的,所以必须找到正确的时间线才能选择正确的WAL文件;
b)找到正确的WAL文件
i.根据recptr,计算logid和segno
ii.从前往后遍历expectedTLIs链表
根据每个时间线,拼成WAL文件名,然后试图打开该文件,如果文件不存在,则继续遍历,直到找到存在的文件
iii.如果没有找到WAL文件,则报错
c)对于logid和segno相同的WAL文件
i.通过b),找到正确的WAL文件
ii.对于logid和segno相同的WAL文件,其TLI必然不同,我们选择在expectedTLIs链表位置靠前的那个时间线上的WAL文件,这样做的原因是:
u 恢复必然从某个checkpoint日志开始;
u 而恢复开始的checkpoint日志必然在TLI大的那个WAL文件内,原因是:
l 日志redo完成后,我们是先创建新的时间线,然后在请求做checkpoint。
u 所以checkpoint之后的日志也必然在TLI大的那个WAL文件内。
3.文件源的选择
a)默认是从XLOG_FROM_PG_XLOG里面,如果是归档恢复,则在加上XLOG_FROM_ARCHIVE
b)在选择WAL文件时,先从归档里面找,如果找不到,再从pg_xlog里面找
c)如果都没有找到,则报错
4.恢复完成后新时间线的创建
a)归档恢复后,我们选择创建新的时间线,原因:
i.本次恢复后,产生的日志文件都在新的时间线上,不会覆盖就的时间先上的日志;
ii.如果发现本次恢复不是想要的结果,则可以再次直到恢复的时间线,不会由于日志覆盖该导致恢复失败;
b)确定新的时间线
i.从recoveryTargetTLI往后找,直到找到不存在history的时间线;
ii.然后对该时间线加1,就是本次恢复后的新的时间线
u 所以,即使我们恢复到之前的时间线,也不会导致时间线不惟一;
u +1的原因是,不存在history的那个时间先应该是归档恢复之前使用的当前的时间线,所以需要加1;
5.Redo的结束
a)在只设置了TLI的情况下,redo完recoveryTargetTLI的日志后,redo操作结束;
结束方式:
在读取下一条日志时,如果在expectedTLIs内找不到适当的WAL文件,则终止redo
b)在设置了TLI时,redo的终止点只会比TLI的时间点早,而不会比它晚,原因是redo需要的日志文件必须在expectedTLIs内。
--------------- -rw------- 1 wln wln 16777216 07-12 10:30 000000020000000000000019 -rw------- 1 wln wln 16777216 07-07 15:41 00000002000000000000001A -rw------- 1 wln wln 41 07-06 08:41 00000002.history -rw------- 1 wln wln 16777216 07-12 10:31 000000030000000000000019 -rw------- 1 wln wln 16777216 07-12 10:31 00000003000000000000001A -rw------- 1 wln wln 84 07-12 10:31 00000003.history -rw------- 1 wln wln 16777216 07-12 12:49 000000040000000000000019 -rw------- 1 wln wln 16777216 07-12 10:39 00000004000000000000001A -rw------- 1 wln wln 127 07-12 10:38 00000004.history drwx------ 2 wln wln 4096 07-12 10:38 archive_status [wln@localhost pg_xlog]$ cat 00000002.history 1 0/602445C no recovery target specified [wln@localhost pg_xlog]$ cat 00000003.history 1 0/602445C no recovery target specified 2 0/19FBD5DC no recovery target specified [wln@localhost pg_xlog]$ cat 00000004.history 1 0/602445C no recovery target specified 2 0/19FBD5DC no recovery target specified 3 0/19FBD6FC no recovery target specified http://MysqL.taobao.org/monthly/2015/07/03/ 原文链接:https://www.f2er.com/postgresql/195590.html