From 74fba59d7bc41703ccb05de1ac14b606aecc99c5 Mon Sep 17 00:00:00 2001 From: Nisha Moond Date: Wed, 2 Sep 2026 19:54:47 +0530 Subject: [PATCH v1 1/2] Avoid re-creating the conflict slot on retry in FindConflictTuple() FindConflictTuple() created a new tuple table slot on each retry when table_tuple_lock() returned TM_Updated, leaving the previous slot holding a buffer pin until the apply transaction ended. Since these slots were not registered in es_tupleTable, they were not released by ExecResetTupleTable(). Create the slot once before the retry loop and reuse it. Re-storing the tuple in the same slot releases the previous buffer pin, avoiding the accumulation of pinned buffers during repeated retries. Oversight in commit 9758174e2e5. Backpatch-through: 18 --- src/backend/executor/execReplication.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index b2ca5cbf117..7886f4850e9 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -722,28 +722,25 @@ FindConflictTuple(ResultRelInfo *resultRelInfo, EState *estate, TM_FailureData tmfd; TM_Result res; - *conflictslot = NULL; - /* * Build additional information required to check constraints violations. * See check_exclusion_or_unique_constraint(). */ BuildConflictIndexInfo(resultRelInfo, conflictindex); + /* Create the slot once and reuse it across retries */ + *conflictslot = table_slot_create(rel, NULL); + retry: if (ExecCheckIndexConstraints(resultRelInfo, slot, estate, &conflictTid, &slot->tts_tid, list_make1_oid(conflictindex))) { - if (*conflictslot) - ExecDropSingleTupleTableSlot(*conflictslot); - + ExecDropSingleTupleTableSlot(*conflictslot); *conflictslot = NULL; return false; } - *conflictslot = table_slot_create(rel, NULL); - PushActiveSnapshot(GetLatestSnapshot()); res = table_tuple_lock(rel, &conflictTid, GetActiveSnapshot(), -- 2.50.1 (Apple Git-155)