2021年8月20日 星期五

PGSQL - Streaming Replication pg_upgrade 版本升級

今天要來示範如何透過 pg_upgrade 進行版本升級,下面會比較單機升級時 Copy 模式以及 Link 模式的差異,以及 HA 叢集下 Primary 與 Standby 升級方法,並透過 Hard Link 與 Rsync 方式來對大型資料庫進行快速的版本升級。

相關測試皆為參考社群官網手冊來進行。

第一項測試為 pg_upgrade 的 Copy 模式與 Link 模式簡單比較,此處僅提供比較結果供參考不詳細列出設置細節。

透過 pgbench 產生 13GB 測試資料用來比較速度。

postgres=# \l+
                                                               List of databases
   Name    |  Owner   | Encoding | Collate | Ctype |   Access privileges   |  Size   | Tablespace |                Description
-----------+----------+----------+---------+-------+-----------------------+---------+------------+--------------------------------------------
 postgres  | postgres | UTF8     | C       | C     |                       | 13 GB   | pg_default | default administrative connection database

使用 Copy 模式進行升級,透過 Copy file 的方式複製一份資料出來,此方法會需要多一倍空間來放資料,執行時間會依據硬碟 I/O 狀況為主,本處測試環境效能較差因此花了約十三分鐘完成。

-bash-4.2$  time /usr/pgsql-13/bin/pg_upgrade -d /var/lib/pgsql/12/data -D /var/lib/pgsql/13/data -b /usr/pgsql-12/bin/ -B /usr/pgsql-13/bin
Performing Consistency Checks
-----------------------------
......
Performing Upgrade
------------------
.......                                                     
Copying user relation files
.......
Upgrade Complete
----------------
.......
real    13m15.062s
user    0m0.320s
sys     0m36.340s
-bash-4.2$

使用 Link 模式進行升級,為透過 disk 底層 Hard Link 連結的方式來進行,僅需要 7 秒時間即完成,並且不消耗額外空間,當資料量更大時甚至是 TB 級別也只會需要幾十秒內就可以完成。

-bash-4.2$ time /usr/pgsql-13/bin/pg_upgrade -d /var/lib/pgsql/12/data -D /var/lib/pgsql/13/data -b /usr/pgsql-12/bin/ -B /usr/pgsql-13/bin --link
Performing Consistency Checks
-----------------------------
.......
Performing Upgrade
------------------
........
If you want to start the old cluster, you will need to remove
the ".old" suffix from /var/lib/pgsql/12/data/global/pg_control.old.
Because "link" mode was used, the old cluster cannot be safely
started once the new cluster has been started.
.......
Linking user relation files
.......
Upgrade Complete
----------------
.......
real    0m7.352s
user    0m0.112s
sys     0m0.332s
-bash-4.2$

在 Copy 模式下搬出一份新檔案,因此新舊資料庫是完全獨立不互相影響的,而 Link 模式在完成升級後,尚未開啟新版本資料庫前,可以復原舊版版本資料庫,但是若已經開啟過新版本資料庫後,則不建議再開啟就版本資料庫,如有需要會建議從備分重倒資料。

mv /var/lib/pgsql/12/data/global/pg_control.old /var/lib/pgsql/12/data/global/pg_control
透過 Link 模式可以做到非常快速的資料庫升級,但升級後還有些相關的資料需要進行維護 (選用 Copy 模式也需要)。

執行完成 pg_upgrade 後,不管是選用 Copy 或是 Link 模式,程式會自動產生 delete_old_cluster.sh 和 analyze_new_cluster.sh 兩個檔案, 一個是執行 rm 指令將舊資料庫刪除,一個是在新版本資料庫開啟後用來執行 Analyze 重新收統計值 (舊統計值無法使用)。

另外在 Index 部分,如使用 B-tree Index 原則上不會受影響可以正常繼續使用,但如果有遇到像是升級 PGSQL 13 版本,有新增 B-tree Index Deduplication 的功能,則必須要執行 Reindex 在執行完成後即可看到 Index 大小變小。




第二項測試為 HA 架構 Streaming Replication 的升級測試,本處容器環境下建置 Primary/Standby 的叢集進行 PGSQL 12 升級至 PGSQL 13 的測試。

以下為升級測試紀錄

1. 安裝與初始化 PGSQL (環境準備)

【Primary】
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum install -y postgresql12-server

export LANG=en_US.UTF-8
export PGSETUP_INITDB_OPTIONS="-E UTF-8"
/usr/pgsql-12/bin/postgresql-12-setup initdb

mkdir -p /dbbackups/archived_wals/
chown -R postgres: /dbbackups/
chown -R postgres: /var/lib/pgsql

cat << "EOF" >> /var/lib/pgsql/12/data/postgresql.auto.conf
wal_level = 'replica'
archive_mode = on 
archive_command = 'cp %p /dbbackups/archived_wals/%f'
restore_command = 'cp /dbbackups/archived_wals/%f %p'
listen_addresses = '*'
EOF

sed -e 's/ident$/md5/' -i /var/lib/pgsql/12/data/pg_hba.conf
cat << "EOF" >> /var/lib/pgsql/12/data/pg_hba.conf
host replication all pg1 trust
host replication all pg2 trust
EOF

service postgresql-12 start

2. 透過 nfs 設定共同存取的 Archived_wal 目錄

【Primary】
yum install -y  nfs-utils rpcbind
cat << "EOF" >> /etc/exports
/dbbackups    10.222.190.0/24(rw,sync,no_subtree_check)
EOF
service nfs start
chkconfig nfs on
【Standby】
mkdir /dbbackups
yum install -y nfs-utils rpcbind
service nfs start
chkconfig nfs on
mount -t nfs 10.222.190.190:/dbbackups /dbbackups
cat << EOF >> /etc/rc.local
mount -t nfs 10.222.190.190:/dbbackups /dbbackups
EOF
3. 建立 Standby
su - postgres
/usr/pgsql-12/bin/pg_basebackup -D /var/lib/pgsql/12/data/ -h pg1 -Pv -X stream -R
exit
service postgresql-12 start

4. 準備測試資料
【Primary】
/usr/pgsql-12/bin/pgbench -i -s 50

5. 在 Primary 上初始化新版本資料庫,Standby 不用,注意此處初始化條件必須與舊版本資料庫相同,wal_segsize 也必須相同,如果初始化條件有差異的話將無法透過 pg_upgrade 升版,另外相關使用到的外掛模組也必須要在新版本資料庫安裝上。
(此步驟開始為升級步驟)
【Primary/Standby】
yum install -y postgresql13-server
【Primary】
export LANG=en_US.UTF-8
export PGSETUP_INITDB_OPTIONS="-E UTF-8"
/usr/pgsql-13/bin/postgresql-13-setup initdb
6. 執行 Primary 資料庫升版
在執行升版建議先事前執行檢查,確保相關準備都有到位,以避免停機升版時出現錯誤無法執行升版,另外可將相關設定檔案備分下來,執行完成後暫時先不啟動資料庫。
【Primary/Standby】
service postgresql-12 stop

【Primary】
su - postgres
cd /var/lib/pgsql/12/data/
tar -zcvf ~/pg12.bkp.tgz {pg_hba.conf,pg_ident.conf,postgresql.auto.conf}

# 執行升版檢查
/usr/pgsql-13/bin/pg_upgrade -d /var/lib/pgsql/12/data -D /var/lib/pgsql/13/data -b /usr/pgsql-12/bin/ -B /usr/pgsql-13/bin --link --check

# 執行升版
/usr/pgsql-13/bin/pg_upgrade -d /var/lib/pgsql/12/data -D /var/lib/pgsql/13/data -b /usr/pgsql-12/bin/ -B /usr/pgsql-13/bin --link
7. 執行 Standby 資料庫升版
在 Standby 確保關閉舊版本資料庫後先將設定檔案還有 Log 等依需求備分下來(會被覆蓋)
【Standby】
su - postgres
cd /var/lib/pgsql/12/data/
tar -zcvf ~/pg12.bkp.tgz {pg_hba.conf,pg_ident.conf,postgresql.auto.conf}
在 Primary 資料庫上執行 Rsync 同步 Hard Link ,此處請一定要小心確認指令正確,是否有指定對目錄,順序為 Primary 舊路徑Primary 新路徑Standby 上層路徑,注意不要多加少加 / ,倒斜線差異會導致同步的目錄就不同了,如果有 Tablespace 目錄也需要針對 Tablespace 目錄執行 Rsync ,熟悉的話也可以依需求去調整 Rsync 指令。

正常執行下只需要幾秒鐘建立 Hard Link 即可完成,執行前建議在測試環境先行測試確保指令正確以避免錯誤覆蓋檔案導致必須透過 pg_basebackup 重拉 Standby,另外也可以執行 --dry-run 做檢查確保同步檔案正確。
【Primary】
rsync --archive --delete --hard-links --size-only --no-inc-recursive /var/lib/pgsql/12 /var/lib/pgsql/13 pg2:/var/lib/pgsql
8. 調整設定檔案後啟動資料庫,到此步驟完成升版,後續在視狀況將舊資料清除以及進行 Analyze、Reindex 等動作
【Primary/Standby】
tar -zxvf ~/pg12.bkp.tgz -C /var/lib/pgsql/13/data
service postgresql-13 start