CREATE SUBSCRIPTION — 定义一个新的订阅
CREATE SUBSCRIPTIONsubscription_name
CONNECTION 'conninfo
' PUBLICATIONpublication_name
[, ...] [ WITH (subscription_parameter
[=value
] [, ... ] ) ]
CREATE SUBSCRIPTION
添加一个新的逻辑复制订阅。创建订阅的用户
成为该订阅的所有者。订阅名称必须与当前数据库中任何现有订阅的名称不同。
订阅表示与发布者的复制连接。因此,除了在本地目录中添加定义外,该命令通常会在发布者上创建一个复制槽。
逻辑复制工作者将在运行此命令的事务提交时开始为新订阅复制数据,除非订阅最初被禁用。
要能够创建订阅,您必须拥有pg_create_subscription
角色的权限,
以及当前数据库上的CREATE
权限。
关于订阅和逻辑复制的更多信息,请参见 Section 29.2和 Chapter 29。
subscription_name
#新订阅的名称。
CONNECTION 'conninfo
'
#定义如何连接到发布者数据库的libpq连接字符串。详情请参见Section 32.1.1。
PUBLICATION publication_name
[, ...]
#要订阅的发布者上的发布名称。
WITH ( subscription_parameter
[= value
] [, ... ] )
#本条款指定了订阅的可选参数。
以下参数控制订阅创建期间发生的操作:
连接
(boolean
) #
指定CREATE SUBSCRIPTION
命令是否应当连接到发布者。默认值是
true
。将此设置为false
将强制
create_slot
、enabled
和
copy_data
的值为false
。
(不能将connect
设置为false
,同时将
create_slot
、enabled
或
copy_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
表示不会有与订阅相关联的复制槽。
这样的订阅还必须将 enabled
和 create_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
选项无法使用。
如果发布者是PostgreSQL 16版本之前的版本,
那么即使binary = true
,任何初始表同步也将使用文本格式。
copy_data
(boolean
) #
指定在复制开始时是否复制正在订阅的publication中的预先存在的数据。
默认值为true
。
如果publication包含WHERE
子句,它将影响复制的数据。请参考
Notes获取详细信息。
请参阅Notes了解
copy_data = true
如何与
origin
参数交互的详细信息。
流式处理
(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,
复制工作者将在每个表上以该表的所有者身份执行操作。后一种配置通常
更加安全;详情请参见
Section 29.10。
默认值为 false
。
origin
(string
) #
指定订阅是否会请求发布者仅发送没有来源的更改,或者无论来源如何都发送
更改。将origin
设置为none
表示订阅会请求
发布者仅发送没有来源的更改。将origin
设置为any
表示发布者会发送无论来源如何的更改。默认值是any
。
请参阅Notes了解
copy_data = true
如何与
origin
参数交互的详细信息。
故障切换
(boolean
) #
指定与订阅关联的复制槽是否启用同步到备用节点,以便在故障切换后
可以从新的主节点恢复逻辑复制。默认值为false
。
当指定类型为boolean
的参数时,
=
值
部分可以省略,这等同于指定TRUE
。
有关如何在订阅和发布实例之间配置访问控制的详细信息,请参见 Section 29.10。
创建复制槽时(默认行为), CREATE
SUBSCRIPTION
不能在事务块内部执行。
创建一个连接到同一数据库集群的订阅(例如,在同一集群中的数据库之间
进行复制或在同一数据库内进行复制)只有在复制槽未作为同一命令的一部分
创建时才会成功。否则,CREATE SUBSCRIPTION
调用将会挂起。
为了使其正常工作,请单独创建复制槽(使用函数
pg_create_logical_replication_slot
,插件名称为
pgoutput
),并使用参数
create_slot = false
创建订阅。请参阅
Section 29.2.3
以获取示例。这是一个实现限制,可能会在未来的版本中解除。
如果发布中的任何表具有WHERE
子句,则对于
表达式
计算结果为假或空的行将不会被发布。
如果订阅中有多个发布,其中同一表使用了不同的WHERE
子句,
只要任一表达式(指向该发布操作)满足,行就会被发布。
在不同的WHERE
子句的情况下,如果其中一个发布没有
WHERE
子句(指向该发布操作)或发布被声明为
FOR ALL TABLES
或
FOR TABLES IN SCHEMA
,
则无论其他表达式如何定义,行总是被发布。
如果订阅者是PostgreSQL 15之前的版本,
则在初始数据同步阶段会忽略任何行过滤。
对于这种情况,用户可能需要考虑删除任何最初复制的数据,
这些数据可能与后续过滤不兼容。
由于初始数据同步在复制现有表数据时不考虑发布的
publish
参数,可能会复制一些不会通过DML复制的行。
参见Section 29.2.2了解示例。
具有多个publication的订阅,其中同一表以不同的列列表发布,不受支持。
我们允许指定不存在的publication,以便用户稍后添加。这意味着
pg_subscription
可以有不存在的publication。
当使用订阅参数组合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 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>);
创建一个到远程服务器的订阅,复制发布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
扩展。