Chapter 22. 備份和恢復

Table of Contents
22.1. SQL 轉儲
22.1.1. 從轉儲中恢復
22.1.2. 使用 pg_dumpall
22.1.3. 大數據庫
22.1.4. 注意
22.2. 文件系統級別的備份
22.3. 在不同版本之間遷移

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

備份 PostgreSQL 數據有兩個完全不同的方法:

22.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 19)裡描述。

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

Important: 如果你的數據庫結構依賴于 OID (比如說用做外鍵),那麼你必須告訴 pg_dump 把 OID 也倒出來。 要倒 OID,可以使用 -o 命令行選項。 缺省時也不會轉儲"大對象"。如果你使用大對象,請參考 pg_dump的命令手冊頁。

22.1.1. 從轉儲中恢復

pg_dump 生成的文本文件可以由 psql 程序讀取。從轉儲中恢復的常用命令是

psql dbname < infile

這裡的 infile 就是你 給pg_dump命令的 outfile 參數。這條命令不會創建數據庫 dbname,你必須在執行psql 前自己從template0創建(也就是說,用命令 createdb -T template0 dbname)。 psql 支持類似 pg_dump 的選項用以控制數據庫服務器位置和用戶名。參考它的手冊獲取更多信息。

如果在原先數據庫裡的對象屬于不同的用戶,那麼轉儲的文件會指示 psql 以各個受影響的用戶輪流聯接然後再創建相關的對象。 這樣就保留了原來的所有權屬性。不過這樣也意味著所有這些用戶必須已經存在,而且你還必須能夠以每個用戶的身份聯接。 所以我們可能需要臨時放鬆一下客戶認證的設置。

一旦完成恢復,在每個數據庫上運行 ANALYZE 是明智的舉動, 這樣優化器就有有用的統計數據了。你也可以運行 vacuumdb -a -zANALYZE 所有數據庫。

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

pg_dump -h host1 dbname | psql -h host2 dbname

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

提示: 恢復的性能可以通過增加配置參數 sort_mem 來改進 (參閱 Section 16.4.2.1)。

22.1.2. 使用 pg_dumpall

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

pg_dumpall > outfile

生成的轉儲可以用 psql 恢復:

psql template1 < infile

(實際上,你可以聲明任意現有的數據庫進行連接,但是如果你是向一個空 的數據庫裝載,那麼 template1 是你唯一的選擇。) 恢復pg_dumpall的轉儲的時候通常需要數據庫超級用戶權限, 因為我們需要它來恢復用戶和組信息。

22.1.3. 大數據庫

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

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

pg_dump dbname | gzip > filename.gz

用下面命令恢復:

createdb dbname
gunzip -c filename.gz | psql dbname

或者

cat filename.gz | gunzip | psql dbname

使用 split。. 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 的手冊獲取細節。

22.1.4. 注意

pg_dump (以及蘊涵的 pg_dumpall))有幾個限制,這些限制的來源是我們很難從系統表中重構某些信息。

具體說來,pg_dump 寫對象的順序並不復雜。 這樣可能導致問題,比如說當把函數用做字段缺省值時。 唯一的解決方法是手工為轉儲重新排序。如果你在數據庫設計裡面創建了循環依賴關系,那你就有更多事要做了。

出于向下兼容的考慮,缺省的時候 pg_dump 並不轉儲大對象。 要轉儲大對象,你必須使用客戶化或者 TAR 輸出格式, 並且在 pg_dump 中使用-b選項。 參閱相應手冊獲取詳細信息。在 PostgreSQL 源碼樹的 contrib/pg_dumplo 路徑裡也包含一個可以轉儲大對象的程序。

請熟悉一下 pg_dump 的手冊頁。