《PostgreSQL 指南:內幕探索》之基礎備份與時間點恢復(上)

資料和雲發表於2019-06-26

墨墨導讀:最近電子工業出版社博文視點出版了《PostgreSQL指南:內幕探索》,日前「資料和雲」公眾號推薦了這本書並贈送了五本,百多位使用者參與,幾十條留言未能放出,為了讓大家更好地學習開源資料PostgreSQL,經出版社官方授權,刊載本書部分章節內容以饗讀者,本文節選了第十章《基本備份與時間點恢復》10.1-10.2。

此外,我們也成立PostgreSQL學習社群,技術探討、資料分享、大牛解答,歡迎加入一起進步,入群方式見文末。

線上資料庫備份大致可分為邏輯備份和物理備份兩類,它們各自都有優點和缺點。邏輯備份有一個缺點,即執行需要花費大量的時間。特別是對於大型資料庫而言,需要花費很長時間進行備份,而從備份資料中恢復資料庫可能需要更長的時間。相反,物理備份可以在相對較短的時間內備份和恢復大型資料庫,因此在實際系統中,其是一個非常重要且實用的功能。

在PostgreSQL中,自8.0版本開始提供了線上的全量物理備份,整個資料庫集簇(即物理備份資料)的執行時快照被稱為基礎備份。

PostgreSQL還在8.0版中引入了時間點恢復(Point-In-Time Recovery,PITR)。這一功能可以將資料庫恢復至任意時間點,這通過使用一個基礎備份和由持續歸檔生成的歸檔日誌來實現。例如,即使你犯了一個嚴重的錯誤(如TRUNCATE所有的表),此功能還可以將資料庫恢復至錯誤發生之前的時刻。

本文描述了以下主題:

  • 基礎備份

  • 時間點恢復(PITR)的工作原理

  • 時間線與時間線歷史檔案

  • 時間點恢復與時間線歷史檔案

在7.4或更低版本中,PostgreSQL僅支援邏輯備份(全量邏輯備份、部分邏輯備份和資料匯出)。

基礎備份



《PostgreSQL 指南:內幕探索》之基礎備份與時間點恢復(上)

製作基礎備份

使用底層命令進行基本備份的標準過程上圖所示,具體步驟如下:

  1. 發出pg_start_backup命令。

  2. 使用你想用的歸檔命令獲取資料庫集簇的快照。

  3. 發出pg_stop_backup命令。

這個簡單的過程對於DBA來說很容易操作,因為它不需要特殊工具,只需要常用工具(如複製命令或類似的歸檔工具)來建立基本備份。此外,在此過程中,不需要獲取表上的鎖,所有使用者都可以在不受備份操作影響的情況下發起查詢。相對於其他開源的關係型資料庫,這是一個巨大的優勢。

更簡單的方式是使用pg_basebackup命令來做基礎備份,不過在其內部也是使用這些底層命令來工作的。

這些命令對顯然是理解PITR的關鍵點之一,我們將在後續章節中探討它們。

pg_start_backup和pg_stop_backup命令的定義在src/backend/access/transam/xlogfuncs.c中。


  • pg_start_backup

pg_start_backup開始為製作基礎備份進行準備工作。恢復過程從重做點開始,因此pg_start_backup必須執行檢查點,以便在製作基礎備份的開始時刻顯式建立一個重做點。此外,這次檢查點的位置必須儲存在非pg_control的其他檔案中,因為在備份期間可能會執行多次常規檢查點。

pg_start_backup執行下列4個操作:

  1. 強制進入整頁寫入模式。

  2. 切換到當前的WAL段檔案(8.4或更高版本)。

  3. 執行檢查點。

  4. 建立backup_label檔案 —— 該檔案建立於基本目錄頂層中,包含有關該基本備份本身的關鍵資訊,如檢查點的檢查點位置。

第3個和第4個操作是該命令的核心。第1和第2個操作是為了更可靠地恢復資料庫集簇。

備份標籤backup_label檔案包含以下7個專案:

  1. 檢查點位置 —— 該命令所建立檢查點的LSN位置。

  2. WAL開始位置——這不是給PITR用的,而是為第11章描述的流複製準備的。它被命名為START WAL LOCATION,因為複製模式下的備用伺服器在初始啟動時只讀取一次該值。

  3. 備份方法——這是用於進行此基本備份的方法,如pg_start_backup或pg_basebackup。

  4. 備份來源 —— 說明此備份是從主庫還是備庫拉取。

  5. 開始時間 —— 這是執行pg_start_backup時的時間戳。

  6. 備份標籤 —— 這是pg_start_backup中指定的標籤。

  7. 開始時間線 —— 這是備份開始的時間線,為了進行正常的檢查,在版本11.0中被引入。

備份標籤

一個9.6版本中備份標籤的實際例子如下所示:


postgres> cat /usr/local/pgsql/data/backup_label  START WAL LOCATION: 0/9000028 (file  000000010000000000000009)  CHECKPOINT LOCATION: 0/9000060  BACKUP METHOD: pg_start_backup  BACKUP FROM: master  START TIME: 2018-7-9 11:45:19 GMT  LABEL: Weekly Backup


可以想象,當使用此基礎備份恢復資料庫時,PostgreSQL從backup_label檔案中取出檢查點位置CHECKPOINTLOCATION,接著從歸檔日誌中的合適位置讀取檢查點記錄,然後從檢查點記錄中獲取重做點的位置,最後從重做點開始進行恢復。

  • pg_stop_backup

pg_stop_backup執行以下5個操作以完成備份:

  1. 如果pg_start_backup開啟了整頁寫入,那麼關閉整頁寫入。

  2. 寫入一條備份結束的XLOG記錄。

  3. 切換WAL段檔案。

  4. 建立一個備份歷史記錄檔案 —— 此檔案包含backup_label檔案的內容,以及已執行pg_stop_backup的時間戳。

  5. 刪除backup_label檔案 —— 從基礎備份恢復需要backup_label檔案,不過一旦被複制,原始的資料庫集簇就不需要該檔案了。

備份歷史檔案的命名方法如下所示:

{WAL段檔名}.{基礎備份開始時的偏移量}.backup

時間點恢復(PITR)的工作原理

下圖展示了PITR的基本概念。PITR模式下的PostgreSQL會在基礎備份上重放歸檔日誌中的WAL資料,從pg_start_backup建立的重做點開始,恢復到你想要的位置為止。在PostgreSQL中,想要恢復到的位置被稱為恢復目標。

《PostgreSQL 指南:內幕探索》之基礎備份與時間點恢復(上)

PITR的基本概念

PITR是如下這樣工作的。假設你在GMT時間2018-07-1612:05:00犯了錯誤,那麼就應該刪掉當前的資料庫集簇,並使用之前製作的基礎備份恢復一個新的,然後建立一個recovery.conf檔案,並在其中將recovery_target_time引數配置為犯錯誤的時間點,在本例中,也就是12:05 GMT。recovery.conf檔案如下所示:


# Place archivelogs under /mnt/server/archivedir directory.restore_command = 'cp /mnt/server/archivedir/%f %p'recovery_target_time = "2018-7-16 12:05 GMT"


在PostgreSQL啟動的時候,如果資料庫集簇中存在recovery.conf和backup_label檔案,就會進入恢復模式。

PITR過程幾乎與常規恢復過程一模一樣,唯一的區別只有以下兩點:

  1. 從哪裡讀取WAL段/歸檔日誌?

    1. 正常恢復模式 —— 來自基礎目錄下的pg_xlog子目錄(在10.0或更高版本中為pg_wal子目錄)。

    2. PITR模式 —— 來自配置引數archive_command中設定的歸檔目錄。

  2. 從哪裡讀取檢查點位置?

    1. 正常恢復模式 —— 來自pg_control檔案。

    2.    PITR模式 —— 來自backup_label檔案。

PITR流程概述如下:

  1. 為了找到重做點,PostgreSQL使用內部函式read_backup_label從backup_label檔案中讀取CHECKPOINTLOCATION的值。

  2. PostgreSQL從recovery.conf中讀取一些引數值,在此例中為restore_command和recovery_target_time。

  3. PostgreSQL開始從重做點重放WAL資料,重做點的位置可以簡單地從CHECKPOINT LOCATION的值中獲得。PostgreSQL執行引數restore_command中配置的命令,將歸檔日誌從歸檔區域複製到臨時區域,並從中讀取WAL資料,複製到臨時區域中的日誌檔案會在使用後被刪除。

  4. 在本例中,因為引數recovery_target_time被設定為該時間戳,所以PostgreSQL從重做點讀取並重放WAL資料,直到時間戳2018-7-1612:05:00為止。如果recovery.conf中沒有配置恢復目標,則PostgreSQL將重放至歸檔日誌的末尾。

  5. 當恢復過程完成時,會在pg_xlog子目錄(在10.0或更高版本中為pg_wal子目錄)中建立時間線歷史檔案,如00000002.history。如果啟用了日誌歸檔功能,則還會在歸檔目錄中建立相同的命名檔案。接下來各節會介紹此檔案的內容和作用。

  6. 提交和中止操作的記錄包含每個操作完成時的時間戳(兩個操作的XLOG資料部分分別在xl_xact_commit和xl_xact_abort中定義)。因此,如果將目標時間設定為引數recovery_target_time,只要PostgreSQL重放提交或中止操作的XLOG記錄,就可以選擇是否繼續恢復。當重放每個動作的XLOG記錄時,PostgreSQL會比較目標時間和記錄中寫入的每個時間戳,如果時間戳超過目標時間,PITR過程就會完成。

函式read_backup_label定義於src/backend/access/transam/xlog.c中。結構xl_xact_commit和xl_xact_abort定義於src/backend/access/transam/xlog.c中。


為什麼可以用一般歸檔工具做基礎備份?

儘管資料庫集簇可能是不一致的,但恢復過程是使資料庫集簇達成一致狀態的過程。由於PITR是基於恢復過程的,所以即使基礎備份是一堆不一致的檔案,它也可以恢復資料庫集簇。因此,我們可以在沒有檔案系統快照功能或其他特殊工具的情況下,使用一般歸檔工具做基礎備份。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556440/viewspace-2648864/,如需轉載,請註明出處,否則將追究法律責任。

相關文章