文档首页/ 云数据库 RDS/ 最佳实践/ RDS for PostgreSQL/ RDS for PostgreSQL发布与订阅
更新时间:2024-09-05 GMT+08:00

RDS for PostgreSQL发布与订阅

逻辑定义

发布可以被定义在任何物理复制的主服务器上。定义有发布的节点被称为发布者。发布是从一个表或者一组表生成的改变的集合,也可以被描述为更改集合或者复制集合。每个发布都只存在于一个数据库中。

订阅是逻辑复制的下游端。订阅被定义在其中的节点被称为订阅者。一个订阅会定义到另一个数据库的连接以及它想要订阅的发布集合(一个或者多个)。逻辑订阅者的行为与一个普通的PostgreSQL实例(主库)无异,逻辑订阅者也可以创建自己的发布,拥有自己的订阅者。

使用权限

  • 创建发布时,发布者必须有流复制权限。即replication权限。
  • 创建发布时,使用all tables发布所有表时,需确保发布者是提权起始及之后版本的root用户。
  • 创建/删除订阅时,需确保订阅者是提权起始及之后版本的root用户。
  • 创建发布/订阅时,需确保发布端和订阅端实例在同一VPC下。

各个版本root用户提权情况参见root用户权限说明

发布使用限制

  • 发布目前只能包含表(即:索引,序列号,物化视图这些不会被发布),每个表可以添加到多个发布中。
  • 一个publication允许有多个订阅者。
  • 允许使用all tables发布所有表。
  • 在同一个数据库中,可以创建多个publication,但是不能重名。已创建的publication可以通过查询pg_publication获取。
  • 发布可以筛选所需的变更类型:包括insert、update、delete 和truncate的任意组合,类似触发器事件,默认所有变更都会被发布。

    例如:发布表t1的updatedelete操作。

    CREATE PUBLICATION update_delete_only FOR TABLE t1
        WITH (publish = 'update, delete') ;
  • 复制标识:当发布了表的update, delete时,表必须设置复制标识(Replica Identity),如果设置了nothing,则执行update, delete时会报错。

    表上的复制标识可以通过查阅pg_class.relreplident获取。

    这是一个字符类型的“枚举”,标识用于组装 “复制标识” 的列:d = default ,f = 所有的列,i 使用特定的索引,n 没有复制标识。

    表上是否具有可用作复制标识的索引约束,可以通过以下查询获取:

    SELECT quote_ident(nspname) || '.' || quote_ident(relname) AS name, con.ri AS keys,
           CASE relreplident WHEN 'd' THEN 'default' WHEN 'n' THEN 'nothing' WHEN 'f' THEN 'full' WHEN 'i' THEN 'index' END AS replica_identity
    FROM pg_class c JOIN pg_namespace n ON c.relnamespace = n.oid, LATERAL (SELECT array_agg(contype) AS ri FROM pg_constraint WHERE conrelid = c.oid) con
    WHERE relkind = 'r' AND nspname NOT IN ('pg_catalog', 'information_schema', 'monitor', 'repack', 'pg_toast')
    ORDER BY 2,3;
  • 复制标识配置

    表到复制标识可以通过ALTER TABLE进行修改。

    ALTER TABLE table_name REPLICA IDENTITY 
    { DEFAULT | USING INDEX index_name | FULL | NOTHING };
    -- 具体有四种形式
    ALTER TABLE t_normal REPLICA IDENTITY DEFAULT;                    -- 使用主键,如果没有主键则为FULL
    ALTER TABLE t_normal REPLICA IDENTITY FULL;                       -- 使用整行作为标识
    ALTER TABLE t_normal REPLICA IDENTITY USING INDEX t_normal_v_key; -- 使用唯一索引
    ALTER TABLE t_normal REPLICA IDENTITY NOTHING;                    -- 不设置复制标识
  • 复制标识在实际使用中的注意事项
    • 表上有主键,使用默认的default复制标识。
    • 表上没有主键,但是有非空唯一索引,显式配置index复制标识。
    • 表上既没有主键,也没有非空唯一索引,显式配置full复制标识(运行效率非常低,仅能作为兜底方案)。
    • 其他所有情况,都无法正常完成逻辑复制功能。输出的信息不足,可能会报错。
    • 特别需要注意:如果nothing复制标识的表纳入到逻辑复制中,对其进行删改会导致发布端报错。

订阅使用限制

  • 为了确保使用Failover Slot,必须在发布端手工创建逻辑复制槽(Failover Slot),并通过create_slot = false关联已有复制槽,如下:

    CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.0.1 port=5432 user=user1 dbname=db1' PUBLICATION pub_name with (create_slot = false,slot_name = FailoverSlot_name);

  • 逻辑复制不会复制DDL变更,因此发布集中的表必须已经存在于订阅端上。
  • 同一个数据库中,可以创建多个subscription,这些subscription可以来自一个或多个发布者。
  • 订阅者的同一张表,不能接受来自同一个源的多个发布。
  • 在创建subscription或者alter subscription时,可以使用enable来启用该订阅,或者使用disable暂停该订阅。
  • 如果要完全删除订阅,使用DROP SUBSCRIPTION,注意,删除订阅后,本地的表不会被删除,数据也不会清除,仅仅是不在接收该订阅的上游信息。

    如果订阅与复制槽相关联,就不能在事务块内部执行DROP SUBSCRIPTION。可以使用ALTER SUBSCRIPTION取消关联复制槽。

    删除订阅可参考以下步骤:

    1. 在订阅端查询订阅关联的的复制槽。

      select subname,subconninfo,subslotname from pg_subscription where subname = 'sub2';

      • subname为订阅者名称。
      • subconninfo为连接远程主机信息。
      • subslotname 为远程主机复制槽名称。
    2. 在订阅端执行ALTER SUBSCRIPTION取消关联复制槽并删除。

      ALTER SUBSCRIPTION subname SET (slot_name = NONE);

      DROP SUBSCRIPTION subname;

    3. 在发布端删除关联的复制槽。

      select pg_drop_replication_slot(' slot_name);

语法参考

  • 发布

    CREATE PUBLICATION用于创建发布,DROP PUBLICATION用于移除发布,ALTER PUBLICATION用于修改发布。

    发布创建之后,可以通过ALTER PUBLICATION动态地向发布中添加或移除表,这些操作都是事务性的。

  • 订阅

    CREATE SUBSCRIPTION用于创建订阅,DROP SUBSCRIPTION用于移除订阅,ALTER SUBSCRIPTION用于修改订阅。

    订阅创建之后,可以通过ALTER SUBSCRIPTION随时暂停恢复订阅。移除并重建订阅会导致同步信息丢失,这意味着相关数据需要重新进行同步。

具体使用说明请参考以下官方文档,以PostgreSQL 13版本为例: