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: 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>, Masahiko Sawada <sawada(dot)mshk(at)gmail(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>, shveta malik <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Proposal: Conflict log history table for Logical Replication
Date: 2026-08-28 13:22:34
Message-ID: CABdArM5HbgRhPttsnZ2SFmxCMgqcanbyT4ZCo=fJBV0V65Hp_w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Plase find couple more comments for v72

Patch-001:
1) We don't allow CLT to be published, so it is excluded from logical
decoding. But, RelationIsLogicallyLogged() only checks for the
pg_conflict namespace. We haven't prevented the underlying TOAST
tables from being decoded. So, even though CLT itself is not decoded,
its TOAST table still passes the check and can accumulate/queue data
in the reorderbuffer.

I think we should pass the HEAP_INSERT_NO_LOGICAL flag in
insert_conflict_log_tuple() -> heap_insert(), so it is also propagated
to the TOAST tables.

Thoughts?
~~~

2) There is a case when replica_identity is reported different in LOG
vs CLT. It seems a side-effect of INCLUDE in the RI index.
A testcase:
-- Table on both nodes:
CREATE TABLE ri_conf (a int NOT NULL, b text, c text);
CREATE UNIQUE INDEX ri_conf_i ON ri_conf (a) INCLUDE (b);
ALTER TABLE ri_conf REPLICA IDENTITY USING INDEX ri_conf_i;

-- Pub
INSERT INTO ri_conf VALUES (1, 'bee', 'cee');

-- Sub: modify locally so the row's origin differs from the incoming change
UPDATE ri_conf SET c = 'local' WHERE a = 1;

-- Pub: trigger delete_origin_differs
DELETE FROM ri_conf WHERE a = 1;

Log on sub:
LOG: conflict detected on relation "public.ri_conf":
conflict=delete_origin_differs
DETAIL: Deleting the row that was modified locally in transaction
817 at 2026-08-28 14:00:12.062999+05:30: local row (1, bee, local),
replica identity (a)=(1).

CLT on sub:
SELECT conflict_type, replica_identity_full, replica_identity
FROM pg_conflict.pg_conflict_log_16390
WHERE relname = 'ri_conf';
conflict_type | replica_identity_full | replica_identity
-----------------------+-----------------------+-----------------------
delete_origin_differs | f | {"a":1,"b":null}

CLT is wrongly reporting column 'b' in replica_identity.
~~~

--
Thanks,
Nisha

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Richard Guo 2026-08-28 13:29:17 Wrong result from JSON constructor in a simple CASE
Previous Message Karina Litskevich 2026-08-28 13:18:29 Re: Function scan FDW pushdown