PostgreSQL 備份的問題準備寫一個合集,此篇是合集的第一篇,打算從 wal 日志來說起,這樣對後面備份的原理和使用的了解是有幫助的.
PG 本身是從7.0 開始有了備份之前采用的方式是調用系統中的函數将資料同步寫入到磁盤導緻資料庫系統的性能太低, 是以從7.0後我們才有了WAL 日志,
PG 将寫入資料庫表的語句和資訊寫入 wal buffer, 通過wal buffer 來臨時存儲 wal 日志的資料, 并在事務送出時,立即将這些資料寫入到磁盤中,也就是wal segment file 檔案中, 而這些資料是通過LSN log sequence number來進行記錄的, LSN 是順序型的記錄.
1 WAL 日志的第一個功能是保證資料庫在啟動後檢查REDO point點,并根據WAL 日志将checkpoint點後的資料進行重做.
其中在WAL 日志中會包含最後一次checkpointer 的記錄,checkpoint後的記錄就是要在資料庫開機重新開機後需要進行重做的資訊.
WAL 檔案本身預設是一個8KB的虛拟檔案,在外顯露的是16MB一個檔案(初始化或編譯的時候決定), 每個檔案是有一個檔案名的,(這裡指16MB檔案中的虛拟檔案名)
虛拟檔案名 = timelineID + LSN -1 / (16*256) + (lsn-1)/16M%256
下面是日志的記錄的結構
typedef struct XLogRecord
{
uint32 xl_tot_len; /* total len of entire record */
TransactionId xl_xid; /* xact id */
XLogRecPtr xl_prev; /* ptr to previous record in log */
uint8 xl_info; /* flag bits, see below */
RmgrId xl_rmid; /* resource manager for this record */
/* 2 bytes of padding here, initialize to zero */
pg_crc32c xl_crc; /* CRC for this record */
/* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */
} XLogRecord;
pg_wal主要通過日志Header part 和 data part 兩個部分組成
其中walwriter 來完成wal buffer 到磁盤的寫入通過 wal_writer_delay 參數來控制資料的寫入,walwriter程序不能被人工停止。
基于上面的WAL 日志,在備份中才有增量備份以及基于時間點的恢複 point-in-Time, 基于PG_wal 的原理,最初級的PG backup的操作主要是基于兩個指令
1 pg_start_backup
2 pg_stop_backup
在兩個指令之間進行資料檔案的拷貝和歸檔檔案的拷貝,進行實體方式的資料備份。
在執行pg_stat_backup 指令時會執行幾個動作,
1 讓PG_WAL日志進入 full -page 模式
2 進行PG_WAL 日志的切換
3 進行checkpiont操作
4 建立backup_lable file 好記錄checkpoint
然後就可以開始拷貝資料了,此間資料庫的任何操作都是可以的
在拷貝完資料後
在執行 pg_stop_backup 指令
1 将full page 的狀态變為普通模式
2 在pg_wal中寫一條備份終止的記錄
3 重新産生一個pg_wal 的 segment file
4 建立一個曆史的檔案将之前的backup_lable都包含在裡面以及執行pg_stop_backup 的時間線
5 删除backup_lable檔案
這樣一個FULL backup 就完成了
PITR 的資料庫恢複的方式原理也比較簡單,資料庫基礎檔案+日志REDO的方式進行任意時間點的恢複(日志必須存在), 在恢複後會産生 history檔案在pg_wal 目錄下, 這個檔案裡面就包含了資料庫恢複的分支。通過history檔案中記錄的資料來表明資料恢複到了日志的那個位置
cat /home/postgres/archivelogs/00000002.history1 0/A000198 before 2021-9-8 12:05:00.861324+00
複制
同時利用這樣的原理,資料庫還可以進行二次恢複或者多次PITR 選擇不同對的時間點進行資料的恢複。
POSTGRESQL 的備份的工具開源和閉源的非常多,但萬變不離其宗的是PG的備份原理和pg_basebackup 指令。pg_basebackup指令主要的功能和特點一句話表述就是,在備份時不影響資料庫的正常運作,通過他備份的資料庫是可以支援PITR方式的資料庫恢複的功能支援。實際上他就是上一篇中最基本的兩個備份指令的在“加工”。 他備份資料庫的特點主要有,備份速度快,資料庫恢複的速度也快,同時缺點也和明顯,就是不能進行資料庫中某一個OBJECT 的備份,要不就全備,沒有選擇。 對于整體的資料庫備份和從庫的建立, pg_basebackup指令是一個必備的選項。
pg_basebackup備份使用了POSTGRESQL 的複制協定, 連接配接是通過一個有效的賬号來進行通路POSTGRESQL 内部的資料庫,并且必須具有replication的權限,這裡需要在pg_hba.conf中做一定的設定,允許相關的通路。當然建立一個superuser 支援備份業務也是一個選擇。
這裡建議雖然可以在一個實體的POSTGRESQL 上同時運作多個pg_basebackup, 但沒有什麼意義,系統的性能會變得非常低下。同時在備份時建議開啟full_page_writes 在你需要備份的主機上。
在使用pg_basebackup備份的時候有一些是必要的參數
舉例
pg_basebackup -D /pgdata/data/ -Ft -Xs -z -P -D postgres -U postgres
以上面的指令舉例
-Ft -Fp 表達的意思是備份資料庫時資料檔案是否進行打包, 前者是将檔案變為 tar 包,後者是不将檔案打包。
-X 選項主要功能是在備份期間對wal 日志的備份的方式選擇, -Xn 是不備份wal 日志, -Xf 是通過copy的方式将wal 日志進行備份, -Xs 是較為常用和安全的方式,需要在資料庫中建立複制槽,并通過複制槽來進行wal 日志的複制。
在備份中,希望備份的檔案是沒有髒頁的, 就需要觸發立即的checkpoint , 此時 -c fast 就是必選項 在高并發的系統中,-c fast 會觸發此時的I/O的系統繁忙,将大量髒頁刷入到磁盤。
同時注意上圖在備份後,會多出來一個pg_wal檔案,這就是上面提到過的,運作備份會進行pg log switch的操作。
使用pg_basebackup指令功能時,需要注意指定的備份目錄不能為非空, 否則無法進行備份。
PG的備份工具有很多,PG_RMAN ,pgbackrest, 今天的pg_probackup主要的好處在于增量備份的多種模式可以選擇,及支援并發運作支援 backup, restore , merge ,delete, validate 和 checkdb的工作。 另外也支援從standby節點進行資料的備份,降低對主節點的性能影響。
官方的pg_probackup 中提到增量備份中支援page-level 的增量備份,這樣可以節省備份的磁盤空間加速備份的速度,基于增量的恢複中支援恢複資料中重用系統中并未修改過的頁面,增加恢複資料的速度。
而其中的merge模式可以通過合并備份資料的方式,直接将全量備份在每次備份的必要性中降低。具體的一些細節我們在下面繼續, 先對pg_probackup 進行安裝。
pg_probackup的安裝一般采用編譯安裝, 下載下傳 tar.gz的安裝包後,需要在有pg 安裝環境的情況下進行編譯安裝,這裡選擇一個簡單的方式來進行
1 下載下傳安裝包
2 解壓安裝包
3 将安裝包放入PG安裝檔案目錄中的contrib目錄中
4 直接運作make
5 直接運作make install
這樣的安裝方式簡單,并且不容易出錯,這也是按照官方文檔中“投機取巧的”描述的一種安裝方式。
安裝完畢後,下面我們就要開始使用pg_probackup 的備份之旅,并在備份中開始其中的一些指令的了解
首先我們對于備份的了解是要有全備有增量備份, 我們首先要對這個備份建立對應的備份的檔案夾和備份的關系
1 先申請一個儲存備份檔案的catalog 目錄
2 在資料目錄中添加一個備份的instance
3 在操作完畢後,會在目的的檔案夾中産生 backups wal 兩個目錄
其中裡面會有配置檔案并存儲目前的資料庫一些資訊
在使用pg_probackup 備份軟體前,需要有一個superuser的權限,或者建立一個具有如下權限的賬号
BEGIN;
CREATE ROLE backup WITH LOGIN;
GRANT USAGE ON SCHEMA pg_catalog TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.current_setting(text) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_is_in_recovery() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_start_backup(text, boolean, boolean) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_stop_backup(boolean, boolean) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_create_restore_point(text) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_switch_wal() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_last_wal_replay_lsn() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_current() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_current_snapshot() TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.txid_snapshot_xmax(txid_snapshot) TO backup;
GRANT EXECUTE ON FUNCTION pg_catalog.pg_control_checkpoint() TO backup;
COMMIT;
複制
在開始備份前需要開啟 hot_standby , full_page_writes 都設定為ON, 同時如果備份機,與需要備份的資料庫不在一台機器上還需要設定ssh 免密的工作。
pg_probackup backup -B /home/postgres/backup --instance backup_p -b FULL --stream
如果在備份中不采用 --stream 的方式,則需要配置archive ,否則備份不能正常進行,上面是通過pg_probackup對系統進行了全備。
下面我們選擇page的方式對系統進行增量備份
pg_probackup backup -B /home/postgres/backup --instance backup_p -b DELTA --stream
官方解釋通過 DELTA的方式來對系統進行incremental的備份, 基于資料檔案産生自FULL 備份後的增量資料,這裡僅僅對變動的資料頁進行備份。
通過 下面的指令可以對備份的progress 進行檢視,有成功也有備份失敗的狀态展示
pg_probackup show -B /home/postgres/backup/
以上是最簡單的備份方式
pg_probackup restore -B /home/postgres/backup/ --instance backup_p
通過上面的指令對資料庫進行了快速的恢複并且資料庫可以正常再次啟動
這裡 pg_probackup 本身支援三種增量模式 DELTA PAGE PTRACK
如果采用page的模式則 postgresql 必須設定 archive模式, 否則 page模式無法進行正确的備份。
在配置完archive模式後,
同時需要在archive 中寫入pg_probackup要求的備份指令,"/usr/local/postgres/bin/pg_probackup/pg_probackup" archive-push -B "/home/postgres/backup" --instance backup_p --wal-file-name=%f '
通過持續不斷的将 wal 日志備份到指定的instance的資料目錄中,保證後續資料恢複時有增量的 wal 日志,這裡 wal日志的備份是需要鑒定目前wal 日志中是否是正确的wal日志并且如果備份的目錄中已經有了相關的日志,我們可以通過 overwwrite指令将原有的檔案覆寫。
在加入了pg_probackup指令到archive 指令并重新開機動機器後,可以看到整體的日志已經開始歸檔到對應的pg_probackup的目錄中
下面就開始一個全備
pg_probackup backup -B /home/postgres/backup --instance backup_p -b page
在通過page的方式進行增量備份
在備份較多的時候,可以通過-i 指令來選擇需要恢複的指定備份(實際也是指定恢複備份的還原時間點)
資料恢複後,庫啟動,如果在archive 中的指令不包含 overwrite 則會導緻啟動是報無法archive的ERROR 此錯誤可以忽略,也可以通過overwrite 加到 archive指令中解決問題
實際上pg_probackup 的指令還有很多沒有寫, 如對備份檔案的定期的check 資料的完整性, 以及第三種備份的方式等等, 但如果是基本使用pg_probackup 上面的内容屬于基本夠用了。