CREATE SUBSCRIPTION — 定义新的订阅
CREATE SUBSCRIPTIONsubscription_name
CONNECTION 'conninfo
' PUBLICATIONpublication_name
[, ...] [ WITH (subscription_parameter
[=value
] [, ... ] ) ]
CREATE SUBSCRIPTION
添加新的逻辑复制订阅。创建订阅的用户将成为订阅所有者。订阅名称必须不同于当前数据库中任何现有订阅的名称。
订阅代表与发布者的复制连接。因此,除了在本地目录中添加定义之外,此命令通常还在发布者上创建一个复制槽。
在运行此命令的事务提交时,将启动逻辑复制工作进程,以复制新订阅的数据,除非该订阅最初已禁用。
要能够创建订阅,您必须拥有 pg_create_subscription
角色的权限以及当前数据库的 CREATE
权限。
subscription_name
#新订阅的名称。
CONNECTION 'conninfo
'
#定义如何连接到发布者数据库的 libpq 连接字符串。有关详细信息,请参见 第 32.1.1 节。
PUBLICATION publication_name
[, ...]
#要订阅的发布者上的发布名称。
WITH ( subscription_parameter
[= value
] [, ... ] )
#此子句为订阅指定可选参数。
以下参数控制订阅创建期间发生的操作
connect
(boolean
) #指定 CREATE SUBSCRIPTION
命令是否应连接到发布者。默认值为 true
。将其设置为 false
会强制 create_slot
、enabled
和 copy_data
的值设置为 false
。(不能将 connect
设置为 false
与将 create_slot
、enabled
或 copy_data
设置为 true
结合使用。)
由于在该选项为 false
时未建立连接,因此没有任何表进行订阅。要启动复制,必须手动创建复制槽,在需要时启用故障转移,启用订阅,然后刷新订阅。请参见 第 29.2.3 节 了解示例。
create_slot
(boolean
) #指定该命令是否应在发布者上创建复制槽。默认值为 true
。
如果设置为 false
,则负责以其他方式创建发布者的槽。请参见 第 29.2.3 节 了解示例。
enabled
(boolean
) #指定订阅是否应主动复制,抑或仅设置订阅但不立即启动。默认值为 true
。
slot_name
(string
) #要使用的发布者复制槽的名称。默认情况下,使用订阅名称作为槽的名称。
将 slot_name
设置为 NONE
意味着订阅不与任何复制槽关联。并且此类订阅还必须将 enabled
和 create_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
,内部两阶段状态仍暂时保留“待定”,直到初始化阶段完成。请参阅pg_subscription
的列subtwophasestate
以了解实际的两阶段状态。
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
调用将挂起。要执行此操作,请单独创建复制槽(使用函数 pg_create_logical_replication_slot
和插件名称 pgoutput
),并使用参数 create_slot = false
创建订阅。有关示例,请参见 第 29.2.3 节,这是一个实现限制,可能在以后的版本中解除。
如果发布中的某个表有 WHERE
子句,则评估为错误或空值的 表达式
的行将不会发布。如果订阅包含多个发布,其中同一个表已使用不同的 WHERE
子句发布,则行将在其中任何表达式(引用到发布操作)满足时发布。对于不同的 WHERE
子句,如果其中一个发布没有 WHERE
子句(引用到发布操作)或者该发布被声明为 FOR ALL TABLES
或 FOR TABLES IN SCHEMA
,则无论其他表达式的定义如何,都会始终发布行。如果订阅者为 PostgreSQL 15 之前的版本,则在初始数据同步阶段将忽略任何行筛选。对于此情况,用户可能想要考虑删除任何不兼容后续筛选的初始复制数据。由于初始数据同步在复制现有表数据时不考虑发布 publish
参数,因此可能会复制一些无法使用 DML 复制的行。请参阅 第 29.2.2 节 以获取示例。
不支持在一个表在多个发布中已使用不同的列列表进行发布的订阅。
我们允许指定不存在的发布,以便用户以后添加这些发布。这意味着 pg_subscription
可以包含不存在的发布。
当使用 copy_data = true
和 origin = 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>);
创建一个订阅以连接远程服务器,在发布表中复制表 mypublication
和insert_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 SUBSCRIPTION
是一个 PostgreSQL 扩展。