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

dns*_*nsh 5 postgresql replication jdbc logical-replication

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

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

final ReplicationSlotInfo replicationSlotInfo = pgConnection.getReplicationAPI()
                    .createReplicationSlot()
                    .logical()
                    .withSlotName(replicationSlotName)
                    .withOutputPlugin("wal2json")
                    .make();
Run Code Online (Sandbox Code Playgroud)

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

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()
Run Code Online (Sandbox Code Playgroud)

当复制器 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;
Run Code Online (Sandbox Code Playgroud)

输出:

slot_name   replicationslotlag  active
data_stream_slot    100 GB  f
Run Code Online (Sandbox Code Playgroud)

这种复制延迟会超过 RDS 磁盘,从而导致 RDS 关闭。

我以为wal_keep_segments会处理这个问题,它被设置为 32。但它不起作用。即使 Java 复制进程未运行,我是否还必须设置任何其他属性来避免这种情况。

jja*_*nes 5

有一项提议允许限制逻辑复制槽 WAL 保留。我认为这正是您所需要的,但尚不清楚何时/是否可用。

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

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

wal_keep_segments只适用于物理复制,不适用于逻辑复制。它是用来代替插槽的,而不是补充它们。如果两者都有,则保留 WAL 直到满足两个条件。事实上,这就是你面临的问题;如果不使用插槽,则无法像物理复制那样完成逻辑复制。

  • 在 Postgres 13 中 - `max_slot_wal_keep_size` (2认同)