38. PostgreSQL 備份與還原

有很多種方法可以備份 PostgreSQL 資料庫,而您選擇哪一種方法將很大程度取決於您如何使用該資料庫。

  • 對於相對靜態的資料庫,可以使用基本的 pg_dump/pg_restore 工具來定期建立資料快照。

  • 對於頻繁變更的資料,使用「線上備份」方案可以持續將更新存檔到安全的位置。

線上備份是 高可用性的複寫和備用系統的基礎,特別是對於 PostgreSQL >= 9.0 的版本。

38.1. 規劃您的資料

正如在 PostgreSQL 綱要中所討論的,確保生產資料始終儲存在單獨的綱要中是管理資料非常重要的**最佳實務**。原因有二:

  • 備份和還原綱要中的資料比管理要單獨備份的表格清單要簡單得多。

  • 將資料表格排除在「public」綱要之外可以更容易地進行升級,如 軟體升級 中所討論的。

38.2. 基本備份與還原

使用 pg_dump 公用程式可以輕鬆備份完整的資料庫。該公用程式是一個命令列工具,使其易於使用腳本自動化,也可以透過 PgAdmin 公用程式中的 GUI 來調用。

要備份我們的 nyc 資料庫,我們可以使用 GUI,只需右鍵點擊您要備份的資料庫即可

_images/backup1.jpg

輸入您要建立的備份檔案的名稱。

_images/backup2.jpg

請注意,有三個備份格式選項:壓縮、tar 和純文字。

  • 純文字 只是一個文字 SQL 檔案。這是最簡單的格式,並且在許多方面是最靈活的,因為它可以輕鬆編輯或更改,然後載回資料庫,允許對所有權或其他全域資訊進行離線更改。

  • Tar 使用 UNIX 封存格式將轉儲的組件保存在單獨的檔案中。使用 tar 格式允許 pg_restore 公用程式選擇性地還原轉儲的部分。

  • 壓縮 類似於 Tar 格式,但會單獨壓縮內部組件,允許選擇性還原它們而無需解壓縮整個封存。

我們將勾選「壓縮」選項,然後開始,儲存備份檔案。

可以使用如下的命令列完成相同的操作

pg_dump --file=nyc.backup --format=c --port=54321 --username=postgres nyc

由於備份檔案採用「壓縮」格式,我們可以透過 pg_restore 命令列出清單來檢視其內容。在 PgAdmin GUI 中,「檢視」是面板中的一個選項。

_images/backup3.jpg

當您檢視清單時,您可能會注意到其中有很多「FUNCTION」簽章。

_images/backup4.jpg

這是因為 pg_dump 公用程式會轉儲資料庫中的**每個**非系統物件,其中也包括 PostGIS 函數定義。

注意

PostgreSQL 9.1+ 包含一個「EXTENSION」功能,允許將 PostGIS 等附加套件安裝為已註冊的系統組件,因此將其排除在 pg_dump 輸出之外。PostGIS 2.0 及更高版本支援使用此擴充系統進行安裝。

我們可以透過直接使用 pg_restore 從命令列中看到相同的清單

pg_restore --list nyc.backup

包含 PostGIS 函數簽章的轉儲檔案的問題是,我們真正想要的是資料的轉儲,而不是我們的系統函數。

由於每個物件都在轉儲檔案中,我們可以還原到空白資料庫並獲得完整功能。這樣做時,我們預期我們要還原的系統具有與我們從中轉儲的系統完全相同的 PostGIS 版本(因為函數簽章定義參考特定版本的 PostGIS 共用程式庫)。

從命令列還原看起來像這樣

createdb --port 54321 nyc2
pg_restore --dbname=nyc2 --port 54321 --username=postgres nyc.backup

只轉儲資料,而不轉儲函數簽章,是在綱要中儲存資料方便的地方,因為有一個命令列標誌只轉儲特定的綱要

pg_dump --port=54321 -format=c --schema=census --file=census.backup

現在,當我們列出轉儲的內容時,我們只看到我們想要的資料表格

pg_restore --list census.backup

;
; Archive created at Thu Aug  9 11:02:49 2012
;     dbname: nyc
;     TOC Entries: 11
;     Compression: -1
;     Dump Version: 1.11-0
;     Format: CUSTOM
;     Integer: 4 bytes
;     Offset: 8 bytes
;     Dumped from database version: 8.4.9
;     Dumped by pg_dump version: 8.4.9
;
;
; Selected TOC Entries:
;
6; 2615 20091 SCHEMA - census postgres
146; 1259 19845 TABLE census nyc_census_blocks postgres
145; 1259 19843 SEQUENCE census nyc_census_blocks_gid_seq postgres
2691; 0 0 SEQUENCE OWNED BY census nyc_census_blocks_gid_seq postgres
2692; 0 0 SEQUENCE SET census nyc_census_blocks_gid_seq postgres
2681; 2604 19848 DEFAULT census gid postgres
2688; 0 19845 TABLE DATA census nyc_census_blocks postgres
2686; 2606 19853 CONSTRAINT census nyc_census_blocks_pkey postgres
2687; 1259 20078 INDEX census nyc_census_blocks_geom_gist postgres

只有資料表格很方便,因為這意味著我們可以儲存到安裝了任何版本的 PostGIS 的資料庫,正如我們在 軟體升級 中所討論的那樣。

38.2.1. 備份使用者

pg_dump 公用程式一次操作一個資料庫(如果您限制它的話,則一次操作一個綱要或表格)。但是,有關使用者的資訊儲存在整個叢集中,而不是儲存在任何一個資料庫中!

要備份您的使用者資訊,請使用 pg_dumpall 公用程式,並使用「--globals-only」標誌。

pg_dumpall --globals-only --port 54321

您也可以使用預設模式下的 pg_dumpall 來備份整個叢集,但請注意,與 pg_dump 一樣,您最終會備份 PostGIS 函數簽章,因此必須針對相同的軟體安裝還原轉儲,它不能用作升級過程的一部分。

38.3. 線上備份與還原

線上備份與還原允許管理員保留一套非常最新的備份檔案,而無需重複轉儲整個資料庫的開銷。如果資料庫處於頻繁的插入和更新負載下,則線上備份可能比基本備份更可取。

注意

了解線上備份的最佳方法是閱讀 PostgreSQL 手冊中關於 持續封存和時間點復原 的相關章節。PostGIS 工作坊的本節僅提供線上備份設定的簡要快照。

38.3.1. 運作方式

PostgreSQL 不是持續寫入到主資料表格,而是先將變更儲存在「預寫日誌」(WAL)中。這些日誌合在一起,就是對資料庫所做所有變更的完整記錄。線上備份包括複製資料庫主資料表格,然後複製之後產生的每個 WAL。

_images/backup5.jpg

當需要還原到新的資料庫時,系統會從主資料副本開始,然後將所有 WAL 檔案重播到資料庫中。最終結果是一個還原的資料庫,其狀態與接收到最後一個 WAL 時的原始資料庫相同。

由於 WAL 無論如何都會被寫入,並且將副本傳輸到封存伺服器的計算成本很低,因此線上備份是一種有效的方法,可以在不使用密集的常規完整轉儲的情況下,保持系統的最新備份。

38.3.2. 封存 WAL 檔案

設定線上備份的第一件事是建立封存方法。PostgreSQL 封存方法具有極大的靈活性:PostgreSQL 後端只會調用 archive_command 組態參數中指定的腳本。

這表示封存可以像將檔案複製到網路掛載磁碟機一樣簡單,也可以像加密檔案並透過電子郵件傳送到遠端封存一樣複雜。您可以編寫腳本的任何程序都可用於封存檔案。

要開啟封存,我們將編輯 postgresql.conf,首先開啟 WAL 封存

wal_level = archive
archive_mode = on

然後設定 archive_command 將我們的封存檔案複製到安全的位置(根據需要變更目的地路徑)

# Unix
archive_command = 'test ! -f /archivedir/%f && cp %p /archivedir/%f'

# Windows
archive_command = 'copy "%p" "C:\\archivedir\\%f"'

重要的是,封存命令不會覆寫現有的檔案,因此 unix 命令包含一個初始測試,以確保這些檔案不存在。同樣重要的是,如果複製過程失敗,則命令會傳回非零狀態。

進行變更後,您可以重新啟動 PostgreSQL 以使其生效。

38.3.3. 進行基本備份

封存過程就緒後,您需要進行基本備份。

將資料庫置於備份模式(這不會對查詢或資料更新的操作產生任何影響,它只會強制執行檢查點並寫入一個標籤檔案,指示何時進行備份)。

SELECT pg_start_backup('/archivedir/basebackup.tgz');

對於標籤,使用備份檔案的路徑是一種很好的做法,因為它可以幫助您追蹤備份的儲存位置。

將資料庫複製到封存位置

# Unix
tar cvfz /archivedir/basebackup.tgz ${PGDATA}

然後告訴資料庫備份過程已完成。

SELECT pg_stop_backup();

所有這些步驟當然都可以編寫腳本以進行常規的基本備份。

38.3.4. 從封存還原

這些步驟取自 PostgreSQL 手冊中關於 持續封存和時間點復原 的內容。

  • 如果伺服器正在執行,請停止它。

  • 如果您有足夠的空間,請將整個叢集資料目錄和任何表格空間複製到臨時位置,以備日後需要。請注意,此預防措施要求您的系統上有足夠的可用空間來容納現有資料庫的兩個副本。如果您沒有足夠的空間,您至少應儲存叢集的 pg_xlog 子目錄的內容,因為它可能包含系統關閉之前未封存的日誌。

  • 移除叢集資料目錄下和您正在使用的任何表格空間根目錄下的所有現有檔案和子目錄。

  • 從檔案系統備份還原資料庫檔案。請確保使用正確的所有權(資料庫系統使用者,而不是 root!)和正確的權限還原它們。如果您使用的是表格空間,則應驗證 pg_tblspc/ 中的符號連結是否已正確還原。

  • 移除 pg_xlog/ 中存在的任何檔案;這些檔案來自檔案系統備份,因此很可能已過時而非最新的。如果您根本沒有封存 pg_xlog/,則請使用適當的權限重新建立它,並注意確保如果您之前已設定為符號連結,則重新建立為符號連結。

  • 如果您在步驟 2 中儲存了未歸檔的 WAL 段檔案,請將它們複製到 pg_xlog/ 目錄中。(最好是複製它們,而不是移動它們,這樣如果發生問題而您必須重新開始時,您仍然可以擁有未修改的檔案。)

  • 在叢集資料目錄中建立一個復原指令檔 recovery.conf(請參閱第 26 章)。您可能還想暫時修改 pg_hba.conf,以防止普通使用者連線,直到您確定復原成功為止。

  • 啟動伺服器。伺服器將進入復原模式,並繼續讀取它需要的已歸檔 WAL 檔案。如果由於外部錯誤而終止復原,則只需重新啟動伺服器,它將繼續復原。完成復原程序後,伺服器會將 recovery.conf 重新命名為 recovery.done(以防止稍後意外重新進入復原模式),然後開始正常的資料庫操作。

  • 檢查資料庫的內容,以確保您已復原到所需的狀態。如果沒有,請回到步驟 1。如果一切順利,請將 pg_hba.conf 還原至正常狀態,允許您的使用者連線。