受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

CREATE SUBSCRIPTION

CREATE SUBSCRIPTION — 定义一个新的订阅

Synopsis

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

描述

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

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

除非订阅初始即被禁用,否则在执行该命令所在事务提交时,会启动一个 逻辑复制工作进程为新订阅复制数据。

要能够创建订阅,必须具有pg_create_subscription角色的权限, 以及当前数据库上的CREATE权限。

关于订阅以及整个逻辑复制的更多信息,请参见 Section 29.2Chapter 29

参数

subscription_name #

新订阅的名称。

CONNECTION 'conninfo' #

定义如何连接到发布者数据库的libpq连接字符串。 详情请参见Section 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时不会建立连接,因此不会订阅任何表。 要启动复制,你必须手工创建复制槽、在需要时启用故障切换、启用订阅, 并刷新订阅。示例见 Section 29.2.3

create_slot (boolean) #

指定该命令是否应在发布者上创建复制槽。默认值为 true

如果设为false,则必须以其他方式自行创建 发布者上的复制槽。示例见 Section 29.2.3

enabled (boolean) #

指定订阅是应当主动进行复制,还是仅完成设置但暂不启动。 默认值为true

slot_name (string) #

要使用的发布者上的复制槽名称。默认使用订阅名称作为槽名。

slot_name设为NONE表示该订阅 不关联任何复制槽。这类订阅还必须同时将enabledcreate_slot设为false。 当你打算稍后手工创建复制槽时,可使用此设置。示例见 Section 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子句,将会影响被复制的数据。 详情请参见Notes

关于copy_data = true如何与 origin参数相互作用的细节,请参见 Notes

streaming (enum) #

指定是否为该订阅启用进行中事务的流式传输。默认值为 parallel,表示如果有可用的并行应用工作进程, 接收到的更改会直接通过其中之一应用。如果没有空闲的并行应用工作进程 可以处理流式事务,那么这些更改会写入临时文件,并在事务提交后再应用。 注意,如果并行应用工作进程中发生错误,远端事务的 finish LSN 可能不会记录到服务器日志中。

Caution

当发布者与订阅者的模式不同时,存在发生死锁的风险,尽管这种情况 很少见。应用工作进程会自动重试这些事务。

如果设为on,接收到的更改会写入临时文件,然后仅在 事务在发布者上提交且被订阅者接收之后才应用。

如果设为off,所有事务都会先在发布者上完全解码, 然后才整体发送给订阅者。

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,复制工作进程会在每张表上以该表所有者 的身份执行操作。后一种配置通常安全得多;详情请参见 Section 29.11。 默认值为false

origin (string) #

指定订阅是请求发布者仅发送没有复制源的更改,还是无论复制源如何都发送更改。 将origin设为none表示订阅会请求 发布者仅发送没有复制源的更改。将origin设为 any表示发布者无论复制源如何都发送更改。默认值为 any

关于copy_data = true如何与 origin参数相互作用的细节,请参见 Notes

failover (boolean) #

指定与该订阅关联的复制槽是否启用同步到备库,以便在故障切换后 能够从新的主库继续逻辑复制。默认值为false

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

注意

关于如何在订阅与发布实例之间配置访问控制,详见 Section 29.11

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

创建一个连接到同一数据库集簇的订阅(例如在同一集簇中的不同数据库之间 复制,或者在同一数据库内复制)时,只有在复制槽不作为同一命令的一部分 创建的情况下才会成功。否则,CREATE SUBSCRIPTION 调用将挂起。要实现这种用法,应分别创建复制槽(使用函数 pg_create_logical_replication_slot并指定插件名 pgoutput),然后使用参数 create_slot = false创建订阅。示例见 Section 29.2.3。 这是一个实现限制,未来版本中可能会解除。

如果发布中的任何表带有WHERE子句,则对 expression求值为 falseNULL的行不会被发布。 如果订阅包含多个发布,且同一张表在这些发布中使用了不同的 WHERE子句,那么只要任意一个表达式(针对相应的 发布操作)满足,该行就会被发布。对于不同的 WHERE子句,如果其中某个发布没有 WHERE子句(针对相应的发布操作),或者该发布被声明为 FOR ALL TABLESFOR TABLES IN SCHEMA, 则无论其他表达式如何定义,该行都会被发布。如果订阅者使用的是 15 之前 版本的PostgreSQL,那么在初始数据同步阶段 会忽略所有行过滤。在这种情况下,用户可能需要考虑删除那些初始复制过来、 但与后续过滤不兼容的数据。由于初始数据同步在复制现有表数据时不会考虑 发布的 publish 参数,因此有些使用 DML 时本不会复制的行,也可能在此阶段被复制。示例见 Section 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
     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扩展。

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。