Chapter 9. 備份和恢復

Table of Contents
9.1. SQL 轉儲
9.1.1. 從轉儲中恢復
9.1.2. 使用 pg_dumpall
9.1.3. 大資料庫
9.1.4. 注意
9.2. 文件系統級別的備份
9.3. 在不同版本之間遷移

和任何包含珍貴資料的東西一樣,PostgreSQL 資料庫也應該經常備份.盡管這個過程相當簡單, 但是我們還是應該理解做這件事所 用的技巧和假設.

備份 PostgreSQL 資料有兩個完全不同的方法:

9.1. SQL 轉儲

SQL 轉儲的方法採用的主意是建立一個純文字文件,這個純文字裡面都是 SQL 命令,當把這個文件回饋給伺服器時,將重建與轉儲時狀態一樣 的資料庫. PostgreSQL 為這個用途提供了應用工具 pg_dump.這條命令的基本用法是:

pg_dump dbname > outfile

正如你所見,pg_dump 把結果輸出到標準輸出. 我們下面就可以看到這樣做有什麼好處.

pg_dump 是一個普通的 PostgreSQL 客戶端應用(盡管是個相當聰明的東西.)這就意味著你可以從 任何可以存取該資料庫的遠端主機上面進行備份工作.但是請記住 pg_dump不會以任何特殊權限運行.具體說來,就是 你必須要有你想備份的表的讀權限,因此,實際上你幾乎總是要成為 資料庫超級使用者.

要宣告 pg_dump 應該以哪個使用者身份進行連結,使用命令行 選項 -h host-p port.預設 主機是本地主機或你的環境變數PGHOST宣告的值. 類似,預設連接埠是環境變數PGPORT或(如果它 不存在的話)編譯好了的預設值.(比較方便的是,伺服器通常有相同 的預設.)

和任何其他 PostgreSQL 客戶端應用一樣, pg_dump 預設時用與目前操作系統使用者名同名的資料庫使用者 名進行連結.要覆蓋這個名字,要麼宣告 -U 選項, 要麼設定環境變數PGUSER. 請注意 pg_dump 的連結也和普通客戶應用一樣要 通過客戶認証機制(在 Chapter 4)裡描述.

pg_dump 建立的備份在內部是一致的, 也就是說,在pg_dump運行的時候對資料庫的更新 將不會被轉儲.pg_dump 工作的時候並不阻塞 其他的對資料庫的操作.(但是會阻塞那些需要排它鎖的操作,比如 VACUUM FULL.)

Important: 如果你的資料庫結構依賴於 OID (比如說用做外鍵),那麼你必須告訴 pg_dump 把 OID 也倒出來. 要倒 OID,可以使用 -o 命令行選項. 預設時也不會轉儲"大物件".如果你使用大物件,請參考 pg_dump的命令手冊頁.

9.1.1. 從轉儲中恢復

pg_dump 生成的純文字文件可以由 psql 程式讀取. 從轉儲中恢復的常用命令是

psql dbname < infile

這裡的 infile 就是你 給pg_dump命令的 outfile 參數.這條命令不會建立資料庫 dbname,你必須在執行psql 前自己從template0建立(也就是說,用命令 createdb -T template0 dbname). psql 支援類似 pg_dump 的選項用以控制資料庫伺服器位置 和使用者名.參考它的手冊獲取更多資訊.

如果在原先資料庫裡的物件屬於不同的使用者,那麼轉儲的文件會指示 psql 以各個受影響的使用者輪流連結然後再建立相關的物件. 這樣就保留了原來的所有權屬性.不過這樣也意味著所有這些使用者必須 已經存在,而且你還必須能夠以每個使用者的身份連結. 所以我們可能需要臨時放松一下客戶認証的設定.

pg_dumppsql 可以通過管道 讀寫,這樣我們就可能從一台主機上將資料庫目錄轉儲到另一台主機上, 比如

pg_dump -h host1 dbname | psql -h host2 dbname

Important: pg_dump生成的轉儲輸出是相對於template0的.這就意味著任何 加入到template1的語言,過程等都會經由 pg_dump 轉儲.結果是,在恢復的時候,如果你使用的是客戶化的template1, 那麼你必須從template0中建立空的資料庫,就象我們上面的範例那樣.

9.1.2. 使用 pg_dumpall

上面的方法在備份整個資料庫集群的時候比較麻煩而且不方便.因此我們 提供了 pg_dumpall 程式. pg_dumpall 備份一個給出的集群中的每個資料庫,同時 還確保保留象使用者和組這樣的全局資料狀態.調用 pg_dumpall 很簡單

pg_dumpall > outfile

象上面描寫的那樣,轉儲出的文件可以用 psql 恢復. 不過這時候你絕對需要資料庫超級使用者權限,因為我們需要它來恢復 使用者和組資訊.

9.1.3. 大資料庫

致謝: 最早由 Hannu Krosing ()寫於 1999-06-19。

因為 PostgreSQL 允許表的大小大於你的系統允許的最大文件大小, 可能把表轉儲到一個文件會有問題,因為生成的文件很 可能比你的系統允許的最大文件大。 因為 pg_dump 輸出到 stdout, 你可以用標準的 *nix 工具繞開這個問題:

使用壓縮的轉儲. 使用你熟悉的壓縮程式,比如說 gzip

pg_dump dbname | gzip > filename.gz

用下面命令恢復:

createdb dbname
gunzip -c filename.gz | psql dbname

或者

cat filename.gz | gunzip | psql dbname

使用 split.. 你可以用下面的方法把輸出分解成操作系統可以接受的大小. 比如,讓每個塊大小為 1 兆字節:

pg_dump dbname | split -b 1m - filename

用下面命令恢復:

createdb dbname
cat filename* | psql dbname

使用客戶化轉儲格式. 如果PostgreSQL是在一個安裝了zlib 壓縮庫的系統上制作的, 那麼客戶化轉儲格式將在寫入輸出文件的時候壓縮資料. 對於大資料庫而言,它會生成和使用gzip 類似的轉儲大小的文件, 但是還附加了一個優點:你可以有選擇地恢復庫中的表. 下面的命令用客戶化轉儲格式轉儲一個資料庫:

pg_dump -Fc dbname > filename

請參考 pg_dumppg_restore 的手冊獲取細節.

9.1.4. 注意

pg_dump (以及建筑在其上的 pg_dumpall))有幾個限制,這些限制的來源是 我們很難從系統表中 重構某些資訊.

具體說來,pg_dump 寫物件的順序並不復雜.這樣可能 導致問題,比如說當把函數用做欄位預設值時.唯一的解決方法是 手動為轉儲重新排序.如果你在資料庫設計裡面建立了循環依賴 關系,那你就有更多事要做了.

出於向下兼容的考慮,預設的時候 pg_dump 並不 轉儲大物件.要轉儲大物件,你必須使用客戶化或者 TAR 輸出格式, 並且在 pg_dump 中使用-b選項. 參閱相應手冊獲取詳細資訊.在 PostgreSQL 源碼樹的 contrib/pg_dumplo 路徑裡也包含一個可以轉儲大物件的 程式.

請熟悉一下 pg_dump 的手冊頁.