On Tue, Sep 8, 2026 at 10:42 AM shveta malik <[email protected]> wrote:
>
>
> I tested it further on my machine. Here are the observations:
>
>
> 2)
> FOR TABLE root pub:
> During the intermediate state of DETACH PARTITION ... CONCURRENTLY,
> changes made directly to the partition being detached (t1_part1) are
> also replicated, even though t1_part1 is not explicitly listed in
> pg_publication_tables and pg_partition_root(t1_part1) already returns
> t1_part1. This needs some thought regarding how it should behave.
> Should t1_part1 not replicated here? Thoughts?
>
> Once the detach completes, changes to t1_part1 are no longer
> replicated through the publication of t1, which appears correct.
On debugging further, t1_part1 is also replicated (incorrectly IMO) in
Case 2 because pgoutput's RelationSyncCache is not invalidated during
the first phase of DETACH PARTITION CONCURRENTLY.
In ATExecDetachPartition(), MarkInheritDetached() only updates the
partition's pg_inherits row (inhdetachpending = true), without
generating a cache invalidation. Before commit, only the parent's
relcache is explicitly invalidated via CacheInvalidateRelcache(rel) in
ATExecDetachPartition().
As a result, the partition's previously cached (pre-detach)
RelationSyncEntry is reused, so changes to it continue to be
replicated. This is also confirmed by the fact that if no INSERT is
executed on t1_part1 before DETACH CONCURRENTLY blocks, replication
behaves correctly: the partition is not replicated because a new
RelationSyncCache entry is correctly built after inhdetachpending is
set.
Once FINALIZE runs, the issue self-corrects because
DetachPartitionFinalize() updates the partition's pg_class row
(relispartition = false), which invalidates its relcache, and also
DetachPartitionFinalize() explicitly invalidates the parent and
descendants.
Adding cache-invalidation for part-table here solves the problem, but
I am not sure if it could have any other side-effects. Please have a
look.
@@ -21758,6 +21758,8 @@ ATExecDetachPartition(List **wqueue,
AlteredTableInfo *tab, Relation rel,
/* Invalidate relcache entries for the parent -- must
be before close */
CacheInvalidateRelcache(rel);
+ CacheInvalidateRelcache(partRel);
+
table_close(partRel, NoLock);
table_close(rel, NoLock);
tab->rel = NULL;
thanks
Shveta