pg_rewind時間線修復

作者:杭州美創科技有限公司

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使用這些資訊檢查目標群集是否可以使用指定的源群集倒回。