Re: Proposal: Conflict log history table for Logical Replication

From: Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>
To: Dilip Kumar <dilipbalaut(at)gmail(dot)com>
Cc: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, shveta malik <shveta(dot)malik(at)gmail(dot)com>, vignesh C <vignesh21(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, "Zhijie Hou (Fujitsu)" <houzj(dot)fnst(at)fujitsu(dot)com>, saurabh singh <saurabh(dot)singh214(at)gmail(dot)com>, Robert Haas <robertmhaas(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Proposal: Conflict log history table for Logical Replication
Date: 2026-09-18 08:05:04
Message-ID: CABdArM5vtNjOTutk98qi_0zw59Nch4zjzGL8_=R6yCAcYac73A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Sep 17, 2026 at 8:06 PM Dilip Kumar <dilipbalaut(at)gmail(dot)com> wrote:
>
> >
> > Overall, I prefer option 2 and deal with the very rare cases in a
> > separate patch if necessary.
>
> Yes, that makes sense. I have prepared a top-up patch using approach
> 2, IMHO the edge case should realistically only trigger when a
> user-defined type’s output function produces an unusually massive
> value. I'll see if I can construct a test for this. While we could
> theoretically simulate it with a minimal on-disk type whose output
> function generates a 1GB string, that feels more like an
> artificial/pathological case than a realistic workload.
>

Thanks for the patch. Please find a few initial comments; I’m still reviewing.

1) Issue #2 from [1] is not fixed yet.
replica_identity is currently built from the index's full descriptor,
so INCLUDE columns are included. This is incorrect because:
a) INCLUDE columns are not part of the lookup key, so this does not
match the log, which reports only key columns.
b) On UPDATE, an INCLUDE column can contain arbitrarily large
text/json values and unnecessarily contribute to the tuple size.

The attached diff copies only the index key attributes. Please
consider it if the approach looks reasonable.
~~~

2) Now that remote_tuple has been removed, there is some information
loss when the replica identity key itself is updated.
For example:
-- pub
INSERT INTO t1 VALUES (3,'three');
-- sub
DELETE FROM t1 WHERE a = 3;
-- pub
UPDATE t1 SET a = 30 WHERE a = 3;

Server log:
conflict detected on relation "public.t1": conflict=update_missing
DETAIL: Could not find the row to be updated: remote row (30,
three), replica identity (a)=(3).

Conflict log table: replica_identity = {"a":3}, and there is no
mention of the new key 30 anywhere.

For update_missing the remote change is skipped, but for
update_origin_differs the change is applied, so the local row now has
a=30 while the CLT row names a=3, and nothing connects the two. The
log will show the remote tuple, though.

I am not sure a separate column something like "remote_new_key" is
worth it just for this case as it would be NULL for the two delete
conflicts, and identical to replica_identity for every update that
does not change the key. I think we can document that replica_identity
contains the old key when the key is updated. Thoughts?
~~~

[1] https://www.postgresql.org/message-id/CABdArM5HbgRhPttsnZ2SFmxCMgqcanbyT4ZCo%3DfJBV0V65Hp_w%40mail.gmail.com

--
Thanks,
Nisha

Attachment Content-Type Size
v74_nisha_fix.diff application/octet-stream 927 bytes

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Chao Li 2026-09-18 08:27:50 Re: COMMENT/SEC LABEL tab complete support suggests wrong SQL.
Previous Message Kirill Reshke 2026-09-18 08:01:18 COMMENT/SEC LABEL tab complete support suggests wrong SQL.