Re: Logical replication row filter loses unchanged toasted columns

From: vignesh C <vignesh21(at)gmail(dot)com>
To: "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>
Cc: Shinya Kato <shinya11(dot)kato(at)gmail(dot)com>, "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Matthias van de Meent <boekewurm+postgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>
Subject: Re: Logical replication row filter loses unchanged toasted columns
Date: 2026-09-01 06:06:04
Message-ID: CALDaNm1841L9w9By0OBHBZsqV=io63XG3nOdNKrRtQ818BwkGg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, 31 Aug 2026 at 08:45, Zhijie Hou (Fujitsu)
<houzj(dot)fnst(at)fujitsu(dot)com> wrote:
>
> Here is the updated patch which addressed all comments including Kuroda-San's[1].

Thanks for the updated patch.
I found one case where the update fails with the following test:
CREATE TABLE t (id int PRIMARY KEY, a text, b text, c text);
ALTER TABLE t ALTER COLUMN a SET STORAGE EXTERNAL;
ALTER TABLE t ALTER COLUMN b SET STORAGE EXTERNAL;
ALTER TABLE t ALTER COLUMN c SET STORAGE EXTERNAL;

-- Create a row with more than 400MB of TOASTed data
INSERT INTO t VALUES (1, repeat('a', 400 * 1024 * 1024));

-- Add another 400 MB value to the row.
UPDATE t SET b = repeat('b', 400 * 1024 * 1024) WHERE id = 1;

-- Add another 400 MB value, bringing the total row data to ~1.2 GB.
UPDATE t SET c = repeat('c', 400 * 1024 * 1024) WHERE id = 1;

CREATE PUBLICATION p FOR TABLE t WHERE (id < 0);

UPDATE t SET id = 2 WHERE id = 1;
ERROR: invalid memory alloc request size 1258291264

DROP PUBLICATION p;
-- Without the publication, the same update succeeds.
UPDATE t SET id = 2 WHERE id = 1; -- succeeds

The failure appears to be caused by BuildOldKeyTuple. It inlines all
three TOASTed column values (a, b, and c) into a single tuple and then
passes the resulting tuple to heap_form_tuple(). Since each column is
approximately 400 MB, the resulting tuple requires roughly 1.2 GB of
memory. In this case, palloc0() attempts to allocate 1,258,291,264
bytes, which exceeds PostgreSQL's MaxAllocSize of 1,073,741,823 bytes,
resulting in the error.

Interestingly, the update succeeds after dropping the publication, so
this appears to be specific to the code path triggered by the
publication's row filter.

Regards,
Vignesh

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Virender Singla 2026-09-01 06:18:43 [PATCH] Corruption Issue: Fix missing tts_tid in ExecForceStoreHeapTuple
Previous Message Chao Li 2026-09-01 06:01:16 Re: Reducing relcache memory usage: deduping index shapes