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

CREATE SUBSCRIPTION

CREATE SUBSCRIPTION — 定義一個新訂閱

概要

CREATE SUBSCRIPTION subscription_name
    CONNECTION 'conninfo'
    PUBLICATION publication_name [, ...]
    [ WITH ( subscription_parameter [= value] [, ... ] ) ]

描述

CREATE SUBSCRIPTION 新增一個新的邏輯複製訂閱。建立訂閱的使用者將成為訂閱的所有者。訂閱名稱必須與當前資料庫中任何現有訂閱的名稱不同。

訂閱代表與釋出者(publisher)的複製連線。因此,除了在本地目錄中新增定義外,此命令通常會在釋出者上建立一個複製槽(replication slot)。

除非訂閱最初被停用,否則將在執行此命令的事務提交時啟動一個邏輯複製工作程序來複制新訂閱的資料。

要能夠建立訂閱,您必須擁有 pg_create_subscription 角色的許可權,以及對當前資料庫的 CREATE 許可權。

有關訂閱和整體邏輯複製的更多資訊,請參閱 第 29.2 節第 29 章

引數

subscription_name #

新訂閱的名稱。

CONNECTION 'conninfo' #

定義如何連線到釋出者資料庫的 libpq 連線字串。有關詳細資訊,請參閱 第 32.1.1 節

PUBLICATION publication_name [, ...] #

要在釋出者上訂閱的釋出的名稱。

WITH ( subscription_parameter [= value] [, ... ] ) #

此子句指定訂閱的可選引數。

以下引數控制訂閱建立期間發生的情況

connect (boolean) #

指定 CREATE SUBSCRIPTION 命令是否應連線到釋出者。預設為 true。將其設定為 false 將強制將 create_slotenabledcopy_data 的值設定為 false。(您不能將 connect 設定為 false 與將 create_slotenabledcopy_data 設定為 true 結合使用。)

由於當此選項為 false 時不進行連線,因此不訂閱任何表。要啟動複製,您必須手動建立複製槽,根據需要啟用故障轉移,啟用訂閱,並重新整理訂閱。有關示例,請參閱 第 29.2.3 節

create_slot (boolean) #

指定命令是否應在釋出者上建立複製槽。預設為 true

如果設定為 false,您將負責以其他方式建立釋出者的槽。有關示例,請參閱 第 29.2.3 節

enabled (boolean) #

指定訂閱是否應主動複製,還是僅設定好但尚未啟動。預設為 true

slot_name (string) #

要使用的釋出者複製槽的名稱。預設使用訂閱名稱作為槽名稱。

slot_name 設定為 NONE 意味著訂閱將沒有關聯的複製槽。此類訂閱也必須將 enabledcreate_slot 都設定為 false。當您稍後手動建立複製槽時使用此選項。有關示例,請參閱 第 29.2.3 節

當將 slot_name 設定為有效名稱且 create_slot 設定為 false 時,已命名槽的 failover 屬性值可能與訂閱中指定的對應 failover 引數不同。務必確保釋出者上槽的 failover 屬性與訂閱的對應引數匹配,反之亦然。否則,釋出者上的槽的行為可能與這些訂閱選項的說法不同:例如,即使訂閱的 failover 選項被停用,釋出者上的槽也可能同步到備用伺服器,或者即使訂閱的 failover 選項被啟用,釋出者上的槽也可能被停用同步。

以下引數控制訂閱建立後的複製行為

binary (boolean) #

指定訂閱是否請求釋出者以二進位制格式(而不是文字格式)傳送資料。預設為 false。任何初始表同步複製(參見 copy_data)也使用相同的格式。二進位制格式可能比文字格式更快,但它在機器體系結構和 PostgreSQL 版本之間的可移植性較差。二進位制格式非常特定於資料型別;例如,它不允許將 smallint 列複製到 integer 列,即使在文字格式下這也沒問題。即使啟用了此選項,只有具有二進位制傳送和接收函式的(send and receive functions)資料型別才會以二進位制形式傳輸。請注意,初始同步要求所有資料型別都具有二進位制傳送和接收函式,否則同步將失敗(有關傳送/接收函式的更多資訊,請參閱 CREATE TYPE)。

進行跨版本複製時,釋出者可能對某些資料型別具有二進位制傳送函式,而訂閱者缺少該型別的二進位制接收函式。在這種情況下,資料傳輸將失敗,並且無法使用 binary 選項。

如果釋出者是 16 版之前的 PostgreSQL 版本,則即使 binary = true,任何初始表同步也將使用文字格式。

copy_data (boolean) #

指定在複製開始時是否複製被訂閱的釋出者中的現有資料。預設為 true

如果釋出者包含 WHERE 子句,則會影響複製哪些資料。有關詳細資訊,請參閱 備註

有關 copy_data = true 如何與 origin 引數互動的詳細資訊,請參閱 備註

streaming (enum) #

指定是否為該訂閱啟用進行中事務的流式傳輸。預設值是 parallel,這意味著傳入的更改將直接透過一個可用的並行應用工作程序(apply worker)進行應用。如果沒有空閒的並行應用工作程序來處理流式事務,則更改將寫入臨時檔案並在事務提交後應用。請注意,如果在並行應用工作程序中發生錯誤,遠端事務的完成 LSN 可能不會在伺服器日誌中報告。

注意

當釋出者和訂閱者之間的架構不同時,存在死鎖的風險,儘管這種情況很少見。應用工作程序能夠自動重試這些事務。

如果設定為 on,則傳入的更改將寫入臨時檔案,然後在事務在釋出者上提交併由訂閱者接收後才應用。

如果設定為 off,所有事務將在釋出者上完全解碼,然後才作為一個整體傳送到訂閱者。

synchronous_commit (enum) #

此引數的值將覆蓋該訂閱的應用工作程序內的 synchronous_commit 設定。預設值為 off

對邏輯複製使用 off 是安全的:如果訂閱者因同步丟失而丟失事務,資料將從釋出者重新發送。

當進行同步邏輯複製時,可能需要不同的設定。邏輯複製工作程序會向釋出者報告寫入和重新整理(flush)的位置,並且在使用同步複製時,釋出者將等待實際重新整理。這意味著將訂閱者的 synchronous_commit 設定為 off,當訂閱用於同步複製時,可能會增加發布者上 COMMIT 的延遲。在這種情況下,將 synchronous_commit 設定為 local 或更高可能更有利。

two_phase (boolean) #

指定是否為該訂閱啟用兩階段提交。預設為 false

當啟用兩階段提交時,準備好的事務將在 PREPARE TRANSACTION 時傳送到訂閱者,並在訂閱者上作為兩階段事務進行處理。否則,準備好的事務僅在提交時傳送到訂閱者,然後由訂閱者立即處理。

兩階段提交的實現要求複製已成功完成初始表同步階段。因此,即使 two_phase 對訂閱啟用,內部兩階段狀態在初始化階段完成之前將暫時保持 pending 狀態。有關實際兩階段狀態,請參閱 pg_subscriptionsubtwophasestate 列。

disable_on_error (boolean) #

指定在訂閱工作程序從釋出者複製資料期間檢測到任何錯誤時,是否應自動停用訂閱。預設為 false

password_required (boolean) #

如果設定為 true,由此訂閱引起的對釋出者的連線必須使用密碼認證,並且密碼必須作為連線字串的一部分指定。當訂閱由超級使用者擁有時,此設定將被忽略。預設為 true。只有超級使用者可以將此值設定為 false

run_as_owner (boolean) #

如果為 true,則所有複製操作都將以訂閱所有者的身份執行。如果為 false,複製工作程序將以每個表的擁有者的身份執行操作。後者通常更安全;有關詳細資訊,請參閱 第 29.11 節。預設為 false

origin (string) #

指定訂閱是否請求釋出者僅傳送沒有 origin 的更改,或者傳送不考慮 origin 的更改。將 origin 設定為 none 意味著訂閱將請求釋出者僅傳送沒有 origin 的更改。將 origin 設定為 any 意味著釋出者會發送不考慮 origin 的更改。預設為 any

有關 copy_data = true 如何與 origin 引數互動的詳細資訊,請參閱 備註

failover (boolean) #

指定與訂閱關聯的複製槽是否已啟用同步到備用伺服器,以便在故障轉移後可以從新主伺服器恢復邏輯複製。預設為 false

指定布林型別引數時,可以省略 = value 部分,這等同於指定 TRUE

註釋

有關如何配置訂閱和釋出者例項之間的訪問控制的詳細資訊,請參閱 第 29.11 節

當建立複製槽時(預設行為),CREATE SUBSCRIPTION 不能在事務塊內執行。

建立連線到同一資料庫叢集的訂閱(例如,在同一叢集中的資料庫之間進行復制或在同一資料庫內進行復制)只有在複製槽不是透過同一命令建立時才會成功。否則,CREATE SUBSCRIPTION 呼叫將掛起。要使此功能正常工作,請單獨建立複製槽(使用函式 pg_create_logical_replication_slot 並指定外掛名稱 pgoutput),然後使用引數 create_slot = false 建立訂閱。有關示例,請參閱 第 29.2.3 節。這是一個實現限制,未來版本可能會解除。

如果釋出者中的任何表具有 WHERE 子句,則 expression 計算為 falseNULL 的行將不會被髮布。如果訂閱包含多個釋出者,並且同一個表在這些釋出者中以不同的 WHERE 子句釋出,那麼如果任何一個表示式(引用該釋出操作)得到滿足,該行就會被髮布。在不同的 WHERE 子句的情況下,如果其中一個釋出者沒有 WHERE 子句(引用該釋出操作),或者釋出者被宣告為 FOR ALL TABLESFOR TABLES IN SCHEMA,則無論其他表示式如何定義,行始終會被髮布。如果訂閱者是 15 版之前的 PostgreSQL 版本,則在初始資料同步階段會忽略所有行過濾。在這種情況下,使用者可能需要考慮刪除任何最初複製的、與後續過濾不相容的資料。由於初始資料同步在複製現有表資料時不會考慮釋出者 publish 引數,因此可能會複製一些行,而這些行在 DML 中將不會被複制。有關示例,請參閱 第 29.2.2 節

不支援具有多個釋出者,並且在這些釋出者中同一個表以不同的列列表釋出的情況。

我們允許指定不存在的釋出者,以便使用者稍後新增它們。這意味著 pg_subscription 可以包含不存在的釋出者。

當使用 copy_data = trueorigin = NONE 的訂閱引數組合時,初始同步表資料將直接從釋出者複製,這意味著無法瞭解該資料的真實 origin。如果釋出者也有訂閱,則複製的表資料可能源自更上游。這種情況會被檢測到並向用戶記錄一個 WARNING,但警告僅表示潛在問題;使用者有責任進行必要的檢查,以確保複製的資料 origin 確實如期望的那樣或不是。

要查詢哪些表可能包含非本地 origin(由於在釋出者上建立了其他訂閱),請嘗試執行以下 SQL 查詢

# substitute <pub-names> below with your publication name(s) to be queried
SELECT DISTINCT PT.schemaname, PT.tablename
FROM pg_publication_tables PT
     JOIN pg_class C ON (C.relname = PT.tablename)
     JOIN pg_namespace N ON (N.nspname = PT.schemaname),
     pg_subscription_rel PS
WHERE C.relnamespace = N.oid AND
      (PS.srrelid = C.oid OR
      C.oid IN (SELECT relid FROM pg_partition_ancestors(PS.srrelid) UNION
                SELECT relid FROM pg_partition_tree(PS.srrelid))) AND
      PT.pubname IN (<pub-names>);

示例

建立一個訂閱,連線到遠端伺服器,複製 mypublicationinsert_only 這兩個釋出者中的表,並在提交時立即開始複製

CREATE SUBSCRIPTION mysub
         CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
        PUBLICATION mypublication, insert_only;

建立一個訂閱,連線到遠端伺服器,複製 insert_only 釋出者中的表,並且在稍後啟用之前不會開始複製。

CREATE SUBSCRIPTION mysub
         CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
        PUBLICATION insert_only
               WITH (enabled = false);

相容性

CREATE SUBSCRIPTIONPostgreSQL 的擴充套件。

提交更正

如果您在文件中看到任何不正確、與您對特定功能的經驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。