Re: Proposal: Conflict log history table for Logical Replication

From: vignesh C <vignesh21(at)gmail(dot)com>
To: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Cc: Dilip Kumar <dilipbalaut(at)gmail(dot)com>, Nisha Moond <nisha(dot)moond412(at)gmail(dot)com>, Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>, Peter Smith <smithpb2250(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(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 <shvetamalik(at)gmail(dot)com>
Subject: Re: Proposal: Conflict log history table for Logical Replication
Date: 2026-05-12 06:00:54
Message-ID: CALDaNm2UB5p7LCnw27YRe5+59gk_-X7jJ9yPM-BTW1cQaHkkog@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, 11 May 2026 at 11:51, shveta malik <shveta(dot)malik(at)gmail(dot)com> wrote:
>
> Few comments on 001:
> 3)
> Currently the structure of CLT is:
>
> +const ConflictLogColumnDef ConflictLogSchema[] = {
> + { .attname = "relid", .atttypid = OIDOID },
> + { .attname = "schemaname", .atttypid = TEXTOID },
> + { .attname = "relname", .atttypid = TEXTOID },
> + { .attname = "conflict_type", .atttypid = TEXTOID },
> + { .attname = "remote_xid", .atttypid = XIDOID },
> + { .attname = "remote_commit_lsn",.atttypid = LSNOID },
> + { .attname = "remote_commit_ts", .atttypid = TIMESTAMPTZOID },
> + { .attname = "remote_origin", .atttypid = TEXTOID },
> + { .attname = "replica_identity", .atttypid = JSONOID },
> + { .attname = "remote_tuple", .atttypid = JSONOID },
> + { .attname = "local_conflicts", .atttypid = JSONARRAYOID }
> +};
>
> So if user has to delete a conflict from CLT after resolving it, then
> what is the user-friendly way to do it? IMO, it will be cumbersome
> (and perhaps error-prone) to write a query with remote_commit_lsn,
> remote_commit_ts, remote_xid etc in WHERE clause. Do you (or others)
> think we shall add a log_id column (perhaps a bigint GENERATED ALWAYS
> AS IDENTITY). This provides a simple, unique identifier so the user
> can easily target a single row (WHERE log_id = 105) or purge a batch
> of old conflicts (WHERE log_id < 1000).

I agree with this. I could think of a few other possible approaches as well.
The following options seem possible to make row identification/deletion easier:
a) Use existing remote_commit_ts
ex:
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE remote_commit_ts =
'2026-05-12 10:25:46.483899+05:30';
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE remote_commit_ts <
now() - interval '100 minutes';
b) Use existing system column ctid
ex:
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE ctid = '(0,1)';
c) Add a dedicated identifier conflict_id column as Shveta said
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE conflict_id = 42;
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE conflict_id < 100;
d) Add a local conflict_logged_at timestamp
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE conflict_logged_at
= '2026-05-12 10:25:46.483899+05:30';
DELETE FROM pg_conflict.pg_conflict_log_16400 WHERE conflict_logged_at
< now() - interval '100 minutes';

I'm not sure which approach would be best here.
Thoughts?

Regards,
Vignesh

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tatsuo Ishii 2026-05-12 06:03:28 Re: Row pattern recognition
Previous Message Michael Paquier 2026-05-12 05:42:58 Re: Fix pg_stat_statements display of normalized FETCH counts