转载:PostgreSQL时间线的实现

前端之家收集整理的这篇文章主要介绍了转载:PostgreSQL时间线的实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
来自: http://zisedeqing.blog.163.com/blog/static/95550871201481115942717/、

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

猜你在找的Postgre SQL相关文章