使用 Postgres 逻辑复制槽时如何限制 WAL 大小?

How to limit WAL size when using Postgres Logical Replication Slot?

我正在创建复制槽并通过 JDBC 驱动程序将更改从 AWS Postgres RDS 流式传输到 java 进程。

我的复制槽创建代码如下所示。

final ReplicationSlotInfo replicationSlotInfo = pgConnection.getReplicationAPI()
                    .createReplicationSlot()
                    .logical()
                    .withSlotName(replicationSlotName)
                    .withOutputPlugin("wal2json")
                    .make();

我使用以下代码获取复制流。

pgConnection.getReplicationAPI()
                .replicationStream()
                .logical()
                .withSlotName(replicationSlotName)
                .withSlotOption("include-xids", true)
                .withSlotOption("include-timestamp", true)
                .withSlotOption("pretty-print", false)
                .withSlotOption("add-tables", "public.users")
                .withStatusInterval(10, TimeUnit.SECONDS)
                .start()

当复制器 java 进程不是 运行 时,WAL 大小会增加。这是我用来查找复制延迟的查询。

SELECT
    slot_name,
    pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)) AS replicationSlotLag,
    active
FROM
    pg_replication_slots;

输出:

slot_name   replicationslotlag  active
data_stream_slot    100 GB  f

此复制滞后会增加到 RDS 磁盘之外,从而关闭 RDS。

我以为 wal_keep_segments 会解决这个问题,它被设置为 32。但它没有用。 是否有任何其他 属性 我必须设置以避免这种情况,即使 Java 复制过程不是 运行.

wal_keep_segments与逻辑解码无关

使用逻辑解码,你总是必须使用一个逻辑复制槽,它是一种数据结构,它在事务日志(WAL)中标记一个位置,以便服务器从不丢弃逻辑解码可能仍然需要的旧 WAL 段。

这就是如果您不使用这些更改,您的 WAL 目录会增长的原因。

wal_keep_segments 指定要保留的 最小 数量的旧 WAL 段。它用于流复制、pg_receivewalpg_rewind.

等目的

wal_keep_segments 指定 PostgreSQL 应在 pg_xlog 目录中保留的 最小 段数。 PostgreSQL 不删除段可能有几个原因:

  1. 在比 WAL 文件更早的 WAL 位置有一个复制槽,你可以用这个查询来检查它:
SELECT slot_name,
       lpad((pg_control_checkpoint()).timeline_id::text, 8, '0') ||
       lpad(split_part(restart_lsn::text, '/', 1), 8, '0') ||
       lpad(substr(split_part(restart_lsn::text, '/', 2), 1, 2), 8, '0')
       AS wal_file
FROM pg_replication_slots;
  1. WAL 归档已启用,但 archive_command 失败。请在这种情况下检查 PostgreSQL 日志。

  2. 好久没有关卡

a proposal 允许限制逻辑复制槽 WAL 保留。我认为这正是您所需要的,但尚不清楚 when/if 它是否可用。

与此同时,您所能做的就是监视情况,如果它开始落后太多,则放弃插槽。当然,这确实意味着您稍后会遇到重新建立同步的问题,但没有办法解决这个问题(除了修复导致复制过程消失的任何问题 and/or 落后)。

既然你说 java 进程不是 运行,那么删除插槽很容易。如果它是 运行,但只是跟不上,那么你将不得不做一个悲伤的小舞,杀死 wal 发送者,然后尝试在它重新启动之前删除插槽(我不知道如何你在 RDS 上这样做)

wal_keep_segments只适用于物理复制,不适用逻辑。它用于 而不是 插槽,而不是它们之外的插槽。如果两者都有,那么 WAL 将被保留,直到满足 both 条件。确实,这就是您面临的问题;逻辑复制不能像物理复制那样不使用插槽来完成。