Postgresql的三種備份方式


 數據庫的備份有多種分類方式。按照備份后的文件類型,可以分為物理備份(文件系統級別的備份)和邏輯備份(備份后的文件是sql文件或特定格式的導出文件);按照備份過程中是否停止數據庫服務,可分為冷備份(備份過程中停止數據庫服務)和熱備份(備份過程中數據庫服務開啟並可供用戶訪問);按照備份是否是完整的數據庫,可分為全量備份(備份是完整的數據庫)和增量備份(備份是上一次全量備份后數據庫改變的內容)。

       Postgresql的常見備份方式有以下三種:

        1. 文件系統級別的冷備份。

        這種備份方式需要關閉數據庫,然后拷貝數據文件的完整目錄。恢復數據庫時,只需將數據目錄復制到原來的位置。該方式實際工作中很少使用。

 

        2. SQL轉儲。

        這里我們用到的工具是pg_dump和pg_dumpall。

        這種方式可以在數據庫正在使用的時候進行完整一致的備份,並不阻塞其它用戶對數據庫的訪問。它會產生一個腳本文件,里面包含備份開始時,已創建的各種數據庫對象的SQL語句和每個表中的數據。可以使用數據庫提供的工具pg_dumpall和pg_dump來進行備份。pg_dump只備份數據庫集群中的某個數據庫的數據,它不會導出角色和表空間相關的信息,因為這些信息是整個數據庫集群共用的,不屬於某個單獨的數據庫。pg_dumpall,對集簇中的每個數據庫調用pg_dump來完成該工作,還會還轉儲對所有數據庫公用的全局對象(pg_dump不保存這些對象)。 目前這包括適數據庫用戶和組、表空間以及適合所有數據庫的訪問權限等屬性。

        例如,在我的計算機上,可使用如下命令對名為dbname的數據庫進行備份:

        pg_dump  –h 127.0.0.1  -p  5432  -U  postgres -c  -C –f  dbname.sql  dbname

        使用如下命令可對全部pg數據庫進行備份。

        pg_dumpall –h 127.0.0.1 –p 5432 -U postgres –c  -C –f db_bak.sql

        恢復方式很簡單。執行恢復命令即可:

        psql –h 127.0.0.1 -p 5432 -U postgres –f db_bak.sql

 

       3. 連續歸檔

        這種方式的策略是把一個文件系統級別的全量備份和WAL(預寫式日志)級別的增量備份結合起來。當需要恢復時,我們先恢復文件系統級別的備份,然后重放備份的WAL文件,把系統恢復到之前的某個狀態。這種備份有顯著的優點:

  1. 不需要一個完美的一致的文件系統備份作為開始點。備份中的任何內部不一致性將通過日志重放來修正。
  2. 可以結合一個無窮長的WAL文件序列用於重放,可以通過簡單地歸檔WAL文件來達到連續備份。
  3. 不需要重放WAL項一直到最后。可以在任何點停止重放,並使數據庫恢復到當時的一致狀態。
  4. 可以連續地將一系列WAL文件輸送給另一台已經載入了相同基礎備份文件的機器,得到一個實時的熱備份系統。

 

        如何進行連續歸檔呢?

        下面的實例中,操作系統為windows 10,Postgresql的版本為9.6。

        首先,需要修改postgresql.conf文件的幾個參數修改如下:

        wal_level = ‘replica’

        archive_mode = ‘on’

        archive_command = 'copy  /y  "%p"  "D:\\archive\\%f"'

        archive_command執行時,%p會被要被歸檔的文件路徑所替代,而%f只會被文件名所替代。如果你需要在命令中嵌入一個真正的%字符,可以使用%%。 “D:\\archive\\”替換為歸檔日志的存放路徑,要確保歸檔的目錄是存在的。

        之后需要重啟數據庫使配置生效。

 

        接下來需要制作一個非排他的基礎備份。Postgresql提供了排他備份和非排他備份兩種備份方式,推薦使用非排他的備份方式。

        1. 作為一個具有運行 pg_start_backup 權利的用戶連接到服務器(不在乎是哪個數據庫)並且發出命令:

Select pg_start_backup('backup_label', false, false);

        2. 對數據庫進行一次文件系統級別的備份。即將postgresql的安裝目錄下的data目錄及其內容復制到其他位置。

        3. 在同一個連接中,發出命令:

        select * from pg_stop_backup(false);

         這個命令代表結束一次非排他的備份。

        現在來看基於時間點的恢復。

        假如你的數據庫出現了故障,需要恢復到之前的某個時刻的一致的狀態,就需要進行基於時間點的恢復。

其過程是:

1. 如果服務器仍在運行,停止它。

2. 如果你具有足夠的空間,將整個集簇數據目錄和表空間復制到一個臨時位置。注意最好是拷貝而不是移動。如果你沒有足夠的空間,你至少要保存集簇的pg_xlog子目錄的內容,因為它可能包含在系統垮掉之前還未被歸檔的日志。

3. 移除data 目錄及其所有子文件和子目錄。

4. 從文件系統備份中恢復數據庫文件。注意它們要使用正確的用戶恢復並且使用正確的權限。如果你在使用表空間,你應該驗證pg_tblspc/中的符號鏈接被正確地恢復。

5.現在已經從備份中恢復了整個數據目錄,接下來,你需要部分或全部刪除數據目錄中的下列文件,如果它們存在:

    (1) postmaster.pid;(必須)

    (2) pg_xlog中的文件;(必須)

    (3) pgsql_tmp開頭的臨時文件;(可選)

    (4) postgresql.auto.conf.tmp;(可選)

    (5) pg_replslot目錄中的文件;(可選)

    (6) pg_stat_tmp目錄中的文件。(可選)

6. 如果你有在第2步中保存的未歸檔WAL段文件,把它們拷貝到pg_xlog/中或WAL日志的歸檔目錄中。

在集簇數據目錄中創建一個恢復命令文件recovery.conf。如果你想恢復到最近的一致狀態,在recovery.conf寫入如下兩行:

restore_command = 'copy /y D:\\archive \\%f\\%p'

recovery_target_timeline = 'latest'

其中,restore_command的內容表示將歸檔日志文件夾中的內容拷貝到pg_xlog,其參數的含義與上文archive_command的參數含義完全相同;recovery_target_timeline = 'latest' 表示恢復到最近的時間點。

        7. 如果要阻止普通用戶在成功恢復之前連接,請修改pg_hba.conf。

        8. 啟動服務器。服務器將會進入到恢復模式並且進而根據需要讀取歸檔WAL文件。恢復可能因為一個外部錯誤而被終止,可以簡單地重新啟動服務器,這樣它將繼續恢復。恢復過程結束后,服務器將把recovery.conf重命名為recovery.done(為了阻止以后意外地重新進入恢復模式),並且開始正常數據庫操作。

        9. 檢查數據庫的內容來確保你已經恢復到了期望的狀態。如果沒有,返回到第1步。如果一切正常,通過恢復pg_hba.conf為正常來允許用戶連接。

這樣就完成了一次文件系統級別的全量備份,並實現了WAL文件級別的增量備份。

 

附:pg_start_backup() 和 pg_stop_backup()做了什么?

       1. pg_start_backup()

        pg_start_backup() 的函數原型如下:

        pg_start_backup(label text [, fast boolean [, exclusive boolean ]])

        其中label是用來唯一標識這次備份操作的任意字符串,fast 表示是否立即執行強制的檢查點,exclusive 表示該備份是否是一個排他備份。

        使用該函數時,推薦將exclusive設置為false,即非排他方式備份。

       執行下面的命令:

        Select pg_start_backup('backup_label', false, false);

        這條命令會產生三個動作:

         1. 在緩沖區中創建兩個變量:label_file和tblspc_map_file。前者包含WAL的起始位置、檢查點的起始位置、備份方法、備份模式、備份開始時間和備份標簽的名稱(本例中,名稱為“backup_label”)等信息;后者包含 “pg_tblspc/”中表空間符號鏈接的信息,如果它們存在。

        2. 強制發生一次檢查點。將檢查點開始前提交的事務對數據庫的修改刷新到磁盤。

        3. 置寫日志標志為:XLogCtl->Insert.forcePageWrites = true。把這個標志設置為true后,如果在備份期間時有其他事務修改數據庫,那么系統會把被修改的數據頁在修改前的完整頁面都記錄到WAL中,而不僅僅是記錄頁面中的變化的部分。

        為什么要將完整的頁面記錄到WAL中呢?

        原因是在備份過程中,其他事務修改數據庫,可能會造成備份后的數據存在新舊數據混合的情況,甚至同一數據頁面也會出現這種情況。假如WAL日志中僅僅記錄變化的那部分的內容,就無法將數據庫恢復到上次備份結束時刻的狀態。所以要將修改后的完整頁面寫入WAL中,以保證數據庫恢復后的一致性。

 

2. pg_stop_backup()

pg_stop_backup()的函數原型如下:

pg_stop_backup([, exclusive boolean ]);

exclusive 表示該備份是否是一個排他備份。

如果采用非排他方式備份,執行:

Select pg_stop_backup(false);

這條命令會產生如下動作:

1. label_file和tblspc_map_file的內容會包含在該函數返回的結果中,並且應該被寫入到該備份的一些文件中(這些內容不在數據目錄中)。

2. 在事務日志歸檔區里創建一個備份歷史文件(.hostory)。這個歷史文件包含 pg_start_backup的標簽、備份的起始與終止事務日志位置以及備份的起始和終止時間。返回值是備份的終止事務日志位置(同樣也可以被忽略)。 在記錄結束位置之后,當前事務日志插入點被自動地推進到下一個事務日志文件,這樣結束的事務日志文件可以立即被歸檔來結束備份。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM