瀚高数据库
目录
环境
文档用途
详细信息
环境
系统平台:Linux x86-64 Red Hat Enterprise Linux 7
版本:14
文档用途
本文翻译了pglogical扩展的官方文档,介绍了pglogical扩展的各类管理函数及使用限制,详情请看下文.
一、节点管理
节点可以使用以下SQL接口实现动态的添加和删除
pglogical.create_node(node_name name, dsn text) 创建节点
参数说明:
* node_name -节点名称,每个数据库只允许创建一个节点
* dsn-连接节点的连接字符串信息,对应发布者节点,这个节点应当是可以从外部访问
pglogical.drop_node(node_name name, ifexists bool) 删除逻辑节点
参数说明:
* node_name -已存在的节点名称
* ifexists -默认为false,如果设置为true,当订阅不存在时不会抛出错误。
pglogical.alter_node_add_interface(node_name name, interface_name name, dsn text) 为节点增加额外的接口创建节点时,也会使用create_node中指定的 dsn 创建该接口,并与节点同名。此接口允许将具有不同连接字符串的备用接口添加到现有节点
参数说明:
* node_name -已经存在的节点名称
* interface_name -将要增加的新接口名称
* dsn -连接新接口节点的连接字符串信息
pglogical.alter_node_drop_interface(node_name name, interface_name name) 移除节点中存在的接口
参数说明:
* node_name -已存在节点的名称
* interface_name -已存在接口的名称
二、订阅管理
pglogical.create_subscription(subscription_name name, provider_dsn text, replication_sets text[], synchronize_structure boolean, synchronize_data boolean, forward_origins text[], apply_delay interval) 创建从当前节点到发布节点的订阅。命令不会阻止,只是启动操作。
参数说明:
* subscription_name - 订阅名称,必须唯一
* provider_dsn -连接到发布者的连接字符串
* replication_sets -要订阅的复制集矩阵,必须是已经存在的,默认配置为"{{default,default_insert_only,ddl_sql}"
* synchronize_structure - 定义是否将结构从发布者同步到订阅者,默认是false
* synchronize_data-定义是否将数据从发布者同步到订阅者,默认是true
* forward_origins - 要转发的源名称数组,当前仅支持的值为空数组,表示不转发任何非源于提供发布节点的更改(这对于节点之间的双向复制很有用),或“{all}”,表示复制所有更改,无论其源是什么,默认值为“{all}”
* apply_delay - 复制延迟时间,默认为0秒
* force_text_transfer -强制发布者使用文本形式复制所有列(文本形式同步较慢,但可用于更改订阅者上复制列的类型),默认为false。
subscription_name会被流复制连接以application_name的方式使用。这意味着这个名称可以在pg_stat_replication的视图中看到。这个名称同样可以被用作synchronous_standby_names,当pglogical被用于同步复制搭建过程时。使用pglogical.wait_for_subscription_sync_complete(sub_name)等待订阅异步开始复制并完成所有需要的结构或数据同步。
pglogical.drop_subscription(subscription_name name, ifexists bool) 中断订阅连接并且从系统目录中移除
参数说明:
* subscription_name - 已存在的订阅名称
* ifexists - 如果设置为true,当订阅不存在时不会抛出错误提醒,默认是false
pglogical.alter_subscription_disable(subscription_name name, immediate bool) 使一个订阅失效并断开它同发布者的连接
参数说明:
* subscription_name -已经存在的订阅名称
* immediate -如果设置为true,订阅会立即停止,否则订阅只会在当前事务结束时停止,默认是false
pglogical.alter_subscription_enable(subscription_name name, immediate bool) 启用失效的订阅
参数说明:
* subscription_name - 已存在的订阅名称
* immediate - 如果设置为true,订阅会立即启动,否则订阅只会在当前事务结束时启动,默认为false
pglogical.alter_subscription_interface(subscription_name name, interface_name name) 切换订阅使用不同的接口连接到发布者节点
参数说明:
* subscription_name - 已存在的订阅名称
* interface_name - 当前发布者节点已存在的接口
pglogical.alter_subscription_synchronize(subscription_name name, truncate bool) 所有复制集中未同步的表进行同步,表会逐张拷贝同步。命令不会阻塞,只是初始化动作。使用pglogical.wait_for_subscription_sync_complete命令来等待同步完成
参数说明:
* subscription_name - 已经存在的订阅名称
* truncate - 如果设置为true,表在进行拷贝前会执行truncate操作,默认为false;
pglogical.alter_subscription_resynchronize_table(subscription_name name, relation regclass) 重新同步一张已经存在的表。这张表可能不存在任何外键约束。警告:这个动作会立马清空表,然后才开始同步,所以这张表开始同步时为空表。同样不会阻塞,使用pglogical.wait_for_table_sync_complete来等待同步完成
参数说明:
* subscription_name -已经存在的订阅名称
* relation - 已经存在的表的名称
pglogical.wait_for_subscription_sync_complete(subscription_name name) 在执行pglogical.create_subscription或者pglogical.alter_subscription_synchronize命令后等待订阅或数据同步完成。
这个函数等待订阅初始化架构/数据同步(如果有),并且直到任何进行中的单表重新同步也完成同步。最好的结果是,在发生任何要求重新同步的复制集变化的发布者上运行pglogical.wait_slot_confirm_lsn(NULL, NULL),然后在订阅者上调用pglogical.wait_for_subscription_sync_complete
pglogical.wait_for_table_sync_complete(subscription_name name, relation regclass)
同pglogical.wait_for_subscription_sync_complete相同,但是只等待订阅的初始同步和已命名的表。其他等待重新同步的表将被忽略。
pglogical.wait_slot_confirm_lsn
SELECT pglogical.wait_slot_confirm_lsn(NULL, NULL)
等待当前节点上的所有复制槽都重放到调用所有发布者时的 xlog 插入位置。当所有复制槽的confirmed_flush_lsn超过pg_current_wal_insert_lsn()时返回。
(可选)可以只等待一个复制槽(第一个参数)。(可选)可以等待传递的任意 LSN 而不是插入 lsn(第二个参数)。两者通常都保留为空。
此功能对于确保所有订阅者都收到发布者上某个点的更改非常有用。
pglogical.show_subscription_status(subscription_name name) 显示订阅的状态和基本信息
参数说明:
* subscription_name - 可以配置已存在的订阅名称,如果未配置名称,函数会显示当前节点上的所有订阅的状态
pglogical.show_subscription_table(subscription_name name, relation regclass) 显示一张表的同步状态
参数说明:
* subscription_name -已存在的订阅的名称
* relation - 已存在的表的名称
pglogical.alter_subscription_add_replication_set(subscription_name name, replication_set name) 将一个复制集添加到订阅中。不同步,仅激活事件的消耗。
参数说明:
* subscription_name - 已存在的订阅名称
* replication_set - 要添加的复制集名称
pglogical.alter_subscription_remove_replication_set(subscription_name name, replication_set name) 从订阅者移除一个复制集
参数说明:
* subscription_name - 已存在的订阅名称
* replication_set - 要移除的复制集的名称
这里同样有一个postgresql.conf参数,pglogical.extra_connection_options,可以设置为分配适用于 pglogical 建立的所有连接的连接选项。这在设置自定义保持连接选项等的时候有用。
pglogical 默认启用 TCP 保持连接,以确保当上游服务器意外消失时可以注意到相关情况。将keepalives = 0 添加到 pglogical.extra_connection_options会禁用它。
三、复制集管理
复制集提供了一种控制数据库中哪些表会被复制以及这些表上的哪些动作会被复制的机制每个复制集可以单独设定INSERTs, UPDATEs, DELETEs 和 TRUNCATEs 是否被复制。每个表可以位于多个复制集中,每个订阅者也可以订阅多个复制集。复制的表和操作的结果集是表所在集合的并集。在将表添加到复制集中之前,不会复制它们。三个已存在的复制集的名称为"default",“default_insert_only” 和 “ddl_sql”. "default"复制集被定义为复制表中所有的改动。“default_insert_only” 只复制insert类动作并且适用于没有主键的表,“ddl_sql” 复制集被定义为复制pglogical.replicate_ddl_command命令中定义的架构变化。下列函数用于管理复制集
pglogical.create_replication_set(set_name name, replicate_insert bool, replicate_update bool, replicate_delete bool, replicate_truncate bool) 这个函数创建新的复制集
参数说明:
* set_name - 复制集名称,必须唯一
* replicate_insert -定义insert动作是否被复制,默认为true
* replicate_update -定义update动作是否被复制,默认为true
* replicate_delete- 定义delete动作是否被复制,默认为true
* replicate_truncate - 定义truncate动作是否被复制,默认为true
pglogical.alter_replication_set(set_name name, replicate_inserts bool, replicate_updates bool, replicate_deletes bool, replicate_truncate bool) 这个函数修改已存在的复制集的参数
参数说明:
* set_name - 已存在的复制集名称
* replicate_insert -定义insert动作是否被复制,默认为true
* replicate_update -定义update动作是否被复制,默认为true
* replicate_delete- 定义delete动作是否被复制,默认为true
* replicate_truncate - 定义truncate动作是否被复制,默认为true
pglogical.drop_replication_set(set_name text) 移除复制集
参数说明:
* set_name - 已存在的复制集的名称
pglogical.replication_set_add_table(set_name name, relation regclass, synchronize_data boolean, columns text[], row_filter text) 为复制集添加一张表
参数说明:
* set_name - 已存在的复制集的名称
* relation- 添加到复制集中的表的名称或OID
* synchronize_data - 如果设置为true,订阅了该复制集的所有订阅者都将同步表的数据,默认为false
* columns - 要复制的列的列表。通常所有的列都应被复制,参数需被设为NULL,此为默认值。
* row_filter - 行过滤表达式,默认为NULL(不过滤),更多信息请看Row Filtering部分
警告:使用有效的行筛选器同步数据时请谨慎。 当设置了有效的row_filter时使用synchronize_data=true是对表的一次性操作。当修改了row_filter后再次执行并不会同步数据到订阅者。订阅者需要调用pglogical.alter_subscription_resynchronize_table() 来达到目的
pglogical.replication_set_add_all_tables(set_name name, schema_names text[], synchronize_data boolean) 复制集中增加指定模式下所有的表。只有已存在的表会被添加,未来创建的表会不被自动添加,对于如何保证未来创建的表添加到正确的复制集中,请看复制集新表自动分配部分
参数说明:
* set_name - 已存在的复制集的名称
* schema_names - 要添加的表所在模式的阵列
* synchronize_data - 如果设置为true,订阅了该复制集的所有订阅者都将同步表的数据,默认为false
pglogical.replication_set_remove_table(set_name name, relation regclass) 从复制集中移除表
参数说明:
* set_name - 已存在的复制集的名称
* relation- 添加到复制集中的表的名称或OID
pglogical.replication_set_add_sequence(set_name name, relation regclass, synchronize_data boolean) 为复制集增加序列
参数说明:
* set_name - 已存在的复制集的名称
* relation- 添加到复制集中的序列的名称或OID
* synchronize_data - 如果设置为true,序列值会立刻同步,默认为false
pglogical.replication_set_add_all_sequences(set_name name, schema_names text[], synchronize_data boolean) 增加指定模式下的所有序列,只有已存在的需求会被添加,所有未来创建的序列不会自动添加
参数说明:
* set_name - 已存在的复制集的名称
* schema_names - 要添加的表所在模式的阵列
* synchronize_data - 如果设置为true,序列值会立刻同步,默认为false
pglogical.replication_set_remove_sequence(set_name name, relation regclass) 从复制集中移除一个序列
参数说明:
* set_name - 已存在的复制集的名称
* relation- 要被移除复制集的序列的名称或OID
你可以使用pglogical.tables视图查询表同复制集的隶属关系
复制集新表自动分配
事件触发器可以被用来设计定义新表复制集的规则举例:
CREATE OR REPLACE FUNCTION pglogical_assign_repset()
RETURNS event_trigger AS $$
DECLARE obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
IF obj.object_type = 'table' THEN
IF obj.schema_name = 'config' THEN
PERFORM pglogical.replication_set_add_table('configuration', obj.objid);
ELSIF NOT obj.in_extension THEN
PERFORM pglogical.replication_set_add_table('default', obj.objid);
END IF;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER pglogical_assign_repset_trg
ON ddl_command_end
WHEN TAG IN ('CREATE TABLE', 'CREATE TABLE AS')
EXECUTE PROCEDURE pglogical_assign_repset();
上面的例子会将config模式下的新表增加到configuration复制集中,其他模式下的新表会被添加到default复制集中.
四、额外的功能
pglogical.replicate_ddl_command(command text, replication_sets text[]) 在本地执行后将指定的命令发送到复制队列,以便在订阅了指定复制集的订阅端执行。
参数说明:
* command - 要执行的DDL语句
* replication_sets -同指令关联的复制集矩阵的名称,默认为{ddl_sql}
pglogical.synchronize_sequence(relation regclass) 将序列状态推送给订阅者。
不同于订阅以及表同步功能,这个函数应当在发布者节点运行,它强制更新跟踪的序列状态,一旦所有订阅者复制了已执行此函数的事务,所有订阅者都将使用该状态(复制集筛选仍然适用)。
参数说明:
* relation - 已存在的系列名称
五、行过滤
pglogical允许在发布端及订阅端进行基于行的过滤。
发布端的行过滤
在发布端,行过滤功能可以通过指定pglogical.replication_set_add_table函数的row_filter参数来完成,row_filter是同具有同检查约束相同限制的普通pg表达式简单的row_filter例子类似于row_filter := ‘id > 0’,该表达式保证只有id列值大于0的行会被复制。允许在row_filter内部使用易失性函数,但必须谨慎写入,因为任何执行写入的表达式都可能会抛出错误并停止复制。还值得注意的是,row_filter在复制会话中运行,因此特定于会话的表达式(如 CURRENT_USER)将具有复制会话的值,而不是执行写入的会话的值。
订阅端的行过滤
在订阅端,行过滤可以使用标准的before 触发器机制来实现。这要求将任何此类的触发器标记为ENABLE REPLICA或者ENABLE ALWAYS,否则这些触发器不会被任何复制进行执行
六、同步复制
支持同步复制,使用同PostgreSQL的物理流复制一样的标准机制。如果synchronous_standby_names中使用了pglogic订阅名称,则synchronous_commit和synchronous_ststandby_names设置将影响commit命令何时向客户端报告成功。有关如何配置这两个变量的更多信息,请参阅PostgreSQL文档。
七、冲突
假如一个节点订阅了多个发布或者订阅节点有本地写,传入的更改可能会发生冲突。这些冲突会根据配置进行自动检测及处理。冲突解决的配置项是通过设置pglogical.conflict_resolution参数完成的。冲突解决日志会根据pglogical.conflict_log_level中设置的日志级别来记录。这个参数的默认值为log,如果设置为低于log_min_messages的水平,数据库日志中不会记录已解决的冲突
八、配置选项
一些pglogical的蚕食配置可以通过修改postgresql.conf文件或者使用alter system set命令来修改
pglogical.conflict_resolution 设置本地数据与传入变更的冲突解决方法。
可能的值如下:
error - 如果检测到冲突则停止复制,需要人为介入解决
apply_remote - 应用同本地数据冲突的远程变更
keep_local - 保存本地数据版本并且忽略来自远端的冲突变化
last_update_wins - 保存拥有最新时间戳的数据版本(可能是本地版本也可能是远程版本)
first_update_wins- 保存拥有最老时间戳的数据版本(可能是本地版本也可能是远程版本)
可用的设置和默认值取决于PostgreSQL的版本和其他设置。PostgreSQL中的默认值为apply_remote.keep_local, last_update_wins 和 first_update_wins三个参数要求PostgreSQL开启track_commit_timestamp参数,因为PostgreSQL9.4版本中没有track_commit_timestamp参数,所有此版本的pglogical.conflict_resolution只能配置为apply_remote或者error在 Postgres-XL中,只支持设置为error。
pglogical.conflict_log_level 当pglogical.conflict_resolution设置为error之外的其他值时设置报告检测到的冲突的日志级别
这项配置的主要用途是控制冲突的记录。可以设置的值同PostgreSQL的log_min_messages的设置相同。默认值是log。
pglogical.batch_inserts 告诉PGLogical在可能的情况下使用批处理插入机制。批处理机制使用同COPY命令相同的PostgreSQL内部批处理插入模式。
批处理插入将提高在一个表中进行多次插入的事务的复制性能。当事务执行了5次以上INSERT时,PGLogical将切换到批处理模式。只有当表上没有INSTEAD OF INSERT和BEFORE INSERT触发器,并且表的列没有默认的易失性表达式时,才能切换到批处理模式。此外,只有当pglogical.conflict_resolution设置为error时,批处理模式才会工作。默认值是true。
pglogical.use_spi 告诉PGLogical使用SPI接口来形成实际的SQL(INSERT、UPDATE、DELETE)语句,以应用传入的更改,而不是使用内部低级接口。
这主要用于Postgres XL和调试目的。PostgreSQL中的默认值是true。只有当pglogical.conflict_resolution设置为error时,才能将其设置为true。在此状态下,不会检测到冲突。在Postgres-XL中,此参数只能设置为true。
pglogical.temp_directory 定义存储架构同步所需的临时文件的系统路径。此路径需要已存在,并且可由运行Postgres的用户写入。
默认值为空,这告诉PGLogical根据环境和操作系统设置使用默认临时目录。
九、局限和限制
需要超级用户
当前,pglogic复制和管理需要超级用户权限。稍后可能会扩展到更细粒度的权限。
未记录日志的表和临时表不会被复制
UNLOGGED和TEMPORARY表不会也无法复制,就像物理流复制一样。
一次一个数据库
若要复制多个数据库,必须为每个数据库设置单独的发布者/订阅者关系。无法一次为 PostgreSQL 安装中的所有数据库配置复制。
需要主键或复制标识
对于缺少主键或其他有效复制标识的表无法复制 UPDATE和DELETE类动作,对于使用索引的表的,索引必须是唯一的、非部分的、不可延迟的,并且仅包含标记为NOT NULL的列。复制无法找到应更新/删除的元组,因为没有唯一标识符。尚不支持REPLICA IDENTITY FULL。
只有一个唯一索引/约束/PK
如果配置了多个上游或下游接受本地写入,则下游复制表上应仅存在一个UNIQUE索引。冲突解决一次只能使用一个索引,因此如果行满足主键但违反了下游端的UNIQUE约束,则冲突行可能会出错。这将停止复制,直到修改下游表以删除冲突。如果下游只从上游而不是其他任何地方获取写入,那么对上游有额外的唯一约束是可以的。规则是下游约束不得比上游约束更具限制性。允许使用部分二级唯一索引,但出于解决冲突的目的,将忽略这些索引。唯一约束必须不能是延迟生效的在下游终端pglogical不支持基于索引的约束被定于为DEFERRABLE。当尝试将更改应用到表时,如果存在这样的索引,会产生报错.
ERROR: pglogical doesn't support index rechecks needed for deferrable indexes
DETAIL: relation "public"."test_relation" has deferrable indexes: "index1", "index2"
DDL
自动的DDL复制是不被支持的。管理 DDL 以使发布者和订阅者数据库保持兼容是用户的责任。pglogic提供了pglogical.replicate_ddl_command功能,允许DDL在发布者和订阅者上以一致的点运行。
不刷新复制队列
不支持冻结主机上的事务,并等待所有挂起的排队事务从插槽中重放。在未来的版本中,将添加对使上游只读的支持。这意味着在应用表结构更改时必须小心。如果存在尚未复制的已提交事务,并且同时更改了发布者和订阅者的表结构,从而导致订阅者表与排队的事务不兼容,则复制将停止。管理员应确保在进行架构更改之前停止对主服务器的写入,或者使用 pglogical.replicate_ddl_command 函数对架构更改进行排队,以便在副本上的一致点重放这些更改。一旦添加了多主机复制支持,那么使用pglogical.replicate_ddl_command就不够了,因为在发布服务器上提交架构更改后,订阅者可能会使用旧结构生成新的xact。用户必须确保在进行架构更改之前,所有节点上的写入都已停止并且所有插槽都已赶上。
外键
不会对复制过程强制执行外键约束 - 即使违反外键,在发布端成功的内容也会应用于订阅者。
TRUNCATE
使用TRUNCATE … CASCADE命令时只有发布端会应用CASCADE选项(正确处理这个问题可能需要在PostgreSQL中添加对外键的ON TRUNCATE CASCADE支持)。不支持TRUNCATE … RESTART IDENTITY。这种标识重起步骤不会复制到副本。
序列
添加到复制集的序列的状态是定期复制的,而不是实时复制的。动态缓冲区用于要复制的值,以便订阅者实际接收序列的未来状态。这最大限度地减少了订阅者对序列last_value概念落后的机会,但并没有完全消除这种可能性。可能需要调用synchronize_sequence以确保所有订阅者在数据库中的“大事件”(如数据加载或在线升级期间)之后都拥有有关给定序列的最新信息。通常建议对多节点系统上的序列使用 bigserial 和 bigint 类型,因为较小的序列可能会快速到达序列空间的末尾。希望在发布者和订阅者上具有独立序列的用户可以避免向复制集添加序列,并创建步长间隔等于或大于节点数的序列。然后在每个节点上设置不同的偏移量。对 CREATE SEQUENCE 或 ALTER SEQUENCE 使用 INCREMENT BY 选项,并使用 setval(…) 设置起点。
触发器
应用进程和初始COPY进程都在session_replication_role设置为replica的情况下运行,这意味着将触发ENABLE REPLICA 和ENABLE ALWAYS触发器。
PostgreSQL版本区别
PGlogical可以跨PostgreSQL大版本进行复制。尽管如此,长期跨版本复制不被视为设计目标,尽管它通常可能有效。 跨版本复制时,更改在发布端有效但在订阅端无效的问题更有可能出现。从旧版本复制到较新版本更安全,因为PostgreSQL保持了稳定的向后兼容性,但只有有限的向前兼容性。仅当在同一版本的 PostgreSQL 之间复制或从较低版本复制到较高版本时,才支持初始架构同步。在不同小版本中 复制并不会导致什么不同。
大对象
PostgreSQL的逻辑解析功能不支持对象的变更解析,所有pglogical不支持复制大对象
Postgres-XL
支持Postgres-XL的最低版本是9.5r1.5Postgres-XL只能作为订阅者(不能是发布者)。对于具有许多小事务的工作负载,由于写入延迟增加,复制性能可能会受到影响。另一方面,大型插入(或批量复制)事务经过了大量优化,可以在Postgres XL中快速工作。
此外,任何DDL限制都适用,因此在使用replicate_DDL_command()时需要格外小心。
Postgres XL更改了pglogical.conflict_resolution和pglogical.use_spi配置选项的默认值和可用设置。