pg_upgrade — 升級 PostgreSQL 伺服器實例
pg_upgrade
-b
oldbindir
[-B
newbindir
] -d
oldconfigdir
-D
newconfigdir
[option
...]
pg_upgrade (先前稱為 pg_migrator) 允許將儲存在 PostgreSQL 資料檔案中的資料升級到更新的 PostgreSQL 主要版本,而無需通常用於主要版本升級的資料傾印/還原,例如,從 12.14 到 13.10 或從 14.9 到 15.5。 次要版本升級不需要它,例如,從 12.7 到 12.8 或從 14.1 到 14.5。
主要的 PostgreSQL 版本會定期新增新功能,這些功能通常會變更系統表格的版面配置,但內部資料儲存格式很少變更。pg_upgrade 利用此事實,透過建立新的系統表格並簡單地重複使用舊的使用者資料檔案來執行快速升級。 如果未來的主要版本變更資料儲存格式的方式導致舊資料格式無法讀取,pg_upgrade 將無法用於此類升級。(社群將嘗試避免這種情況。)
pg_upgrade 會盡力確保舊叢集和新叢集是二進位相容的,例如,透過檢查相容的編譯時間設定,包括 32/64 位元二進位檔。 重要的是,任何外部模組也是二進位相容的,儘管 pg_upgrade 無法檢查這一點。
pg_upgrade 支援從 9.2.X 及更高版本升級到目前的主要 PostgreSQL 版本,包括快照版本和 beta 版本。
pg_upgrade 接受以下命令列引數
-b
bindir
--old-bindir=
bindir
舊的 PostgreSQL 可執行檔目錄;環境變數 PGBINOLD
-B
bindir
--new-bindir=
bindir
新的 PostgreSQL 可執行檔目錄;預設是 pg_upgrade 所在的目錄;環境變數 PGBINNEW
-c
--check
僅檢查叢集,不變更任何資料
-d
configdir
--old-datadir=
configdir
舊的資料庫叢集設定目錄;環境變數 PGDATAOLD
-D
configdir
--new-datadir=
configdir
新的資料庫叢集設定目錄;環境變數 PGDATANEW
-j njobs
--jobs=njobs
要使用的同時處理程序或執行緒數
-k
--link
使用硬連結,而不是將檔案複製到新的叢集
-N
--no-sync
預設情況下,pg_upgrade
將等待升級叢集的所有檔案安全地寫入磁碟。此選項會導致 pg_upgrade
不等待就返回,這更快,但意味著後續的作業系統崩潰可能會使資料目錄損毀。 通常,此選項對於測試很有用,但不應在生產安裝中使用。
-o
options
--old-options
options
要直接傳遞到舊的 postgres
命令的選項;多個選項調用會附加在一起
-O
options
--new-options
options
要直接傳遞到新的 postgres
命令的選項;多個選項調用會附加在一起
-p
port
--old-port=
port
舊的叢集連接埠號碼;環境變數 PGPORTOLD
-P
port
--new-port=
port
新的叢集連接埠號碼;環境變數 PGPORTNEW
-r
--retain
即使在成功完成後,也保留 SQL 和記錄檔
-s
dir
--socketdir=
dir
升級期間用於 postmaster sockets 的目錄;預設為目前的工作目錄;環境變數 PGSOCKETDIR
-U
username
--username=
username
叢集的安裝使用者名稱;環境變數 PGUSER
-v
--verbose
啟用詳細的內部記錄
-V
--version
顯示版本資訊,然後結束
--clone
使用有效率的檔案複製(在某些系統上也稱為 「reflinks」),而不是將檔案複製到新的叢集。 這可以近乎即時地複製資料檔案,從而提供 -k
/--link
的速度優勢,同時保持舊的叢集不被觸及。
僅在某些作業系統和檔案系統上支援檔案複製。 如果選擇了它但不受支援,pg_upgrade 執行將會發生錯誤。 目前,它在 Linux (kernel 4.5 或更高版本) 上使用 Btrfs 和 XFS(在建立時具有 reflink 支援的檔案系統上),以及在 macOS 上使用 APFS 支援。
--copy
將檔案複製到新的叢集。這是預設行為。(另請參閱 --link
和 --clone
。)
--copy-file-range
使用 copy_file_range
系統呼叫以進行有效率的複製。在某些檔案系統上,這會產生類似於 --clone
的結果,共享實體磁碟區塊,而在其他檔案系統上,它可能仍然複製區塊,但透過最佳化的路徑進行。目前,它在 Linux 和 FreeBSD 上受到支援。
--sync-method=
method
當設定為 fsync
(預設值)時,pg_upgrade
將遞迴地開啟並同步升級後叢集資料目錄中的所有檔案。檔案搜尋將遵循 WAL 目錄和每個已配置的資料表空間的符號連結。
在 Linux 上,可以使用 syncfs
來要求作業系統同步包含升級後叢集資料目錄、其 WAL 檔案和每個資料表空間的整個檔案系統。請參閱recovery_init_sync_method,以了解使用 syncfs
時需要注意的注意事項。
當使用 --no-sync
時,此選項無效。
-?
--help
顯示說明,然後結束
以下是使用 pg_upgrade 執行升級的步驟
(可選)移動舊叢集
如果您使用特定版本的安裝目錄,例如 /opt/PostgreSQL/17
,則無需移動舊叢集。圖形安裝程式都使用特定版本的安裝目錄。
如果您的安裝目錄不是特定版本,例如 /usr/local/pgsql
,則必須移動目前的 PostgreSQL 安裝目錄,以免干擾新的 PostgreSQL 安裝。關閉目前的 PostgreSQL 伺服器後,重新命名 PostgreSQL 安裝目錄是安全的;假設舊目錄為 /usr/local/pgsql
,您可以執行
mv /usr/local/pgsql /usr/local/pgsql.old
以重新命名目錄。
對於原始碼安裝,請建置新版本
使用與舊叢集相容的 configure
旗標建置新的 PostgreSQL 原始碼。pg_upgrade 將檢查 pg_controldata
以確保所有設定都相容,然後再開始升級。
安裝新的 PostgreSQL 二進制檔案
安裝新伺服器的二進制檔案和支援檔案。pg_upgrade 包含在預設安裝中。
對於原始碼安裝,如果您希望將新伺服器安裝在自定義位置,請使用 prefix
變數
make prefix=/usr/local/pgsql.new install
初始化新的 PostgreSQL 叢集
使用 initdb
初始化新的叢集。同樣,使用與舊叢集相符的相容 initdb
旗標。許多預先建置的安裝程式會自動執行此步驟。無需啟動新的叢集。
安裝擴充功能共享物件檔案
許多擴充功能和自定義模組,無論是來自 contrib
還是其他來源,都使用共享物件檔案(或 DLL),例如 pgcrypto.so
。如果舊叢集使用了這些,則必須將與新伺服器二進制檔案匹配的共享物件檔案安裝到新叢集中,通常透過作業系統指令。請勿載入綱要定義,例如 CREATE EXTENSION pgcrypto
,因為這些定義將從舊叢集複製。如果擴充功能更新可用,pg_upgrade 將報告此情況並建立一個腳本,可以在以後執行以更新它們。
複製自定義全文檢索搜尋檔案
將任何自定義全文檢索搜尋檔案(字典、同義詞、詞庫、停用詞)從舊叢集複製到新叢集。
調整驗證
pg_upgrade
將多次連接到舊伺服器和新伺服器,因此您可能需要在 pg_hba.conf
中將驗證設定為 peer
,或使用 ~/.pgpass
檔案(請參閱第 32.16 節)。
準備發布者升級
pg_upgrade 嘗試遷移邏輯槽。這有助於避免需要在新的發布者上手動定義相同的邏輯槽。只有當舊叢集為 17.0 或更高版本時,才支援遷移邏輯槽。版本 17.0 之前的叢集上的邏輯槽將被靜默忽略。
在您開始升級發布者叢集之前,請確保暫時停用訂閱,方法是執行 ALTER SUBSCRIPTION ... DISABLE
。升級後重新啟用訂閱。
pg_upgrade 能夠升級邏輯槽有一些先決條件。如果未滿足這些條件,將報告錯誤。
新的叢集必須將 wal_level
設為 logical
。
新的叢集必須將 max_replication_slots
配置為大於或等於舊叢集中存在的槽數的值。
舊叢集上的槽引用的輸出插件必須安裝在新 PostgreSQL 可執行檔案目錄中。
舊叢集已將所有交易和邏輯解碼訊息複製到訂閱者。
舊叢集上的所有槽都必須可用,即沒有任何槽的 pg_replication_slots.conflicting
不是 true
。
新的叢集不能有永久邏輯槽,即不能有任何槽的 pg_replication_slots.temporary
是 false
。
準備訂閱者升級
在新訂閱者中設定訂閱者配置。pg_upgrade 嘗試遷移訂閱相依性,包括 pg_subscription_rel 系統目錄中存在的訂閱表資訊以及訂閱的複製來源。這允許新的訂閱者上的邏輯複製從舊訂閱者停止的地方繼續。只有當舊叢集為 17.0 或更高版本時,才支援遷移訂閱相依性。版本 17.0 之前的叢集上的訂閱相依性將被靜默忽略。
pg_upgrade 能夠升級訂閱有一些先決條件。如果未滿足這些條件,將報告錯誤。
舊訂閱者中的所有訂閱表都應處於狀態 i
(初始化)或 r
(就緒)。這可以透過檢查 pg_subscription_rel.srsubstate
來驗證。
與每個訂閱對應的複製來源條目應該存在於舊叢集中。這可以透過檢查 pg_subscription 和 pg_replication_origin 系統表格來找到。
新叢集必須將 max_replication_slots
設定為大於或等於舊叢集中存在的訂閱數的值。
停止兩台伺服器
確認兩台資料庫伺服器都已停止,例如在 Unix 上使用:
pg_ctl -D /opt/PostgreSQL/12 stop pg_ctl -D /opt/PostgreSQL/17 stop
或在 Windows 上,使用正確的服務名稱
NET STOP postgresql-12 NET STOP postgresql-17
串流複製和日誌傳送備用伺服器必須在關機期間運行,以便它們接收所有變更。
準備升級備用伺服器
如果您使用 步驟 13 中概述的方法升級備用伺服器,請透過針對舊的主伺服器和備用叢集執行 pg_controldata 來驗證舊的備用伺服器是否已趕上。驗證所有叢集中 「Latest checkpoint location」 的值是否匹配。另外,請確認新主叢集上的 postgresql.conf
檔案中,wal_level
未設定為 minimal
。
執行 pg_upgrade
始終運行新伺服器的 pg_upgrade 二進制檔案,而不是舊伺服器的。pg_upgrade 需要指定舊叢集和新叢集的資料目錄和可執行 (bin
) 目錄。您還可以指定使用者和埠號值,以及您希望資料檔案被連結或複製,而不是預設的複製行為。
如果您使用連結模式,升級速度會快很多(沒有檔案複製)並且佔用更少的磁碟空間,但是一旦在升級後啟動新叢集,您將無法存取舊叢集。連結模式還要求舊叢集和新叢集的資料目錄位於同一個檔案系統中。(表空間和 pg_wal
可以位於不同的檔案系統上。)複製模式提供相同的速度和磁碟空間優勢,但不會導致新叢集啟動後舊叢集無法使用。複製模式還要求舊叢集和新叢集的資料目錄位於同一個檔案系統中。此模式僅在某些作業系統和檔案系統上可用。
--jobs
選項允許多個 CPU 核心用於複製/連結檔案以及平行轉儲和還原資料庫綱要;一個好的起點是 CPU 核心數和表空間數的最大值。此選項可以顯著減少在多處理器機器上運行的多資料庫伺服器的升級時間。
對於 Windows 使用者,您必須登入管理員帳戶,然後使用帶引號的目錄運行 pg_upgrade,例如:
pg_upgrade.exe --old-datadir "C:/Program Files/PostgreSQL/12/data" --new-datadir "C:/Program Files/PostgreSQL/17/data" --old-bindir "C:/Program Files/PostgreSQL/12/bin" --new-bindir "C:/Program Files/PostgreSQL/17/bin"
啟動後,pg_upgrade
將驗證兩個叢集是否相容,然後進行升級。 您可以使用 pg_upgrade --check
僅執行檢查,即使舊伺服器仍在運行。pg_upgrade --check
還會概述升級後您需要進行的任何手動調整。 如果您要使用連結或複製模式,您應該將選項 --link
或 --clone
與 --check
一起使用,以啟用模式特定的檢查。pg_upgrade
需要目前目錄中的寫入權限。
顯然,在升級期間不應有人存取叢集。 pg_upgrade 預設在埠 50432 上運行伺服器,以避免意外的用戶端連線。 在執行升級時,您可以對兩個叢集使用相同的埠號,因為舊叢集和新叢集不會同時運行。 但是,在檢查舊的運行中的伺服器時,舊埠號和新埠號必須不同。
如果在還原資料庫綱要時發生錯誤,pg_upgrade
將退出,您將必須如 步驟 19 中所述還原到舊叢集。 若要再次嘗試 pg_upgrade
,您需要修改舊叢集,以便 pg_upgrade 綱要還原成功。 如果問題是 contrib
模組,您可能需要從舊叢集中解除安裝 contrib
模組,並在升級後將其安裝到新叢集中,假設該模組未用於儲存使用者資料。
升級串流複製和日誌傳送備用伺服器
如果您使用連結模式並且有串流複製(請參閱 第 26.2.5 節)或日誌傳送(請參閱 第 26.2 節)備用伺服器,您可以按照以下步驟快速升級它們。 您將不會在備用伺服器上運行 pg_upgrade,而是在主伺服器上運行 rsync。 暫時不要啟動任何伺服器。
如果您沒有使用連結模式,沒有或不想使用 rsync,或者想要更簡單的解決方案,請跳過本節中的說明,只需在 pg_upgrade 完成且新的主伺服器運行後重新建立備用伺服器即可。
在備用伺服器上安裝新的 PostgreSQL 二進制檔案
確認新的二進制檔案和支援檔案已安裝在所有備用伺服器上。
確認新的備用資料目錄不存在
確認新的備用資料目錄不存在或為空。 如果已運行 initdb,請刪除備用伺服器的新資料目錄。
安裝擴充功能共享物件檔案
在新備用伺服器上安裝與您在新主叢集中安裝的相同的擴充功能共享物件檔案。
停止備用伺服器
如果備用伺服器仍在運行,請立即使用上述說明停止它們。
儲存組態檔案
儲存您需要保留的舊備用伺服器組態目錄中的任何組態檔案,例如 postgresql.conf
(以及它包含的任何檔案)、postgresql.auto.conf
、pg_hba.conf
,因為它們將在下一步中被覆蓋或移除。
運行 rsync
使用連結模式時,可以使用 rsync 快速升級備用伺服器。 為此,從主伺服器上位於舊資料庫叢集目錄和新資料庫叢集目錄之上的目錄中,在每個備用伺服器的主伺服器上運行此命令:
rsync --archive --delete --hard-links --size-only --no-inc-recursive old_cluster new_cluster remote_dir
其中 old_cluster
和 new_cluster
相對於主伺服器上的目前目錄,而 remote_dir
位於備用伺服器上的舊叢集目錄和新叢集目錄之上。 主伺服器和備用伺服器上指定目錄下的目錄結構必須匹配。 請參閱 rsync 手冊頁以瞭解指定遠端目錄的詳細資訊,例如:
rsync --archive --delete --hard-links --size-only --no-inc-recursive /opt/PostgreSQL/12 \ /opt/PostgreSQL/17 standby.example.com:/opt/PostgreSQL
您可以使用 rsync 的 --dry-run
選項來驗證該命令將執行的操作。 雖然必須在主伺服器上針對至少一個備用伺服器運行 rsync,但可以在升級後的備用伺服器上運行 rsync 來升級其他備用伺服器,只要未啟動升級後的備用伺服器即可。
這個動作會記錄 pg_upgrade 在連結模式下建立的連結,這些連結連接主要伺服器上新舊叢集中的檔案。然後,它會在備用伺服器的舊叢集中找到匹配的檔案,並在備用伺服器的新叢集中為它們建立連結。主要伺服器上未連結的檔案會從主要伺服器複製到備用伺服器。(通常檔案很小。)這提供了快速的備用伺服器升級。不幸的是,rsync 會不必要地複製與臨時表和未記錄表相關的檔案,因為這些檔案通常不存在於備用伺服器上。
如果您有表空間,則需要為每個表空間目錄執行類似的 rsync 命令,例如:
rsync --archive --delete --hard-links --size-only --no-inc-recursive /vol1/pg_tblsp/PG_12_201909212 \ /vol1/pg_tblsp/PG_17_202307071 standby.example.com:/vol1/pg_tblsp
如果您已將 pg_wal
重新定位到資料目錄之外,則也必須在這些目錄上執行 rsync。
設定串流複製和記錄傳送備用伺服器
設定伺服器以進行記錄傳送。(您不需要執行 pg_backup_start()
和 pg_backup_stop()
或進行檔案系統備份,因為備用伺服器仍然與主要伺服器同步。)如果舊的主要伺服器早於 17.0 版本,則主要伺服器上的任何槽位都不會複製到新的備用伺服器,因此必須手動重新建立舊備用伺服器上的所有槽位。如果舊的主要伺服器是 17.0 或更新版本,則只有主要伺服器上的邏輯槽位會複製到新的備用伺服器,但舊備用伺服器上的其他槽位不會複製,因此必須手動重新建立。
還原 pg_hba.conf
如果您修改了 pg_hba.conf
,請還原其原始設定。也可能需要調整新叢集中的其他組態檔,以符合舊叢集,例如 postgresql.conf
(以及它包含的任何檔案)、postgresql.auto.conf
。
啟動新的伺服器
現在可以安全地啟動新的伺服器,然後啟動任何 rsync'ed 備用伺服器。
升級後處理
如果需要任何升級後處理,pg_upgrade 將在完成時發出警告。它還將產生必須由管理員執行的腳本檔案。腳本檔案將連接到每個需要升級後處理的資料庫。每個腳本都應該使用以下方式執行
psql --username=postgres --file=script.sql postgres
這些腳本可以按任何順序執行,並且一旦執行完畢就可以刪除。
通常,在重建腳本完成執行之前,存取重建腳本中引用的表是不安全的;這樣做可能會產生不正確的結果或較差的效能。未在重建腳本中引用的表可以立即存取。
統計資訊
由於最佳化器統計資訊不會由 pg_upgrade
傳輸,因此您將被指示在升級結束時執行命令以重新產生該資訊。您可能需要設定連線參數以符合您的新叢集。
使用 vacuumdb --all --analyze-only
可以有效地產生這些統計資訊,並且使用 --jobs
可以加快速度。--analyze-in-stages
選項可用於快速產生最小的統計資訊。如果 vacuum_cost_delay
設定為非零值,則可以使用 PGOPTIONS
覆蓋此設定以加快統計資訊的產生速度,例如 PGOPTIONS='-c vacuum_cost_delay=0' vacuumdb ...
。
刪除舊的叢集
一旦您對升級感到滿意,您可以執行 pg_upgrade
完成時提到的腳本,來刪除舊叢集的資料目錄。(如果您在舊的資料目錄中有使用者定義的表空間,則無法自動刪除。)您也可以刪除舊的安裝目錄(例如,bin
、share
)。
恢復到舊的叢集
如果在執行 pg_upgrade
之後,您希望恢復到舊的叢集,則有幾種選擇
如果使用了 --check
選項,則舊的叢集未被修改;它可以重新啟動。
如果 沒有 使用 --link
選項,則舊的叢集未被修改;它可以重新啟動。
如果使用了 --link
選項,則資料檔案可能在新舊叢集之間共享
如果在連結開始之前 pg_upgrade
中止,則舊的叢集未被修改;它可以重新啟動。
如果您沒有啟動新的叢集,則舊的叢集未被修改,除非在連結開始時,.old
後綴被附加到 $PGDATA/global/pg_control
。要重複使用舊的叢集,請從 $PGDATA/global/pg_control
中刪除 .old
後綴;然後您可以重新啟動舊的叢集。
如果您啟動了新的叢集,它已經寫入了共享檔案,並且使用舊的叢集是不安全的。在這種情況下,舊的叢集將需要從備份中還原。
可以使用一些環境變數為命令行選項提供預設值
PGBINOLD
舊的 PostgreSQL 可執行檔目錄;選項 -b
/--old-bindir
。
PGBINNEW
新的 PostgreSQL 可執行檔目錄;選項 -B
/--new-bindir
。
PGDATAOLD
舊的資料庫叢集配置目錄;選項 -d
/--old-datadir
。
PGDATANEW
新的資料庫叢集配置目錄;選項 -D
/--new-datadir
。
PGPORTOLD
舊的叢集端口號;選項 -p
/--old-port
。
PGPORTNEW
新的叢集端口號;選項 -P
/--new-port
。
PGSOCKETDIR
用於升級期間的 postmaster socket 的目錄;選項 -s
/--socketdir
。
PGUSER
叢集的安裝使用者名稱;選項 -U
/--username
。
pg_upgrade 建立各種工作檔案,例如 schema 傾印,儲存在新叢集目錄中的 pg_upgrade_output.d
中。每次執行都會建立一個新的子目錄,該子目錄以 ISO 8601 (%Y%m%dT%H%M%S
) 格式的時間戳記命名,所有產生的檔案都儲存在其中。如果 pg_upgrade 成功完成,pg_upgrade_output.d
及其包含的檔案將自動刪除;但是,如果出現問題,其中的檔案可能會提供有用的除錯資訊。
pg_upgrade 在舊的和新的資料目錄中啟動短期的 postmaster。預設情況下,用於與這些 postmaster 通訊的臨時 Unix socket 檔案是在目前的工作目錄中建立的。在某些情況下,目前目錄的路徑名稱可能太長而無法成為有效的 socket 名稱。在這種情況下,您可以使用 -s
選項將 socket 檔案放入具有較短路徑名稱的目錄中。為了安全起見,請確保該目錄對任何其他使用者都不可讀或不可寫。(Windows 不支援此功能。)
如果任何失敗、重建和重新索引的情況影響您的安裝,pg_upgrade 將會報告所有這些情況;將自動產生重建表和索引的升級後腳本。如果您嘗試自動化許多叢集的升級,您應該發現具有相同資料庫 schema 的叢集需要相同的叢集升級後步驟;這是因為升級後步驟是基於資料庫 schema,而不是使用者資料。
對於部署測試,建立一個只有 schema 的舊叢集副本,插入虛擬資料,然後升級它。
pg_upgrade 不支援升級包含使用以下 reg*
OID 引用系統資料類型表欄位的資料庫
regcollation |
regconfig |
regdictionary |
regnamespace |
regoper |
regoperator |
regproc |
regprocedure |
(regclass
、regrole
和 regtype
可以升級。)
如果您想使用連結模式,並且不希望在啟動新叢集時修改舊叢集,請考慮使用複製模式。如果複製模式不可用,請複製舊叢集,然後在連結模式下升級該副本。若要建立舊叢集的有效副本,請使用 rsync
在伺服器執行時建立舊叢集的「髒」副本,然後關閉舊伺服器,並再次執行 rsync --checksum
以更新副本,使其保持一致。(--checksum
是必要的,因為 rsync
的檔案修改時間的精確度只有一秒。)您可能需要排除某些檔案,例如 postmaster.pid
,如 第 25.3.4 節 中所述。如果您的檔案系統支援檔案系統快照或寫入時複製檔案副本,您可以使用它來建立舊叢集和表格空間的備份,但快照和副本必須同時建立,或者在資料庫伺服器關閉時建立。
如果您在文件中看到任何不正確、與特定功能的體驗不符或需要進一步澄清的地方,請使用此表單來報告文件問題。