天天看點

轉載:PostgreSQL時間線的實作

來自: http://zisedeqing.blog.163.com/blog/static/95550871201481115942717/、

1.1    基本原理

正常情況下,資料庫是沿着一條時間線一直延伸的,但是如果中途,使用者期望從歸檔中進行恢複,則這時資料庫的時間線就會産生分支,沿着新的時間線延伸。如下圖所示:

轉載:PostgreSQL時間線的實作

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的内容如下:

轉載:PostgreSQL時間線的實作

則00000003.history的内容如下:

轉載:PostgreSQL時間線的實作

?  歸檔

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

[[email protected] pg_xlog]$ cat 00000002.history

1       0/602445C       no recovery target specified

[[email protected] pg_xlog]$ cat 00000003.history

1       0/602445C       no recovery target specified

2       0/19FBD5DC      no recovery target specified

[[email protected] 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/

繼續閱讀