PostgreSQL 時間線解析
“時間線”(Timeline)是PG一個很有特色的概念,在備份恢複方麵的文檔裏麵時有出現。但針對這個概念的詳細解釋卻很少,也讓人不太好理解。我們在此仔細解析一下。
時間線的引入
為了理解引入時間線的背景,我們來分析一下,如果沒有時間線,會有什麼問題?先舉個將數據庫恢複到以前時間點的例子。假設在一個數據庫的運行過程中,DBA在周三12:00AM刪掉了一個關鍵的表,但是直到周五中午才發現這個問題。這個時候DBA拿出最初的數據庫備份,加上存在歸檔目錄的日誌文件,將數據庫恢複到周三11:00AM的時間點,這樣就能正常啟動和運行。但是,DBA後來意識到這樣恢複是不對的,想恢複到周四8:00AM的數據。這時會發現無法做到:因為在數據庫不斷運行中,會產生與舊的WAL文件重名的文件,這些文件進入歸檔目錄時,會覆蓋原來的舊日誌,導致恢複數據庫需要的WAL文件丟失。為了避免這種情況,需要區分原始數據庫曆史生成的WAL文件和完成恢複之後繼續運行產生的(重名的)新WAL文件。整個過程如圖1所示:
為了解決這個問題,PostgreSQL引入了時間線的概念。每當歸檔文件恢複完成後,創建一個新的時間線用來區別新生成的WAL記錄。WAL文件名由時間線和日誌序號組成,源碼實現如下:
#define XLogFileName(fname, tli, log, seg) \
snprintf(fname, XLOG_DATA_FNAME_LEN + 1, "%08X%08X%08X", tli, log, seg)
例如:
$ ls -1
00000002.history
00000003.history
00000003000000000000001A
00000003000000000000001B
時間線ID號是WAL文件名組成之一,因此一個新的時間線不會覆蓋由以前的時間線生成的WAL。 如圖2所示,每個時間線類似一個分支,在當前時間線的操作不會對其他時間線WAL造成影響。有了時間線,我們就可以恢複到之前的任何時間點。
新時間線的出現場景
新的時間線會在什麼情況下出現呢?
1. 即時恢複(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,不能恢複到早於基本備份分支的時間點。
2. standby promote
搭建一個PG主備,然後停止主庫,在備庫機器執行:
$ pg_ctl promote –D $PGDATA
這時候備庫將會升為主備,同時產生一個新的timeline,同樣生成一個新的history文件。
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機製恢複出來我們需要的數據。
最後更新:2017-04-01 13:44:35
上一篇:
MySQL · 引擎特性 · InnoDB Change Buffer介紹
下一篇:
MySQL · 引擎特性 · InnoDB Adaptive hash index介紹
漲姿勢,為什麼開源項目都愛把動物作為品牌 Logo ?
《vSphere性能設計:性能密集場景下CPU、內存、存儲及網絡的最佳設計實踐》一1.1.4 從默認值開始
C++字符串完全指引之一 —— Win32 字符編碼
Java並發——Synchronized優化(輕量級鎖、偏向鎖)
從多租戶隔離到高可用,談DaoShip微服務架構演進
PostgreSQL Oracle 兼容性之 - substrb (基於字節的字符串截取)
JAVA加密與解密
ZED-Board從入門到精通係列——插曲
phpmyadmin 出現Cannot start session without errors 錯誤 總結的幾種原因和解決辦法
Python簡史