「時間線」(Timeline)是PG一個頗有特點的概念,在備份恢復方面的文檔裏面時有出現。但針對這個概念的詳細解釋卻不多,也讓人不太好理解,咱們在此仔細解析一下。mysql
爲了理解引入時間線的背景,咱們來分析一下,若是沒有時間線,會有什麼問題?先舉個將數據庫恢復到之前時間點的例子。假設在一個數據庫的運行過程 中,DBA在週三12:00AM刪掉了一個關鍵的表,可是直到週五中午才發現這個問題。這個時候DBA拿出最初的數據庫備份,加上存在歸檔目錄的日誌文 件,將數據庫恢復到週三11:00AM的時間點,這樣就能正常啓動和運行。可是,DBA後來意識到這樣恢復是不對的,想恢復到週四8:00AM的數據,這 時會發現沒法作到:由於在數據庫不斷運行中,會產生與舊的WAL文件重名的文件,這些文件進入歸檔目錄時,會覆蓋原來的舊日誌,致使恢復數據庫須要的 WAL文件丟失。爲了不這種狀況,須要區分原始數據庫歷史生成的WAL文件和完成恢復以後繼續運行產生的(重名的)新WAL文件。整個過程如圖1所示:sql
爲了解決這個問題,PostgreSQL引入了時間線的概念。每當歸檔文件恢復完成後,建立一個新的時間線用來區別新生成的WAL記錄。WAL文件名由時間線和日誌序號組成,源碼實現以下:數據庫
#define XLogFileName(fname, tli, log, seg) \ snprintf(fname, XLOG_DATA_FNAME_LEN + 1, "%08X%08X%08X", tli, log, seg)
例如:app
$ ls -1 00000002.history 00000003.history 00000003000000000000001A 00000003000000000000001B
時間線ID號是WAL文件名組成之一,所以一個新的時間線不會覆蓋由之前的時間線生成的WAL。如圖2所示,每一個時間線相似一個分支,在當前時間線的操做不會對其餘時間線WAL形成影響,有了時間線,咱們就能夠恢復到以前的任什麼時候間點。post
What happens at a end of recovery?spa
Example: End of recovery3d
LOG: database system was interrupted; last known up at 2013-01-30 21:45:14 EET LOG: starting archive recovery LOG: redo starts at 13/E00000C8 LOG: could not open file "pg_xlog/0000000100000013000000E4": No such file or directory LOG: redo done at 13/E3D389A0 LOG: last completed transaction was at log time 2013-01-30 21:45:20+02 LOG: selected new timeline ID: 2 LOG: archive recovery complete LOG: database system is ready to accept connections
First WAL file with new timelinerest
Timeline history file日誌
0000000100000013000000E1 0000000100000013000000E2 0000000100000013000000E3 0000000100000013000000E4 0000000100000013000000E5 00000002.history 0000000200000013000000E3 0000000200000013000000E4 0000000200000013000000E5
Timeline history filepostgresql
新的時間線會在什麼狀況下出現呢?
一、即時恢復(PITR)
配置recovery.conf文件:
restore_command = 'cp /mnt/server/archivedir/%f %p' //從歸檔目錄恢復日誌 recovery_target_time = '2015-7-16 12:00:00 ' //指定歸檔時間點,如沒指定恢復到故障前的最後一完成的事務 recovery_target_timeline = 'latest' //指定歸檔時間線,’latest’表明最新的時間線分支,如沒指定恢復到故障前的pg_control裏面的時間線 standby_mode = ‘off’ //打開後將會以備庫身份啓動,而不是即時恢復
設置好recovery.conf文件後,啓動數據庫,將會產生新的timeline,並且會生成一個新的history文件。恢復的默認行爲是沿着與當前基本備份相同的時間線恢復。若是你想恢復到某些時間線,你須要指定的recovery.conf目標時間線recovery_target_timeline
,不能恢復到早於基本備份分支的時間點。
二、standby promote
搭建一個PG主備,而後中止主庫,在備庫機器執行:
$ pg_ctl promote –D $PGDATA
這時候備庫將會升爲主備,同時產生一個新的timeline,一樣生成一個新的history文件。
每次建立一個新的時間線,PostgreSQL都會建立一個「時間線歷史」文件,文件名相似.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之間的全部時間線對應的日誌文件,再進行恢復。
PG中經過timeline機制可以方便地實現數據庫恢復到任意時間點,這對咱們數據庫備份有重要的做用。咱們能夠在數據庫的使用中合理地備份和歸檔咱們的數據,一旦數據出現丟失或損壞,咱們都能有條不紊的使用timeline機制恢復出來咱們須要的數據。
參考:
http://mysql.taobao.org/monthly/2015/07/03/
https://wiki.postgresql.org/images/e/e5/FOSDEM2013-Timelines.pdf