作者:杭州美創科技有限公司
pg_rewind是一個用於把一個PostgreSQL資料目錄與另一個從該目錄中複製出來的資料目錄同步,在集簇的時間線分叉以後,同步一個PostgreSQL集簇和同一集簇的另一份複製的工具。一種典型的場景是在失效後讓一箇舊的主伺服器重新上線,同時有一個後備機跟隨著新的主機。也就是說,在主備不同步後,我們也許不必重建備庫以修復流複製環境,使用pg_rewind解決時間分叉就可以修復同步失敗的問題。
pg_rewind要求目標伺服器在postgresql。conf中啟用了wal_log_hints選項,或者在用initdb初始化集簇時啟用了資料校驗。目前預設情況下這兩者都沒有被開啟。full_page_writes也必須被設定為on,這個是預設的。
以下介紹兩個pg_rewind實踐方案步驟:
第一部分 回退只讀從庫
1.1啟用從庫
啟用只讀從庫,使從庫能夠讀寫
$ pg_ctl promote -D /pgdata/data
1.2寫入從庫
在從庫中寫入資料,生成wal日誌
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432starting vacuum。。。end。starting vacuum pgbench_accounts。。。end。
此時從庫和主庫已不在同一個時間線上
從庫時間線
$ pg_controldata | grep TimeLineIDLatest checkpoint‘s TimeLineID: 9Latest checkpoint’s PrevTimeLineID: 9
主庫時間線
$ pg_controldata | grep TimeLineIDLatest checkpoint‘s TimeLineID: 8Latest checkpoint’s PrevTimeLineID: 8
1.3修復從庫
檢視切換點
$ ll $PGDATA/pg_wal/*。history
檢視最新時間線的。history檔案
$ cat 00000009。history5/5A000060
從00000009000000050000005A開始,所有的wal必須存在從庫pg_wal目錄中。如果已經覆蓋了,必須從歸檔目錄複製到從庫pg_wal目錄中,也可以直接將歸檔檔案全部複製到pg_wal目錄下
$ cp /mnt/server/archivedir/* /pgdata/data/pg_wal/ #/mnt/server/archivedir/為歸檔目錄
停掉從庫
$ pg_ctl stop -m fast -D /pgdata/data
測試修復是否能夠成功
$ pg_rewind -n -D /pgdata/data ——source-server=“hostaddr=192。168。22。128 user=postgres port=5432”pg_rewind: servers diverged at WAL location 5/5A000060 on timeline 8pg_rewind: rewinding from last common checkpoint at 5/59000060 on timeline 8pg_rewind: Done!
可以修復,直接修復
$ pg_rewind -D /pgdata/data ——source-server=“hostaddr=192。168。22。128 user=postgres port=5432”pg_rewind: servers diverged at WAL location 5/5A000060 on timeline 8pg_rewind: rewinding from last common checkpoint at 5/59000060 on timeline 8pg_rewind: Done!
修改配置檔案postgresql。auto。conf
$ vi postgresql。auto。confprimary_conninfo = ‘user=repl passfile=’‘/home/postgres/。pgpass’‘ host=192。168。22。128 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any’restore_command = ‘cp /mnt/server/archivedir/%f %p’recovery_target_timeline = ‘latest’
刪除錯誤時間線上產生的歸檔,即走到時間線00000009上的歸檔
$ mkdir /mnt/server/archivedir/error_tl_9$ mv 00000009* error_tl_9
建立從庫標識檔案
$ touch /pgdata/data/standby。signal
1.4啟動從庫
$ pg_ctl start -D /pgdata/data
在主庫上檢視流複製同步狀態
postgres=# select client_addr,sync_state from pg_stat_replication; client_addr | sync_state ————————+—————— 192。168。22。128 | async
第二部分 降級讀寫主庫
2.1啟用從庫
啟用只讀從庫,使從庫能夠讀寫
$ pg_ctl promote -D /pgdata/data
2.2寫入主、從庫
在從庫中寫入資料,生成wal日誌
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432starting vacuum。。。end。starting vacuum pgbench_accounts。。。end。
在主庫中寫入資料,生成wal日誌
$ pgbench -M prepared -v -r -P 1 -c 4 -j 4 -T 120 -p 5432starting vacuum。。。end。starting vacuum pgbench_accounts。。。end。
此時從庫和主庫已不在同一個時間線上
從庫時間線
$ pg_controldata | grep TimeLineIDLatest checkpoint‘s TimeLineID: 9Latest checkpoint’s PrevTimeLineID: 9
主庫時間線
$ pg_controldata | grep TimeLineIDLatest checkpoint‘s TimeLineID: 8Latest checkpoint’s PrevTimeLineID: 8
2.3修復老主庫
檢視切換點
$ ll $PGDATA/pg_wal/*。history
檢視最新時間線的。history檔案
$ cat 00000008。history5/37000000
從000000080000000500000037開始,所有的wal必須存在從庫pg_wal目錄中。如果已經覆蓋了,必須從歸檔目錄複製到從庫pg_wal目錄中,也可以直接將歸檔檔案全部複製到pg_wal目錄下
$ cp /mnt/server/archivedir/* /pgdata/data/pg_wal/ #/mnt/server/archivedir/為歸檔目錄
停掉老主庫
$ pg_ctl stop -m fast -D /pgdata/data
測試修復是否能夠成功
$ pg_rewind -n -D /pgdata/data ——source-server=“hostaddr=192。168。22。129 user=postgres port=5432”pg_rewind: servers diverged at WAL location 5/37000000 on timeline 8pg_rewind: rewinding from last common checkpoint at 5/37000000 on timeline 8pg_rewind: Done!
可以修復,直接修復
$ pg_rewind -D /pgdata/data ——source-server=“hostaddr=192。168。22。129 user=postgres port=5432”pg_rewind: servers diverged at WAL location 5/37000000 on timeline 8pg_rewind: rewinding from last common checkpoint at 5/37000000 on timeline 8pg_rewind: Done!
修改配置檔案postgresql。auto。conf
$ vi postgresql。auto。confprimary_conninfo = ‘user=repl passfile=’‘/home/postgres/。pgpass’‘ host=192。168。22。128 port=5432 sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgres target_session_attrs=any’restore_command = ‘cp /mnt/server/archivedir/%f %p’recovery_target_timeline = ‘latest’
老主庫建立從庫標識檔案
$ touch /pgdata/data/standby。signal
2.4啟動新從庫
$ pg_ctl start -D /pgdata/data
在新主庫上檢視流複製同步狀態
postgres=# select client_addr,sync_state from pg_stat_replication; client_addr | sync_state ————————+—————— 192。168。22。129 | async
注意事項
當使用線上群集作為源執行pg_rewind時,具有充足許可權來執行pg_rewind在源群集上使用的函式的角色可以用來代替超級使用者。這裡介紹如何建立這樣的角色,在這裡命名rewind_user:
CREATE USER rewind_user LOGIN;GRANT EXECUTE ON function pg_catalog。pg_ls_dir(text, boolean, boolean) TO rewind_user;GRANT EXECUTE ON function pg_catalog。pg_stat_file(text, boolean) TO rewind_user;GRANT EXECUTE ON function pg_catalog。pg_read_binary_file(text) TO rewind_user;GRANT EXECUTE ON function pg_catalog。pg_read_binary_file(text, bigint, bigint, boolean) TO rewind_user;
當使用近期升級的線上群集作為源執行pg_rewind時,必須在升級後執行CHECKPOINT以便其控制檔案反映最新的時間線資訊,pg_rewind使用這些資訊檢查目標群集是否可以使用指定的源群集倒回。