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 的扩展。

提交更正

如果您在文档中看到任何不正确、与您对特定功能的经验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。