2024 年 9 月 26 日:PostgreSQL 17 发布!
支持版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10

CREATE SUBSCRIPTION

CREATE SUBSCRIPTION — 定义新的订阅

概要

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

描述

CREATE SUBSCRIPTION 添加新的逻辑复制订阅。创建订阅的用户将成为订阅的所有者。订阅名称必须不同于当前数据库中任何现有订阅的名称。

订阅代表与发布者的复制连接。因此,除了在本地目录中添加定义之外,此命令通常还会在发布者上创建复制槽。

逻辑复制工作程序将在运行此命令的事务提交时启动,以复制新订阅的数据,除非订阅最初被禁用。

要创建订阅,您必须拥有 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 列,即使在文本格式中可以正常工作。即使启用了此选项,也只有具有二进制发送和接收函数的数据类型才能以二进制格式传输。请注意,初始同步需要所有数据类型都具有二进制发送和接收函数,否则同步将失败(有关发送/接收函数的更多信息,请参阅CREATE TYPE)。

在进行跨版本复制时,发布者可能对某些数据类型具有二进制发送函数,但订阅者可能缺少对该类型的二进制接收函数。在这种情况下,数据传输将失败,并且无法使用 binary 选项。

如果发布者是 16 之前的 PostgreSQL 版本,则即使 binary = true,任何初始表同步也将使用文本格式。

copy_data (boolean) #

指定当复制开始时是否复制正在订阅的发布中的现有数据。默认值为 true

如果发布包含 WHERE 子句,它将影响复制的数据。有关详细信息,请参阅注释

有关 copy_data = true 如何与 origin 参数交互的详细信息,请参阅注释

streaming (enum) #

指定是否为该订阅启用正在进行的事务流。默认值为 off,这意味着所有事务都在发布者上完全解码,然后才以整体形式发送给订阅者。

如果设置为 on,传入的更改将写入临时文件,然后仅在事务在发布者上提交并由订阅者接收后应用。

如果设置为 parallel,传入的更改将通过一个并行应用工作程序(如果有)直接应用。如果没有任何并行应用工作程序可以处理流事务,则更改将写入临时文件,并在事务提交后应用。请注意,如果并行应用工作程序中发生错误,远程事务的结束 LSN 可能不会在服务器日志中报告。

synchronous_commit (enum) #

此参数的值将覆盖此订阅的应用工作程序进程中的 synchronous_commit 设置。默认值为 off

对逻辑复制使用 off 是安全的:如果订阅者因缺少同步而丢失事务,数据将从发布者再次发送。

在进行同步逻辑复制时,可能需要使用不同的设置。逻辑复制工作程序会向发布者报告写入和刷新的位置,而在使用同步复制时,发布者将等待实际刷新。这意味着,当订阅用于同步复制时,将订阅者的 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.10 节。默认值为 false

origin (string) #

指定订阅是否会请求发布者仅发送没有源的更改,或者发送无论源如何的更改。将 origin 设置为 none 表示订阅将请求发布者仅发送没有源的更改。将 origin 设置为 any 表示发布者会发送更改,无论其源是什么。默认值为 any

有关 copy_data = true 如何与 origin 参数交互的详细信息,请参阅注释

failover (boolean) #

指定与订阅关联的复制槽位是否能够同步到备用服务器,以便在故障转移后从新的主服务器恢复逻辑复制。默认值为 false

当指定类型为 boolean 的参数时,可以省略 = value 部分,这等同于指定 TRUE

注意

有关如何配置订阅和发布实例之间的访问控制的详细信息,请参见 第 29.10 节

当创建复制槽位(默认行为)时,CREATE SUBSCRIPTION 不能在事务块中执行。

创建连接到同一个数据库集群的订阅(例如,在同一个集群中的数据库之间复制或在同一个数据库内复制)只有在没有作为同一个命令的一部分创建复制槽位时才会成功。否则,CREATE SUBSCRIPTION 调用将挂起。要使其正常工作,请单独创建复制槽位(使用具有插件名称 pgoutput 的函数 pg_create_logical_replication_slot),并使用参数 create_slot = false 创建订阅。有关示例,请参见 第 29.2.3 节。这是一个实现限制,可能会在将来的版本中解除。

如果发布中的任何表都有 WHERE 子句,则对于 expression 评估结果为 false 或 null 的行将不会发布。如果订阅中有多个发布,其中同一个表已使用不同的 WHERE 子句发布,则如果任何表达式(引用该发布操作)满足,则会发布一行。在不同的 WHERE 子句的情况下,如果其中一个发布没有 WHERE 子句(引用该发布操作),或者发布被声明为 FOR ALL TABLESFOR TABLES IN SCHEMA,则无论其他表达式的定义如何,都会始终发布行。如果订阅者是 15 之前的 PostgreSQL 版本,则在初始数据同步阶段将忽略任何行过滤。在这种情况下,用户可能需要考虑删除任何最初复制的数据,因为这些数据可能与后续过滤不兼容。由于初始数据同步在复制现有表数据时不会考虑发布 publish 参数,因此可能复制了一些使用 DML 不会复制的行。有关示例,请参见 第 29.2.2 节

不支持具有多个发布的订阅,其中同一个表已使用不同的列列表发布。

我们允许指定不存在的发布,以便用户以后可以添加它们。这意味着 pg_subscription 可以具有不存在的发布。

当使用 copy_data = trueorigin = NONE 的订阅参数组合时,初始同步表数据直接从发布者复制,这意味着不可能了解该数据的真实源。如果发布者也有订阅,则复制的表数据可能来自更上游。这种场景会检测到并向用户记录一个 WARNING,但该警告只是一个潜在问题的指示;用户有责任进行必要的检查以确保复制的数据来源确实是想要的,或者不是。

要查找哪些表可能包含非本地来源(由于在发布者上创建的其他订阅),请尝试以下 SQL 查询

# substitute <pub-names> below with your publication name(s) to be queried
SELECT DISTINCT PT.schemaname, PT.tablename
FROM pg_publication_tables PT,
     pg_subscription_rel PS
     JOIN pg_class C ON (C.oid = PS.srrelid)
     JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE N.nspname = PT.schemaname AND
      C.relname = PT.tablename 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 的扩展。

提交更正

如果您在文档中看到任何不正确的内容,不符合您对特定功能的体验,或者需要进一步说明,请使用 此表格 报告文档问题。