使用 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_receivewal
或 pg_rewind
.
等目的
wal_keep_segments 指定 PostgreSQL 应在 pg_xlog
目录中保留的 最小 段数。 PostgreSQL 不删除段可能有几个原因:
- 在比 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;
WAL 归档已启用,但 archive_command
失败。请在这种情况下检查 PostgreSQL 日志。
好久没有关卡
a proposal 允许限制逻辑复制槽 WAL 保留。我认为这正是您所需要的,但尚不清楚 when/if 它是否可用。
与此同时,您所能做的就是监视情况,如果它开始落后太多,则放弃插槽。当然,这确实意味着您稍后会遇到重新建立同步的问题,但没有办法解决这个问题(除了修复导致复制过程消失的任何问题 and/or 落后)。
既然你说 java 进程不是 运行,那么删除插槽很容易。如果它是 运行,但只是跟不上,那么你将不得不做一个悲伤的小舞,杀死 wal 发送者,然后尝试在它重新启动之前删除插槽(我不知道如何你在 RDS 上这样做)
wal_keep_segments
只适用于物理复制,不适用逻辑。它用于 而不是 插槽,而不是它们之外的插槽。如果两者都有,那么 WAL 将被保留,直到满足 both 条件。确实,这就是您面临的问题;逻辑复制不能像物理复制那样不使用插槽来完成。
我正在创建复制槽并通过 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_receivewal
或 pg_rewind
.
wal_keep_segments 指定 PostgreSQL 应在 pg_xlog
目录中保留的 最小 段数。 PostgreSQL 不删除段可能有几个原因:
- 在比 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;
WAL 归档已启用,但
archive_command
失败。请在这种情况下检查 PostgreSQL 日志。好久没有关卡
a proposal 允许限制逻辑复制槽 WAL 保留。我认为这正是您所需要的,但尚不清楚 when/if 它是否可用。
与此同时,您所能做的就是监视情况,如果它开始落后太多,则放弃插槽。当然,这确实意味着您稍后会遇到重新建立同步的问题,但没有办法解决这个问题(除了修复导致复制过程消失的任何问题 and/or 落后)。
既然你说 java 进程不是 运行,那么删除插槽很容易。如果它是 运行,但只是跟不上,那么你将不得不做一个悲伤的小舞,杀死 wal 发送者,然后尝试在它重新启动之前删除插槽(我不知道如何你在 RDS 上这样做)
wal_keep_segments
只适用于物理复制,不适用逻辑。它用于 而不是 插槽,而不是它们之外的插槽。如果两者都有,那么 WAL 将被保留,直到满足 both 条件。确实,这就是您面临的问题;逻辑复制不能像物理复制那样不使用插槽来完成。