public inbox for [email protected]
help / color / mirror / Atom feedFrom: Zhijie Hou (Fujitsu) <[email protected]>
To: Masahiko Sawada <[email protected]>
To: Dilip Kumar <[email protected]>
Cc: Amit Kapila <[email protected]>
Cc: vignesh C <[email protected]>
Cc: [email protected] <[email protected]>
Cc: [email protected] <[email protected]>
Subject: RE: BUG #19360: Bug Report: Logical Replication initial sync fails with "conflict=update_origin_differs" PG12 toPG18
Date: Fri, 3 Apr 2026 07:24:28 +0000
Message-ID: <TYRPR01MB1419594753654605E54773C16945EA@TYRPR01MB14195.jpnprd01.prod.outlook.com> (raw)
In-Reply-To: <CAD21AoCRReJHoLkQBMZztjO7C3Cste9w-PS_SG7VtBW1c3cR9w@mail.gmail.com>
References: <[email protected]>
<CALDaNm3Y6Y4Mub6QC8fZKnNy5jZspELQYCoQF_FL2Zwzweu=og@mail.gmail.com>
<CAA4eK1LxGXR7jOAKh0B8N362S-Q3b6GhBxxcV_HxUaicEPq5Cg@mail.gmail.com>
<CAD21AoDUKQHyy07gTrwsxHTwXAURYnzUYAsf6PxHHv2x1UdFog@mail.gmail.com>
<CAFiTN-vcp7mVT7=rvTpf1uqEQ+rxzDoHd+eJu7u541X9ivG9zQ@mail.gmail.com>
<CAD21AoCRReJHoLkQBMZztjO7C3Cste9w-PS_SG7VtBW1c3cR9w@mail.gmail.com>
On Saturday, January 10, 2026 8:57 AM Masahiko Sawada <[email protected]> wrote:
>
> On Thu, Jan 8, 2026 at 8:46 PM Dilip Kumar <[email protected]> wrote:
> >
> > On Fri, Jan 9, 2026 at 4:17 AM Masahiko Sawada
> <[email protected]> wrote:
> > > Can we somehow
> > > share the apply worker's origin with tablesync workers so that they
> > > can refer to the same origin ID? Or can we invent special origin IDs
> > > (e.g., > 0x00FF) that are the same as the normal origin ID except
> > > for being ignored by the conflict detection system?
> >
> > How will this distinguish between the initial sync is done from the
> > publisher node we are getting the update vs the initial sync is done
> > from some other node? Can we always ignore conflict checking for
> > initial synced data or do we just want to ignore if the initial sync
> > is done from the same node?
>
> I imagined the former idea; always ignore conflict checking, so we don't need
> to distinguish them. IOW we treat the changes via the initial tablesync as if
> the changes made by the normal backend process (who doesn't use
> replication origin) while using the replication tracking ability of the replication
> origin.
I think for changes made by backend process without setting up the origin, the
apply worker still treat that as a conflict change when applying the remote
changes as that's necessary to local vs. remote updates.
I personally prefer to let the tablesync worker share the apply worker's origin
ID while keeping a separate origin for progress tracking. Currently, the worker
first calls replorigin_session_setup() and then stores the origin ID in
replorigin_xact_state. The natural implementation is for the tablesync worker to
still set up its own origin for tracking, but assign the apply worker's origin
ID to the global state. This gives us per‑tablesync progress tracking while
ensuring that changes from both workers appear to come from the same origin.
A small patch demonstrating this approach is attached.
Best Regards,
Hou zj
Attachments:
[application/octet-stream] v1-0001-write-tablesync-changes-with-the-subscription-ori.patch (4.7K, 2-v1-0001-write-tablesync-changes-with-the-subscription-ori.patch)
download | inline diff:
From 3047c7473df8f3be43859c1bec74c99fba80ecf0 Mon Sep 17 00:00:00 2001
From: Zhijie Hou <[email protected]>
Date: Fri, 3 Apr 2026 13:44:40 +0800
Subject: [PATCH v1] write tablesync changes with the subscription origin ID
During initial table synchronization, tablesync workers were writing tuples with
the per-table tablesync origin identity. Later, when the leader apply worker
processed UPDATE/DELETE for those tuples, conflict checks could see an origin
mismatch and report benign update_origin_differs or delete_origin_differs noise
for changes from the same subscription.
Fix this by keeping the tablesync origin for per-table sync progress tracking
and resume but stamp tuple writes with the subscription-level apply origin
identity. This ensures conflict detection sees tablesync and apply changes as
coming from the same subscription.
---
src/backend/replication/logical/tablesync.c | 27 ++++++++++++++++++---
src/test/subscription/t/029_on_error.pl | 9 +++++++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index f49a4852ecb..4aa39341e8e 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -1226,6 +1226,7 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
AclResult aclresult;
WalRcvExecResult *res;
char originname[NAMEDATALEN];
+ char applyoriginname[NAMEDATALEN];
ReplOriginId originid;
UserContext ucxt;
bool must_use_password;
@@ -1285,12 +1286,17 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
MyLogicalRepWorker->relstate == SUBREL_STATE_DATASYNC ||
MyLogicalRepWorker->relstate == SUBREL_STATE_FINISHEDCOPY);
- /* Assign the origin tracking record name. */
+ /* Assign the origin tracking record names. */
ReplicationOriginNameForLogicalRep(MySubscription->oid,
MyLogicalRepWorker->relid,
originname,
sizeof(originname));
+ ReplicationOriginNameForLogicalRep(MySubscription->oid,
+ InvalidOid,
+ applyoriginname,
+ sizeof(applyoriginname));
+
if (MyLogicalRepWorker->relstate == SUBREL_STATE_DATASYNC)
{
/*
@@ -1320,7 +1326,15 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
*/
originid = replorigin_by_name(originname, false);
replorigin_session_setup(originid, 0);
- replorigin_xact_state.origin = originid;
+
+ /*
+ * Tablesync keeps its own origin for replication progress, but writes
+ * must be tagged with the subscription-level apply origin so conflict
+ * detection sees tablesync and apply changes as coming from the same
+ * subscription.
+ */
+ replorigin_xact_state.origin = replorigin_by_name(applyoriginname, false);
+
*origin_startpos = replorigin_session_get_progress(false);
CommitTransactionCommand();
@@ -1407,7 +1421,14 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
UnlockRelationOid(ReplicationOriginRelationId, RowExclusiveLock);
replorigin_session_setup(originid, 0);
- replorigin_xact_state.origin = originid;
+
+ /*
+ * Tablesync keeps its own origin for replication progress, but writes
+ * must be tagged with the subscription-level apply origin so conflict
+ * detection sees tablesync and apply changes as coming from the same
+ * subscription.
+ */
+ replorigin_xact_state.origin = replorigin_by_name(applyoriginname, false);
/*
* If the user did not opt to run as the owner of the subscription
diff --git a/src/test/subscription/t/029_on_error.pl b/src/test/subscription/t/029_on_error.pl
index 7d68759b6cd..85d3478f44f 100644
--- a/src/test/subscription/t/029_on_error.pl
+++ b/src/test/subscription/t/029_on_error.pl
@@ -146,6 +146,8 @@ COMMIT;
test_skip_lsn($node_publisher, $node_subscriber,
"(2, NULL)", "2", "test skipping transaction");
+my $log_location = -s $node_subscriber->logfile;
+
# Test for PREPARE and COMMIT PREPARED. Update the data and PREPARE the
# transaction, raising an error on the subscriber due to violation of the
# unique constraint on tbl. Then skip the transaction.
@@ -160,6 +162,13 @@ COMMIT PREPARED 'gtx';
test_skip_lsn($node_publisher, $node_subscriber,
"(3, NULL)", "3", "test skipping prepare and commit prepared ");
+# Check that no update_origin_differs conflicts are raised
+my $logfile = slurp_file($node_subscriber->logfile(), $log_location);
+unlike(
+ $logfile,
+ qr/conflict detected on relation "public.tbl": conflict=update_origin_differs.*/,
+ 'modifying the row copied by tablesync should not cause update_origin_differs conflict');
+
# Test for STREAM COMMIT. Insert enough rows to tbl to exceed the 64kB
# limit, also raising an error on the subscriber during applying spooled
# changes for the same reason. Then skip the transaction.
--
2.53.0.windows.2
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: RE: BUG #19360: Bug Report: Logical Replication initial sync fails with "conflict=update_origin_differs" PG12 toPG18
In-Reply-To: <TYRPR01MB1419594753654605E54773C16945EA@TYRPR01MB14195.jpnprd01.prod.outlook.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox