因機房要搬遷,所以在這裡記錄辛酸血淚測試過程 (XD)
移動資料庫 Enterprisedb 或是 PostgreSQL 其實在 9.1 版本上,有出一個工具 pg_basebackup,這工具在未來的版本做得很棒,要做 streaming replication 會變得非常的簡單,但對於資料庫容量過於龐大的話,建議就不要使用,後面會說明原因;對於新版本 9.6 以上是否有一樣的狀況,筆者手邊沒有新版本的大型資料庫可測,因此就當做知識瞭解即可。
環境:edb 9.1 整體資料量 500g 左右
方法1. pg_basebackup
該工具的方法我相信有在管理 PostgreSQL 或 EDB 的 dba、管理員都不陌生,來看以下工具的說明
pg_basebackup takes a base backup of a running PostgreSQL server.
Usage:
pg_basebackup [OPTION]...
Options controlling the output:
-D, --pgdata=DIRECTORY receive base backup into directory
-F, --format=p|t output format (plain, tar)
-x, --xlog include required WAL files in backup
-z, --gzip compress tar output
-Z, --compress=0-9 compress tar output with given compression level
General options:
-c, --checkpoint=fast|spread
set fast or spread checkpointing
-l, --label=LABEL set backup label
-P, --progress show progress information
-v, --verbose output verbose messages
--help show this help, then exit
--version output version information, then exit
Connection options:
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port number
-U, --username=NAME connect as specified database user
-w, --no-password never prompt for password
-W, --password force password prompt (should happen automatically)
而筆者就從 slave 主機上下了以下的指令,執行的過程沒有出現什麼問題
pg_basebackup -h IPAddress_Master -D /edb/data/ -U repl -p 5432 -v -x -P
不過因為傳送執行時間大約 5~6 小時,為了確保 edb、PostgreSQL 產生出來的 archive log 不被 loss 掉,因此定期傳送 archive log 到 slave 主機上
rsync -avzP /arch/pg_archivelog/* IPAddress_Slave:/backup/archivelog_standby
等待 pg_basebackup 完成後,建立 recovery.conf 讓 slave 資料庫能夠與 master 溝通做 streaming replication
restore_command = 'cp /backup/archivelog_standby/%f %p'
standby_mode = 'true'
primary_conninfo = 'host=IPAddress_Master port=5432 user=repl'
recovery_target_timeline = 'latest'
trigger_file='/tmp/standbytrigger'
然後再修改一下 slave postgresql.conf 的設定
hot_standby = on
之後就開啟服務吧~~~~!!!!!!!!
pg_ctl start -D /edb/data
如果 pg_xlog 底下的檔案不存在的話,就會使用 archive log 來還原,當還原結束後,就會與 master 主機進行 streaming replication,
進 master 下以下 sql 可以看到連線狀況,
SELECT * FROM pg_stat_replication;
查目前使用的 log 編號 ( master + slave ),會發現 master + slave 的編號會是相同的 (不同的話,要排除傳送過程是不是有 delay)
psql edb -c "select pg_current_xlog_location()"
同步過程中,測試了 create table + insert + delete + drop table 基本上都是3秒內就傳送到 slave 主機上,因此「覺得」沒什麼問題,就是因為「覺得」沒什麼問題,這才是問題
實際把資料庫交付給程式開發人員檢查,發現有部份的 Table 資料有少 😫😫
(os: 怎麼可能!!都同步成功了,表示還原就沒問題才對啊~~)
檢查後發現有少的資料的部份,是在備份期間,簡單解釋時間軸:
09:00 開始備份
15:00 備份完畢
15:00 開啟資料庫 進行 archivelog 還原
15:03 還原完畢
15:03 streaming replication 同步
而資料不見的部份就是 9:00 開始備份 -> 15:00 備份完畢 這段期間,但並非全部沒還原,而是只有吃到 10:00 前的資料,就是只還原了一小部份的資料,想說怎麼那麼奇怪,前前後後測試了3次,結果都相同,備份期間的資料都只會還原一部份,但同事測試了 edb 11 的版本,並沒有發生這個問題,因此就想說是個 bug,然後就放棄了這個方法,因為 edb 9.1 已經 EOSL 了啊…沒得問😭😭
方法2. pg_start_backup + rsync + pg_stop_backup (推薦)
因方法1有些問題,就想到用差異的方式來備份,但就無法像 straming replication 的 slave 可以開啟資料庫到 read only 模式,可即時知道資料同步狀況,但這個備份方法也是基礎的備份方法,因此還是要會怎麼操作
首先對 edb 下 pg_start_backup (Postgresql 也是相同操作)
psql -c "select pg_start_backup('mybackup', true)"
此時就可以用 rsync 把檔案傳送到 slave 主機上
rsync -avzrHSP -e "ssh -o ServerAliveInterval=30" \
--delete /edb/* \
--exclude=postmaster.pid IPAddress_Slave:/edb
當 rsync 傳送完畢時,對 master 主機下達 pg_stop_backup 即可
psq -c "select pg_stop_backup()"
回到 slave 主機上,就可以開啟服務囉?
(瞇之音:這樣備份期間的資料還會有嗎?答:沒測試 XD
但是建議再做一次上面提到的步驟,rsync 是使用差異備份的方法,如果 master、slave 檔案的 checksum 不同,那麼就視為相異,就會先刪除 slave 檔案,再傳送新的檔過去覆蓋掉,因為是用差異備份的方法,所以實際上傳送的時間大約1小時內通常就會結束,比起第一次傳送 5~6 小時減少很多,所以就放在 linux crontab 上,每小時去跑大概就沒什麼問題吧!
#!/bin/bash
source /home/enterprisedb/pgplus_env.sh
rsync_gb_count=`ps -ef | grep ${0##*/} | grep -v grep | wc -l`
if [ "$rsync_gb_count" -ge 3 ]; then
echo "Exit Shell"
exit 1
fi
get_count_generate_data()
{
count="0"
next_count=`ps -ef | grep "rsync -avzrHSP" | grep -v grep | wc -l`
check="^[0-9]+$"
if ! [[ $next_count =~ $check ]] ; then
next_count="1"
fi
count=$(($count + $next_count))
}
get_count_generate_data
echo "Now rsync is running. This make take a while."
echo -ne "."
while [ "$count" -gt "0" ]; do
echo -ne "."
sleep 5
get_count_generate_data
done
echo "Begin_`date`">> /backup/script/rsync.log
psql -c "select pg_start_backup('mybackup', true)"
if [ $? -eq 0 ]; then
rsync -avzrHSP -e "ssh -o ServerAliveInterval=30" \
--delete /edb/* \
--exclude=postmaster.pid IPAddress_Slave:/edb \
>> /backup/script/rsync.log
fi
psql -c "select pg_stop_backup()"
echo "End_`date`">> /backup/script/rsync.log
至於 script 寫的好不好,又是另一回事,能用的順利不卡卡,就是好工具 XD
以上內容僅供參考,若有錯誤的地方,還請讀者們給予提醒修正
相關資料來源:
Taking a backup of a streaming WAL slave https://dba.stackexchange.com/questions/48103/taking-a-backup-of-a-streaming-wal-slave
0 留言