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:57:32
Message-ID: CALDaNm2jw-yGtoC23bcqXp0eCz34+GRU5Okq=iuhCpQrscJjGA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, 1 Sept 2026 at 11:36, vignesh C <vignesh21(at)gmail(dot)com> wrote:
>
> 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.

I analyzed the issue further and found that the same allocation
failure already exists through other code paths, independent of the
patch.

For both examples, I used the following setup:
CREATE TABLE tab_huge (id int PRIMARY KEY, a text, b text, c text);
ALTER TABLE tab_huge ALTER COLUMN a SET STORAGE EXTERNAL;
ALTER TABLE tab_huge ALTER COLUMN b SET STORAGE EXTERNAL;
ALTER TABLE tab_huge ALTER COLUMN c SET STORAGE EXTERNAL;
INSERT INTO tab_huge VALUES (1, repeat('a', 400 * 1024 * 1024));
-- Add another 400 MB value to the row.
UPDATE tab_huge 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 tab_huge SET c = repeat('c', 400 * 1024 * 1024) WHERE id = 1;

Example 1: REPLICA IDENTITY FULL
ALTER TABLE tab_huge REPLICA IDENTITY FULL;
UPDATE tab_huge SET id = 2 WHERE id = 1;
ERROR: invalid memory alloc request size 1258291264

Example 2: Inserting a row with more than 1 GB of data
INSERT INTO tab_huge VALUES (2, repeat('a', 400 * 1024 * 1024),
repeat('a', 400 * 1024 * 1024), repeat('a', 400 * 1024 * 1024));
ERROR: invalid memory alloc request size 1258291264

This suggests that the allocation failure is not necessarily
introduced by the patch. The same limitation can already be triggered
by existing code paths when PostgreSQL needs to form or flatten a
tuple containing more than 1 GB of data. Given this, the failure in
the earlier test may be an existing limitation rather than a failure
caused by the patch.
Thoughts?

Regards,
Vignesh

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Ashutosh Bapat 2026-09-01 07:01:27 Re: PGQ catalog representation and pg_dump support
Previous Message Xuneng Zhou 2026-09-01 06:28:19 Re: WAIT FOR NO_THROW option could use some documentation