pglogical 2 扩展为 PostgreSQL 提供基于发布/订阅模型的逻辑流复制。它基于作为 BDR 项目一部分开发的技术。
虽然 pglogical 仍在积极维护,但 EnterpriseDB 将新功能开发的重点放在 pglogical 的一个衍生项目Postgres Distributed上。Postgres Distributed 引入了许多新功能,如 DDL 复制、写入主节点、并行应用等。
我们使用以下术语来描述节点间的数据流,这些术语特意沿用了早期 Slony 技术中的用法:
- 节点 - PostgreSQL 数据库实例
- 提供者和订阅者 - 节点扮演的角色
- 复制集 - 表的集合
pglogical 利用了最新的内核功能,因此有以下版本限制:
- 提供者和订阅者节点必须运行 PostgreSQL 9.4 或更高版本
- PostgreSQL 9.5 或更高版本是复制源点过滤和冲突检测所必需的
- 此外,订阅者可以是 Postgres-XL 9.5 或更高版本
支持的用例包括:
- 主要版本之间的升级(在满足上述限制条件下)
- 全数据库复制
- 使用复制集选择性复制表集合
- 在发布者或订阅者端选择性复制表行
- 在发布者端选择性复制表列
- 从多个上游服务器收集/合并数据
架构细节:
- pglogical 在单个数据库级别工作,而非像物理流复制那样在整个服务器级别工作
- 一个提供者可以向多个订阅者提供数据,而不会产生额外的磁盘写入开销
- 一个订阅者可以合并来自多个源的更改,并检测更改之间的冲突,具有自动且可配置的冲突解决能力(满足多主复制所需的某些但非所有方面)
- 级联复制以更改集转发的形式实现。
要求
要使用 pglogical,提供者和订阅者必须运行 PostgreSQL 9.4 或更新版本。
pglogical 扩展必须在提供者和订阅者上都安装。您必须在两者上都执行 CREATE EXTENSION pglogical。
提供者和订阅者上的表必须具有相同的名称并位于相同的模式中。未来的版本可能会添加映射功能。
提供者和订阅者上的表必须具有相同的列,每列具有相同的数据类型。CHECK 约束、NOT NULL 约束等在订阅者上必须与提供者相同或更弱。
表必须具有相同的主键。不建议添加除主键之外的额外 UNIQUE 约束。
"限制和约束"部分涵盖了一些额外要求。
安装
软件包
pglogical 可通过 yum 以 RPM 包形式用于 Fedora、CentOS 和 RHEL,通过 apt 以 DEB 包形式用于 Debian 和 Ubuntu,或作为源代码从此处获取。请参阅下文关于从源代码安装的说明。
使用 YUM 安装 pglogical
以下说明适用于 Red Hat 系列操作系统。先决条件
这些 RPM 包都需要来自 http://yum.postgresql.org/ 的 PGDG PostgreSQL 版本。您不能将其与 Fedora 和 RHEL 中包含的 stock PostgreSQL 版本一起使用。如果您还没有安装 PostgreSQL:
- 从 http://yum.postgresql.org/repopackages.php 安装相应的 PGDG 仓库 rpm 包
- 安装 PostgreSQL
- PostgreSQL 9.5:
yum install postgresql95-server postgresql95-contrib - PostgreSQL 9.6:
yum install postgresql96-server postgresql96-contrib - PostgreSQL 10:
yum install postgresql10-server postgresql10-contrib - PostgreSQL 11:
yum install postgresql11-server postgresql11-contrib - PostgreSQL 12:
yum install postgresql12-server postgresql12-contrib - PostgreSQL 13:
yum install postgresql13-server postgresql13-contrib - PostgreSQL 14:
yum install postgresql14-server postgresql14-contrib - PostgreSQL 15:
yum install postgresql15-server postgresql15-contrib - PostgreSQL 16:
yum install postgresql16-server postgresql16-contrib - PostgreSQL 17:
yum install postgresql17-server postgresql17-contrib - PostgreSQL 18:
yum install postgresql18-server postgresql18-contrib
- PostgreSQL 9.5:
安装
您可以继续为您的 PostgreSQL 版本安装 pglogical:
- PostgreSQL 9.5:
yum install pglogical_95 - PostgreSQL 9.6:
yum install pglogical_96 - PostgreSQL 10:
yum install pglogical_10 - PostgreSQL 11:
yum install pglogical_11 - PostgreSQL 12:
yum install pglogical_12 - PostgreSQL 13:
yum install pglogical_13 - PostgreSQL 14:
yum install pglogical_14 - PostgreSQL 15:
yum install pglogical_15 - PostgreSQL 16:
yum install pglogical_16 - PostgreSQL 17:
yum install pglogical_17 - PostgreSQL 18:
yum install pglogical_18
使用 APT 安装 pglogical
以下说明适用于 Debian 和所有基于 Debian 的 Linux 发行版。
先决条件
- 添加 https://apt.postgresql.org/ 仓库。请参阅该站点的说明。
- 安装 PostgreSQL
- PostgreSQL 9.5:
sudo apt-get install postgresql-9.5 - PostgreSQL 9.6:
sudo apt-get install postgresql-9.6 - PostgreSQL 10:
sudo apt-get install postgresql-10 - PostgreSQL 11:
sudo apt-get install postgresql-11 - PostgreSQL 12:
sudo apt-get install postgresql-12 - PostgreSQL 13:
sudo apt-get install postgresql-13 - PostgreSQL 14:
sudo apt-get install postgresql-14 - PostgreSQL 15:
sudo apt-get install postgresql-15 - PostgreSQL 16:
sudo apt-get install postgresql-16 - PostgreSQL 17:
sudo apt-get install postgresql-17 - PostgreSQL 18:
sudo apt-get install postgresql-18
- PostgreSQL 9.5:
安装
一旦先决条件完成,安装 pglogical 只需为您的 PostgreSQL 版本执行以下命令:
- PostgreSQL 9.5:
sudo apt-get install postgresql-9.5-pglogical - PostgreSQL 9.6:
sudo apt-get install postgresql-9.6-pglogical - PostgreSQL 10:
sudo apt-get install postgresql-10-pglogical - PostgreSQL 11:
sudo apt-get install postgresql-11-pglogical - PostgreSQL 12:
sudo apt-get install postgresql-12-pglogical - PostgreSQL 13:
sudo apt-get install postgresql-13-pglogical - PostgreSQL 14:
sudo apt-get install postgresql-14-pglogical - PostgreSQL 15:
sudo apt-get install postgresql-15-pglogical - PostgreSQL 16:
sudo apt-get install postgresql-16-pglogical - PostgreSQL 17:
sudo apt-get install postgresql-17-pglogical - PostgreSQL 18:
sudo apt-get install postgresql-18-pglogical
从源代码安装
源代码安装与使用 PGXS 构建的任何其他 PostgreSQL 扩展相同。
确保包含来自 PostgreSQL 版本的 pg_config 的目录在您的 PATH 环境变量中。如果您没有 pg_config,您可能需要从包管理器中为您的 PostgreSQL 版本安装 -dev 或 -devel 包。
然后运行 make 进行编译,运行 make install 进行安装。安装步骤可能需要使用 sudo。
例如,对于典型的 Fedora 或 RHEL 9 安装,假设您使用 yum.postgresql.org 的 PostgreSQL 包:
sudo dnf install postgresql17-devel
PATH=/usr/pgsql-17/bin:$PATH make clean all
sudo PATH=/usr/pgsql-17/bin:$PATH make install
使用
本节描述 pglogical 复制扩展的基本用法。
快速设置
首先,PostgreSQL 服务器必须正确配置以支持逻辑解码:
wal_level = 'logical'
max_worker_processes = 10 # 提供者节点上每个数据库需要一个
# 订阅者节点上每个节点需要一个
max_replication_slots = 10 # 提供者节点上每个节点需要一个
max_wal_senders = 10 # 提供者节点上每个节点需要一个
shared_preload_libraries = 'pglogical'
如果您使用 PostgreSQL 9.5+(这在 9.4 上不起作用)并希望使用最后/首先更新获胜来处理冲突解决,您可以将此附加选项添加到 postgresql.conf:
track_commit_timestamp = on # 为最后/首先更新获胜冲突解决所需
# 此属性在 PostgreSQL 9.5+ 中可用
pg_hba.conf 必须允许来自 localhost 的逻辑复制连接。直到 PostgreSQL 9.6,逻辑复制连接都是使用 pg_hba.conf 中的 replication 关键字来管理的。在 PostgreSQL 10 及更高版本中,pg_hba.conf 将逻辑复制连接视为对提供者数据库的常规连接。
接下来,必须在所有节点上安装 pglogical 扩展:
CREATE EXTENSION pglogical;
如果使用 PostgreSQL 9.4,则还必须在该节点上安装 pglogical_origin 扩展:
CREATE EXTENSION pglogical_origin;
现在创建提供者节点:
SELECT pglogical.create_node(
node_name := 'provider1',
dsn := 'host=providerhost port=5432 dbname=db'
);
将 public 模式中的所有表添加到默认复制集。
SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);
您也可以选择创建额外的复制集并将表添加到其中。
通常最好在订阅之前创建复制集,以便在初始复制设置期间,所有表在单个初始事务中同步。但是,大型数据库的用户可能希望增量创建它们以便更好地控制。
一旦提供者节点设置完成,订阅者就可以订阅它。首先必须创建订阅者节点:
SELECT pglogical.create_node(
node_name := 'subscriber1',
dsn := 'host=thishost port=5432 dbname=db'
);
最后,在订阅者节点上,您可以创建订阅,这将在后台启动同步和复制进程:
SELECT pglogical.create_subscription(
subscription_name := 'subscription1',
provider_dsn := 'host=providerhost port=5432 dbname=db'
);
SELECT pglogical.wait_for_subscription_sync_complete('subscription1');
使用基础备份创建订阅者节点
除了 SQL 级别的节点和订阅创建,pglogical 还支持通过使用 pg_basebackup 克隆提供者并将其作为 pglogical 订阅者启动来创建订阅者。这是通过 pglogical_create_subscriber 工具完成的;请参阅 --help 输出。
与 pglogical.create_subscription 的数据同步选项不同,此克隆会忽略复制集并复制所有数据库上的所有表。但是,它通常要快得多,尤其是在高带宽链路上。
节点管理
可以使用 SQL 接口动态添加和删除节点。
pglogical.create_node(node_name name, dsn text) 创建一个节点。
参数:
node_name- 新节点的名称,每个数据库只允许一个节点dsn- 连接到节点的连接字符串,对于应该是提供者的节点,这应该可以从外部访问
pglogical.drop_node(node_name name, ifexists bool) 删除 pglogical 节点。
参数:
node_name- 现有节点的名称ifexists- 如果为 true,当订阅不存在时不抛出错误,默认为 false
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- 指定是否将结构从提供者同步到订阅者,默认为 falsesynchronize_data- 指定是否将数据从提供者同步到订阅者,默认为 trueforward_origins- 要转发的源名称数组,当前唯一支持的值为空数组(表示不转发任何非源自提供者节点的更改,这对于节点间的双向复制很有用),或"{all}"(表示复制所有更改,无论其来源如何),默认为"{all}"apply_delay- 延迟复制多少时间,默认为 0 秒force_text_transfer- 强制提供者使用文本表示复制所有列(速度较慢,但可用于更改订阅者上复制列的类型),默认为 false
subscription_name 被复制连接用作 application_name。这意味着它可以在 pg_stat_replication 监控视图中看到。当 pglogical 用作同步复制设置的一部分时,它也可以在 synchronous_standby_names 中使用。
使用 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,表将在复制前被截断,默认为 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 之后完成同步。
此函数等待订阅的初始模式/数据同步(如果有)完成,并等待任何待单独重新同步的表也完成同步。
为了获得最佳效果,在任何请求重新同步的复制集更改之后,在提供者上运行 SELECT 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 进行的所有连接的连接选项。这可以是设置自定义 keepalive 选项等的有用位置。
pglogical 默认启用 TCP keepalives 以确保在上游服务器意外消失时能注意到。要禁用它们,请在 pglogical.extra_connection_options 中添加 keepalives = 0。
复制集
复制集提供了一种机制来控制数据库中的哪些表将被复制以及对那些表执行的哪些操作将被复制。
每个复制的集合可以单独指定是否复制对集合的 INSERT、UPDATE、DELETE 和 TRUNCATE 操作。每个表可以位于多个复制集中,每个订阅者也可以订阅多个复制集。复制的最终表集和操作是表所在集合的并集。表在添加到复制集之前不会被复制。
存在三个预定义的复制集,名为 "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,默认为 truereplicate_update- 指定是否复制 UPDATE,默认为 truereplicate_delete- 指定是否复制 DELETE,默认为 truereplicate_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,默认为 truereplicate_update- 指定是否复制 UPDATE,默认为 truereplicate_delete- 指定是否复制 DELETE,默认为 truereplicate_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- 要添加到集合中的表的名称或 OIDsynchronize_data- 如果为 true,表数据将在所有订阅了给定复制集的订阅者上同步,默认为 falsecolumns- 要复制的列列表。通常当所有列都应复制时,这将设置为 NULL,这是默认值row_filter- 行过滤表达式,默认为 NULL(无过滤),更多信息请参阅行过滤。警告:在同步带有有效行过滤器的数据时要小心。使用synchronize_data=true和有效的row_filter就像对表的一次性操作。再次使用修改后的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- 要添加到集合中的序列的名称或 OIDsynchronize_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 {mathJaxContainer[0]} 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 中,而所有其他不是由扩展创建的新表将进入默认复制集。
附加功能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 是普通的 PostgreSQL 表达式,其允许内容与 CHECK 约束具有相同的限制。
简单的 row_filter 可能类似于 row_filter := 'id > 0',这将确保只复制 id 列值大于零的行。
允许在 row_filter 中使用易变函数,但必须注意写入操作,因为任何进行写入的表达式都会抛出错误并停止复制。
还值得注意的是,row_filter 在复制会话内部运行,因此诸如 CURRENT_USER 之类的会话特定表达式将具有复制会话的值,而不是执行写入的会话的值。
订阅者端行过滤
在订阅者端,可以使用标准的 BEFORE TRIGGER 机制实现基于行的过滤。
需要将任何此类触发器标记为 ENABLE REPLICA 或 ENABLE ALWAYS,否则它们将不会由复制进程执行。
同步复制
使用 PostgreSQL 为物理复制提供的相同标准机制支持同步复制。
如果在 synchronous_standby_names 中使用了 pglogical 订阅名称,则 synchronous_commit 和 synchronous_standby_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 设置。由于 track_commit_timestamp 在 PostgreSQL 9.4 中不可用,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 在可能的情况下使用批量插入机制。批量机制使用 PostgreSQL 内部的批量插入模式,COPY 命令也使用此模式。
批量插入将提高对一个表进行多次插入的事务的复制性能。当事务对一个表进行了超过 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 中默认为 false。
只有当 pglogical.conflict_resolution 设置为 error 时,才能将其设置为 true。在这种状态下,不会检测冲突。
在 Postgres-XL 中,默认且唯一允许的设置是 true。
pglogical.temp_directory 定义用于存放模式同步所需的临时文件的系统路径。该路径必须存在且对运行 Postgres 的用户可写。
默认为空,这告诉 PGLogical 使用基于环境和操作系统设置的默认临时目录。
限制和约束
需要超级用户权限
当前 pglogical 复制和管理需要超级用户权限。以后可能会扩展到更细粒度的权限。
不复制 UNLOGGED 和 TEMPORARY 表
UNLOGGED 和 TEMPORARY 表将不会也不能被复制,就像物理流复制一样。
一次一个数据库
要复制多个数据库,您必须为每个数据库设置单独的提供者/订阅者关系。无法一次为 PostgreSQL 安装中的所有数据库配置复制。
需要主键或副本标识
对于缺乏主键或其他有效副本标识(例如使用索引,该索引必须是唯一的、非部分的、不可延迟的,并且仅包含标记为 NOT NULL 的列)的表,无法复制 UPDATE 和 DELETE。复制无法找到应该更新/删除的元组,因为没有唯一标识符。尚不支持 REPLICA IDENTITY FULL。
只有一个唯一索引/约束/主键
如果配置了多个上游,或者下游接受本地写入,则下游复制表上应只存在一个 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 以使提供者和订阅者数据库保持兼容是用户的责任。
pglogical 提供了 pglogical.replicate_ddl_command 函数,允许在提供者和订阅者上的一致点运行 DDL。
如果您需要 DDL 复制,可以查看 EnterpriseDB 基于 pglogical 构建的 Postgres Distributed 产品。
无复制队列刷新
不支持在主节点上冻结事务并等待所有挂起的排队事务从槽中重放。未来版本将添加支持使上游对此只读。
这意味着在应用表结构更改时必须小心。如果有已提交但尚未复制的事务,并且提供者和订阅者的表结构同时更改,使得订阅者表与排队事务不兼容,复制将停止。
管理员应确保在进行模式更改之前停止对主节点的写入,或者使用 pglogical.replicate_ddl_command 函数对模式更改进行排队,以便在副本上的一致点重放。
一旦添加了多主复制支持,仅使用 pglogical.replicate_ddl_command 将不够,因为在模式更改在发布者上提交后,订阅者可能会使用旧结构生成新事务。用户将必须确保在进行模式更改之前停止所有节点上的写入,并且所有槽都已跟上。
外键
复制过程不强制执行外键约束 - 在提供者端成功的操作将应用于订阅者,即使会违反外键。
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 进程都使用设置为 replica 的 session_replication_role 运行,这意味着将触发 ENABLE REPLICA 和 ENABLE ALWAYS 触发器。
PostgreSQL 版本差异
PGLogical 可以在不同的 PostgreSQL 主要版本之间进行复制。尽管如此,长期的跨版本复制并非设计目标,尽管它可能经常有效。当跨版本复制时,更可能出现更改在提供者上有效但在订阅者上无效的问题。
从旧版本复制到新版本更安全,因为 PostgreSQL 保持可靠的向后兼容性,但仅具有有限的前向兼容性。初始模式同步仅在相同版本的 PostgreSQL 之间或从低版本到高版本复制时才受支持。
在不同次要版本之间复制完全没有区别。
数据库编码差异
PGLogical 不支持在不同编码的数据库之间进行复制。我们建议在所有复制数据库中使用 UTF-8 编码。
大对象
PostgreSQL 的逻辑解码工具不支持解码对大对象的更改,因此 pglogical 无法复制大对象。
Postgres-XL
Postgres-XL 的最低受支持版本是 9.5r1.5。
Postgres-XL 仅支持作为订阅者(不能是提供者)。对于具有许多小事务的工作负载,由于写入延迟增加,复制性能可能会受到影响。另一方面,大型插入(或批量复制)事务经过大量优化,可以与 Postgres-XL 非常快速地协同工作。
此外,任何 DDL 限制都适用,因此在使用 replicate_ddl_command() 时需要格外小心。
Postgres-XL 更改了 pglogical.conflict_resolution 和 pglogical.use_spi 配置选项的默认值和可用设置。