Re: Crashes on a partition whose concurrent detach never finished

From: shveta malik <shveta(dot)malik(at)gmail(dot)com>
To: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Cc: Mihail Nikalayeu <mihailnikalayeu(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>, vignesh C <vignesh21(at)gmail(dot)com>, ashutosh(dot)bapat(dot)oss(at)gmail(dot)com, shveta malik <shveta(dot)malik(at)gmail(dot)com>
Subject: Re: Crashes on a partition whose concurrent detach never finished
Date: 2026-09-08 07:05:35
Message-ID: CAJpy0uA6womAP7fkmT=sSfKG_0CfKUSb7HhP_J9mw071MXc39w@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Tue, Sep 8, 2026 at 10:42 AM shveta malik <shveta(dot)malik(at)gmail(dot)com> 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

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Michael Paquier 2026-09-08 07:14:20 Re: Improve error handling in test modules: test_extensible, test_bitmapset
Previous Message Michael Paquier 2026-09-08 07:05:24 Re: Missing dshash cleanup in pgstat_read_statsfile() after OOM