全部产品
Search
文档中心

云数据库 RDS:只读实例本地逻辑复制槽

更新时间:Jun 18, 2026

RDS PostgreSQL支持在只读实例上创建本地逻辑复制槽,下游订阅者可以直接连接只读实例消费变更,从而将逻辑复制的消费流量从主实例转移到只读实例,减轻主实例的负载。

前提条件

PostgreSQL 16或以上版本,且内核小版本不低于20260530。如提示不支持,请升级内核小版本,具体操作,请参见升级内核小版本

背景信息

PostgreSQL 原生逻辑复制槽(Logical Replication Slot)在主实例上创建,下游订阅者必须连接主实例消费变更。RDS PostgreSQL 支持在只读实例上创建本地逻辑复制槽,使下游订阅者可以直接连接只读实例消费变更,以减轻主实例负载。逻辑复制槽的更多信息,请参见PostgreSQL官方文档

注意事项

  • 在只读实例上创建的逻辑复制槽为本地 slot,不参与主备故障转移。只读实例重搭(重建)后,这些 slot 将丢失,需要在重搭后重新创建。

  • 建议仅在非高可用的只读实例上使用此方式。如果只读实例承担高可用读流量,slot 丢失可能导致下游订阅中断,需评估业务影响。

使用示例

以下示例假设已有主实例(RW)和只读实例(RO),且只读实例通过流复制与主实例保持数据同步。本文介绍以下三种典型使用方式:

  • 基本用法:在只读实例上手动创建并消费slot(使用test_decoding插件),适用于自定义解码逻辑场景。

  • 通过Subscription订阅只读实例(自动创建slot):最典型的使用场景,由CREATE SUBSCRIPTION自动在只读实例上创建slot。

  • 通过Subscription订阅只读实例(手动预创建slot):进阶用法,先手动创建slot再建立订阅,确保不丢失建立期间的变更。

基本用法:手动创建并消费slot

本示例演示如何在只读实例上手动创建逻辑复制槽,并通过test_decoding插件消费主实例的数据变更。

  1. 在只读实例上创建本地逻辑复制槽。

    -- [RO] 创建本地logical slot
    SELECT pg_create_logical_replication_slot('my_slot', 'test_decoding');
  2. 确认slot创建成功。

    -- [RO] 确认slot创建成功
    SELECT slot_name, plugin FROM pg_replication_slots WHERE slot_name = 'my_slot';

    查询结果:

     slot_name |    plugin     
    -----------+---------------
     my_slot   | test_decoding 
    (1 row)
  3. 在主实例上写入数据。

    -- [RW] 主库写入数据
    INSERT INTO my_table VALUES (1), (2), (3);
  4. 等待WAL回放到只读实例。

    在主实例上查询当前WAL位置:

    -- [RW] 获取主库当前WAL位置
    SELECT pg_current_wal_lsn();

    在只读实例上查询回放进度,直到回放位置不小于主实例的WAL位置:

    -- [RO] 查看只读实例回放进度
    SELECT pg_last_wal_replay_lsn();
    说明

    PostgreSQL 15及以上版本,也可以使用pg_wal_replay_wait(target_lsn)函数主动等待回放至指定LSN,无需轮询。

  5. 在只读实例上通过slot消费变更。

    -- [RO] 通过slot消费变更
    SELECT * FROM pg_logical_slot_get_changes('my_slot', NULL, NULL);

    查询结果:

        lsn    | xid |                  data
    -----------+-----+----------------------------------------
     0/XXXXXXX | 123 | table public.my_table: INSERT: ...
    (3 rows)
  6. 不再需要时,删除slot。

    -- [RO] 删除slot
    SELECT pg_drop_replication_slot('my_slot');

通过Subscription订阅只读实例(自动创建slot)

这是最典型的使用场景:下游订阅实例(Subscriber)直接连接只读实例,由CREATE SUBSCRIPTION自动在只读实例上创建slot。

  1. 在主实例上创建表和发布。

    -- [RW] 主库上创建表和publication
    CREATE TABLE tab_rep (id int PRIMARY KEY, data text);
    CREATE PUBLICATION my_pub FOR TABLE tab_rep;
  2. 等待WAL回放到只读实例,确保publication在只读实例上可见。等待方法请参见"基本用法"中的步骤4。

  3. 在下游订阅实例上创建相同的表结构。

    -- [Subscriber] 下游实例创建表结构
    CREATE TABLE tab_rep (id int PRIMARY KEY, data text);
  4. 在下游订阅实例上创建订阅,连接只读实例。

    -- [Subscriber] 创建subscription,连接只读实例
    -- subscription会自动在只读实例上创建名为'my_sub'的slot
    CREATE SUBSCRIPTION my_sub
        CONNECTION 'host=<RO_HOST> port=<RO_PORT> dbname=postgres'
        PUBLICATION my_pub
        WITH (copy_data = off);
    说明

    此操作会在只读实例上自动创建一个逻辑复制槽。该slot为只读实例本地slot,不参与故障转移,只读实例重搭后会丢失。

  5. 在主实例上写入数据并验证同步。

    -- [RW] 主库写入数据
    INSERT INTO tab_rep VALUES (1, 'hello'), (2, 'world');

    数据流向:RW →(流复制/WAL)→ RO →(逻辑复制)→ Subscriber。

    -- [Subscriber] 验证数据已同步
    SELECT * FROM tab_rep;

    查询结果:

     id | data
    ----+-------
      1 | hello
      2 | world
    (2 rows)
  6. 不再需要时,在下游实例上删除订阅(会自动删除只读实例上的slot)。

    -- [Subscriber] 删除subscription,自动清理只读实例上的slot
    DROP SUBSCRIPTION my_sub;

通过Subscription订阅只读实例(手动预创建slot)

如果需要先创建slot再建立订阅(例如确保不丢失建立期间的变更),可以手动预创建slot。

  1. 在只读实例上手动创建slot。

    -- [RO] 先在只读实例上手动创建slot
    SELECT pg_create_logical_replication_slot('my_sub', 'pgoutput');
  2. 在下游订阅实例上创建订阅,使用已有的slot。

    -- [Subscriber] 创建subscription,使用已有的slot,不再自动创建
    CREATE SUBSCRIPTION my_sub
        CONNECTION 'host=<RO_HOST> port=<RO_PORT> dbname=postgres'
        PUBLICATION my_pub
        WITH (copy_data = off, create_slot = false);
    说明

    通过指定create_slot = false,CREATE SUBSCRIPTION将直接使用只读实例上已有的slot,不会重复创建。后续使用方式与"通过Subscription订阅只读实例(自动创建slot)"相同。