2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4

47.2. 邏輯解碼概念 #

47.2.1. 邏輯解碼 #

邏輯解碼是指將資料庫表中所有永續性更改提取成一種連貫、易於理解的格式的過程,這種格式可以在不知道資料庫內部狀態的詳細資訊的情況下進行解釋。

PostgreSQL 中,邏輯解碼是透過解碼 預寫日誌 (write-ahead log) 的內容來實現的,該日誌描述了儲存層面的更改,並將其解碼成特定於應用程式的格式,例如元組流或 SQL 語句。

47.2.2. 複製槽 #

在邏輯複製的上下文中,複製槽代表了一個可以按照原始伺服器上發生的順序回放給客戶端的更改流。每個複製槽都從單個數據庫流式傳輸一系列更改。

注意

PostgreSQL 還有流式複製槽(請參閱 第 26.2.5 節),但在此處它們的使用方式略有不同。

複製槽有一個在 PostgreSQL 叢集的所有資料庫中都唯一的識別符號。複製槽獨立於使用它們的連線而存在,並且是崩潰安全的。

在正常操作中,邏輯複製槽只會發出每個更改一次。每個複製槽的當前位置僅在檢查點時持久化,因此在發生崩潰的情況下,複製槽可能會回退到較早的 LSN,這將在伺服器重新啟動時導致最近的更改被再次傳送。邏輯解碼客戶端負責避免處理同一訊息多次而產生的負面影響。客戶端可能希望記錄它們在解碼時看到的最後一個 LSN,並跳過任何重複的資料,或者(在使用複製協議時)請求從該 LSN 開始解碼,而不是讓伺服器確定起始點。複製進度跟蹤功能就是為此目的而設計的,請參閱 複製源

對於單個數據庫,可以存在多個獨立的複製槽。每個複製槽都有自己的狀態,允許不同的使用者從資料庫更改流中的不同點接收更改。對於大多數應用程式,每個使用者都需要一個單獨的複製槽。

邏輯複製槽不瞭解接收者(或接收者們)的狀態。甚至可能在不同時間有多個不同的接收者使用同一個複製槽;它們只會獲取上一個接收者停止消耗它們之後的更改。在任何給定時間,只有一個接收者可以從一個複製槽消耗更改。

邏輯複製槽也可以在熱備伺服器上建立。為防止 VACUUM 從系統目錄中移除必需的行,應在備伺服器上設定 hot_standby_feedback。儘管如此,如果任何必需的行被移除,複製槽就會失效。強烈建議在主伺服器和備伺服器之間使用物理複製槽。否則,hot_standby_feedback 將僅在連線存活時起作用(例如,節點重啟會破壞它)。然後,主伺服器可能會刪除備伺服器上的邏輯解碼可能需要的系統目錄行(因為它不知道備伺服器上的 catalog_xmin)。如果在主伺服器上將 wal_level 降低到低於 logical,備伺服器上現有的邏輯複製槽也會失效。一旦備伺服器檢測到 WAL 流中的這種變化,就會發生這種情況。這意味著,對於延遲的 walsender(如果有的話),主伺服器上 wal_level 引數更改之前的某些 WAL 記錄將不會被解碼。

建立邏輯複製槽需要有關所有當前正在執行事務的資訊。在主伺服器上,此資訊可直接獲得,但在備伺服器上,必須從主伺服器獲取此資訊。因此,複製槽的建立可能需要等待主伺服器上發生某些活動。如果主伺服器處於空閒狀態,在備伺服器上建立邏輯複製槽可能需要顯著的時間。這可以透過在主伺服器上呼叫 pg_log_standby_snapshot 函式來加速。

注意

複製槽在崩潰後仍然存在,並且不瞭解其消費者(或消費者們)的狀態。即使沒有連線使用它們,它們也會阻止移除必需的資源。這會消耗儲存空間,因為只要複製槽需要,VACUUM 就無法移除必需的 WAL 或系統目錄中的必需行。在極端情況下,這可能導致資料庫關閉以防止事務 ID 迴繞(請參閱 第 24.1.5 節)。因此,如果不再需要複製槽,就應該將其刪除。

47.2.3. 複製槽同步 #

主伺服器上的邏輯複製槽可以透過使用 pg_create_logical_replication_slotfailover 引數,或透過在複製槽建立期間使用 CREATE SUBSCRIPTIONfailover 選項來同步到熱備伺服器。此外,還需要在備伺服器上啟用 sync_replication_slots。透過在備伺服器上啟用 sync_replication_slots,可以在 slotsync 工作程序中定期同步故障轉移複製槽。為了使同步正常工作,必須在主伺服器和備伺服器之間有一個物理複製槽(即,在備伺服器上配置了 primary_slot_name),並且在備伺服器上必須啟用了 hot_standby_feedback。還必須在 primary_conninfo 中指定一個有效的 dbname。強烈建議在主伺服器的 synchronized_standby_slots 列表中命名上述物理複製槽,以防止訂閱者比熱備伺服器更快地消耗更改。即使配置正確,由於等待 synchronized_standby_slots 中命名的複製槽,在將更改傳送給邏輯訂閱者時也可能存在一些延遲。當使用 synchronized_standby_slots 時,主伺服器不會完全關閉,直到與 synchronized_standby_slots 中指定的物理複製槽關聯的備伺服器確認接收了 WAL 到主伺服器上的最新重新整理位置。

注意

雖然啟用 sync_replication_slots 允許自動定期同步故障轉移複製槽,但也可以在備伺服器上使用 pg_sync_replication_slots 函式手動同步它們。然而,此函式主要用於測試和除錯,應謹慎使用。與自動同步不同,它不包含迴圈重試,使其更容易發生同步失敗,特別是在初始同步場景中,此時所需的 WAL 檔案或複製槽的目錄行可能已被移除或有被移除的風險。相比之下,透過 sync_replication_slots 進行的自動同步提供連續的複製槽更新,從而實現無縫故障轉移並支援高可用性。因此,它是同步複製槽的推薦方法。

當複製槽同步按照建議進行配置,並且初始同步由 pg_sync_replication_slots 自動或手動完成時,備伺服器僅在滿足以下條件時才能持久化同步的複製槽:主伺服器上的邏輯複製槽必須保留備伺服器上仍可用的 WAL 和系統目錄行。這確保了資料完整性,並允許在提升後邏輯複製順利繼續。如果所需的 WAL 或目錄行已從備伺服器中清除,複製槽將不會被持久化以避免資料丟失。在這種情況下,可能會出現以下日誌訊息

LOG:  could not synchronize replication slot "failover_slot"
DETAIL:  Synchronization could lead to data loss, because the remote slot needs WAL at LSN 0/3003F28 and catalog xmin 754, but the standby has LSN 0/3003F28 and catalog xmin 756.

如果邏輯複製槽被消費者主動使用,則無需手動干預;複製槽將自動前進,並在下一個週期恢復同步。但是,如果沒有配置消費者,建議使用 pg_logical_slot_get_changespg_logical_slot_get_binary_changes 在主伺服器上手動推進複製槽,從而允許同步繼續。

在故障轉移後恢復邏輯複製的能力取決於故障轉移時備伺服器上同步複製槽的 pg_replication_slots.synced 值。只有在故障轉移前在備伺服器上達到同步狀態為 true 的持久化複製槽才能在故障轉移後用於邏輯複製。臨時同步的複製槽不能用於邏輯解碼,因此這些複製槽的邏輯複製無法恢復。例如,如果同步的複製槽由於停用了訂閱而無法在備伺服器上持久化,那麼即使重新啟用訂閱,在故障轉移後也無法恢復訂閱。

要從同步的邏輯複製槽恢復邏輯複製,必須更改訂閱的 'conninfo' 以指向新的主伺服器。這可以透過 ALTER SUBSCRIPTION ... CONNECTION 來完成。建議在提升備伺服器之前先停用訂閱,並在更改連線字串後重新啟用它們。

注意

有可能在提升期間舊的主伺服器會重新上線,並且如果訂閱沒有被停用,邏輯訂閱者可能會繼續從舊的主伺服器接收資料,即使在提升之後,直到連線字串被更改。這可能會導致資料不一致問題,從而阻止邏輯訂閱者能夠從新的主伺服器繼續複製。

47.2.4. 輸出外掛 #

輸出外掛將預寫日誌的內部表示形式中的資料轉換為複製槽使用者所需的格式。

47.2.5. 匯出的快照 #

當使用流式複製介面(請參閱 CREATE_REPLICATION_SLOT)建立新的複製槽時,會匯出一個快照(請參閱 第 9.28.5 節),該快照將準確顯示資料庫在所有更改將被包含在更改流中的狀態。這可以用於建立新的副本,方法是使用 SET TRANSACTION SNAPSHOT 讀取複製槽建立時的資料庫狀態。然後可以使用此事務轉儲當時資料庫的狀態,之後可以使用複製槽的內容進行更新,而不會丟失任何更改。

不需要快照匯出的應用程式可以使用 SNAPSHOT 'nothing' 選項將其停用。

提交更正

如果您在文件中發現任何不正確之處,與您對特定功能的體驗不符,或需要進一步澄清,請使用 此表單 報告文件問題。