最近在使用上,發現一個使用細節的改進,在 PGSQL 10 上是一個重要的改進~
pg_basebackup 的參數中,除了主機連線設置之外,還有幾個關於備份的選項。其中有一個 WAL 傳輸選項 -X,將備份所需的 WAL 一起打包的方式,這保證備份檔可以獨立啟動,不會遺漏 WAL 檔案。
WAL 備份模式有兩種:
-X fetch 指的是,在 pg_basebackup 備份程序的最後,才抓取所需的 WAL 檔案
-X stream 則是,在 pg_basebackup 的備份期間,以串流傳遞的方式,不斷補上需要的 WAL 檔案
另外,全備份提供三種模式進行:
-F plain:用來建立 Streaming Replication
-F tar:不壓縮打包,常常搭配壓縮指令使用(下一項)
-F tar -z:打包並且 gzip 壓縮,可以再用 -Z 設定壓縮等級
上面的選項,並不是可以任意搭配的。這就是這篇筆記的重點。
下面為 9.x 版 pg_basebackup 備份選項的簡易搭配表:
PGSQL 9.x
|
-X fetch
(需要 wal_keep_segments)
|
-X stream
(可選搭 replication slot)
|
-F plain
|
O
|
O
|
-F tar
|
O
|
X
|
-F tar -z
|
O
|
X
|
再來則是 10 版 pg_basebackup 備份選項的簡易搭配表:
PGSQL 10
|
-X fetch
(需要 wal_keep_segments)
|
-X stream
(可選搭 replication slot)
|
-F plain
|
O
|
O
|
-F tar
|
O
|
O
|
-F tar -z
|
O
|
O
|
以下會分別用 Postgres 9.6 以及 Postgres 10 進行試驗。
為了方便測試,這裡把 max_wal_size 減小(預設 1GB),讓 pg_xlog 目錄(PGSQL10 的 pg_wal 目錄)留下來的 WAL 數量少一些,比較容易發生 WAL 太早被移除/備份的情形。
psql -c "alter system set max_wal_size = '80MB';" pg_ctl restart
備份指令測試期間,同時使用以下指令,長時間的塞資料(看電腦速度,我的測試環境耗時半小時左右~),讓資料庫一直刷新的 WAL 檔案,並不斷的觸發向外備份
#長時間塞資料
psql -c "select id , \
(random()*100)::int num1_100 , \
(random()*10000)::text num1_1W , \
(random()*1000000)::text num1_100W \
into test_tab from generate_series(1,10000000) id;"
在上面的資料插入運作期間,進行 pg_basebackup 備份。以下分成兩部份,分別是在 Postgres 9.6 進行一次,以及在 Postgres 10 進行一次。這裡在 Linux 下的本機測試備份(以 OS 帳號 postgres 進行),因此不用特地輸入連線資訊即可。
一)在 PostgreSQL 9.6 (含)之前的版本
沒辦法同時作壓縮備份與 WAL Stream 模式的指定
bash-$ mkdir ~/pg96-backup bash-$ pg_basebackup -U postgres -D ~/pg96-backup -F tar -X stream -P -v pg_basebackup: WAL streaming can only be used in plain mode Try "pg_basebackup --help" for more information. bash-$ pg_basebackup -U postgres -D ~/pg96-backup -F tar -z -X stream -P -v pg_basebackup: WAL streaming can only be used in plain mode Try "pg_basebackup --help" for more information. bash-$
在 PGSQL 9.4 之前,會詳細的設定 checkpoint_segments 與 wal_keep_segments 以避免 Streaming Rplication 中斷或是 pg_basebackup 備份缺少 WAL 造成不完整的狀況。
在 PGSQL 9.5 之後,由於 WAL 檔案控制模式的改變(max_wal_size & min_wal_size 取代了 checkpoint_segments),以及 Replication Slot 的使用,WAL 的設定比較簡單,但可能會因此不小心一同忘記設定 wal_keep_segments。
若不幸忘記設置 wal_keep_segments,一旦在 pg_basebackup -X fetch 備份期間發生了 WAL Rotate/Archiving,在備份最末階段,會告知備份失敗,因為 pg_xlog/ 目錄找不到需要的檔案了(儘管該 WAL 檔案被備份到 Archive 目錄)。以下簡單進行示範
bash-$ #同時在另一個 Shell 進行長時間塞資料的行為 bash-$ pg_basebackup -D ~/pg96-backup -F tar -X fetch -z -P -v pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 3/787D10F0 on timeline 1 1101661/1101661 kB (100%), 3/3 tablespaces pg_basebackup: could not get write-ahead log end position from server: ERROR: requested WAL segment 000000010000000300000078 has already been removed pg_basebackup: removing contents of data directory "/var/lib/postgres/pg96-backup" bash-$ ls -l ~/pg96-backup total 0 bash-$
如果要成功,需要設置「夠大的」的 wal_keep_segments 才不會失敗:在這次測試中 10 個還不夠........直接設定到 100 個,但這樣也表示 pg_xlog/ 目錄的內容可能到 1600MB 之多。
psql -c "alter system set wal_keep_segments = '100';" pg_ctl restart #進行長時間塞資料的行為
bash-$ pg_basebackup -D ~/pg96-backup -F tar -X fetch -z -P -v
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
transaction log start point: 4/6804DE48 on timeline 1
2025730/2025730 kB (100%), 3/3 tablespaces
transaction log end point: 4/A454FE08
pg_basebackup: base backup completed
bash-$ ls -l ~/pg96-backup
total 694384
-rw-rw-r--. 1 enterprisedb enterprisedb 117 Feb 6 07:02 30254.tar.gz
-rw-rw-r--. 1 enterprisedb enterprisedb 117 Feb 6 07:02 30255.tar.gz
-rw-rw-r--. 1 enterprisedb enterprisedb 711036705 Feb 6 07:21 base.tar.gz
bash-$
[NOTE] 不好意思,PGSQL9.6 測試環境用的比較久,比 PGSQL10 多了兩個 Tablespace,不過不影響結論~
上面可見,要正常備份,需要設置充足的 wal_keep_segments,但這樣就得好好的拿捏這個量~
二)在 PostgreSQL 10 後,pg_basebackup -F tar -X stream 功能被增加進來,使的下面的功能可以用
bash-$ #同時在進行長時間塞資料的行為 bash-$ mkdir ~/pg10-backup bash-$ pg_basebackup -U postgres -D ~/pg10-backup -F tar -X stream -z -P -v pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 0/3051400 on timeline 1 pg_basebackup: starting background WAL receiver 200570/200570 kB (100%), 1/1 tablespace pg_basebackup: write-ahead log end point: 0/28C3DB28 pg_basebackup: waiting for background process to finish streaming ... (等待塞完資料,以及 checkpoint) pg_basebackup: base backup completed bash-$
仔細查看最後的備份內容,PGSQL 10 比起之前版本多了一個 WAL 獨立的壓縮檔,而之前版本的備份,則是把 $PGDATA/pg_xlog/ 目錄一併壓縮在 base.tar.gz 裡面
bash-$ ls -l ~/pg10-backup/
total 293888
-rw-rw-r--. 1 enterprisedb enterprisedb 66873697 Feb 5 09:44 base.tar.gz
-rw-------. 1 enterprisedb enterprisedb 234057964 Feb 5 09:49 pg_wal.tar.gz
bash-$
要注意的是,這裡把 PGSQL 10 的 pg_basebackup 指令對 PGSQL 10 Server 進行備份;然而,若把 PGSQL10 的 pg_basebackup 指令對 PGSQL9.6 進行 -F tar -X stream 備份則會發生錯誤
bash-$ pg_basebackup -U postgres -D ~/pg96-backup -F tar -X stream -P -v pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 3/F7000028 on timeline 1 pg_basebackup: starting background WAL receiver pg_basebackup: unexpected termination of replication stream: ERROR: requested WAL segment 000000010000000300000000 has already been removed 642725/642725 kB (100%), 3/3 tablespaces pg_basebackup: write-ahead log end point: 3/F7000130 pg_basebackup: waiting for background process to finish streaming ... pg_basebackup: child process exited with error 1 pg_basebackup: removing contents of data directory "/var/lib/postgres/pg96-backup" bash-$ pg_basebackup -U enterprisedb -D ~/pg96-backup -F tar -z -X stream -P -v pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 3/F9000028 on timeline 1 pg_basebackup: starting background WAL receiver pg_basebackup: unexpected termination of replication stream: ERROR: requested WAL segment 000000010000000300000000 has already been removed 642725/642725 kB (100%), 3/3 tablespaces pg_basebackup: write-ahead log end point: 3/F9000130 pg_basebackup: waiting for background process to finish streaming ... pg_basebackup: child process exited with error 1 pg_basebackup: removing contents of data directory "/var/lib/postgres/pg96-backup" bash-$
PGSQL 10 的 pg_basebackup 改進的功能,讓我們可以順利的進行備份,不用再被 wal_keep_segments 困擾~
另外,我們還可以讓 pg_basebackup -X stream 咬一個 replication slot,就可以更加保障備份過程~
參考資料
EnterpriseDB 原廠客服
其他 pg_basebackup 的筆記,可以上網查查
沒有留言:
張貼留言