Re: BUG #19723: CREATE INDEX racing with ALTER INDEX ATTACH PARTITION triggers unexpected internal error

From: Ayush Tiwari <ayushtiwari(dot)slg01(at)gmail(dot)com>
To: exclusion(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org, Álvaro Herrera <alvherre(at)kurilemu(dot)de>
Subject: Re: BUG #19723: CREATE INDEX racing with ALTER INDEX ATTACH PARTITION triggers unexpected internal error
Date: 2026-09-28 04:44:08
Message-ID: CAJTYsWV3K0vN1c=4ZEybDtcMKRLk2qatFvG2aQRQ1ZXVWXMn3Q@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hi,

On Sat, 26 Sept 2026 at 19:55, Ayush Tiwari <ayushtiwari(dot)slg01(at)gmail(dot)com> wrote:
> On Sat, 26 Sept 2026 at 18:51, PG Bug reporting form
> <noreply(at)postgresql(dot)org> wrote:
> >
> > The following bug has been logged on the website:
> >
> > Bug reference: 19723
> > Logged by: Alexander Lakhin
> > Email address: exclusion(at)gmail(dot)com
> > PostgreSQL version: 19beta4
> > Operating system: Ubuntu 24.04
> > Description:
> >
> > The following script:
> > echo "
> > CREATE TABLE t (a int, b int) PARTITION BY list (b);
> > CREATE TABLE tp1 PARTITION OF t FOR VALUES IN (1);
> > " | psql
> >
> > for ((i=1;i<=100;i++)); do
> > echo "iteration $i"
> > echo "
> > DROP INDEX t_a_idx;
> > DROP INDEX t_a_idx2;
> > CREATE INDEX t_a_idx ON ONLY t (a);
> > CREATE INDEX tp1_a_idx ON tp1 (a);
> > " | psql
> >
> > echo "ALTER INDEX t_a_idx ATTACH PARTITION tp1_a_idx;" | psql &
> > echo "CREATE INDEX t_a_idx2 ON t(a);" | psql
> > wait
> > grep 'ERROR: bogus pg_inherit row' server.log && break;
> > done
> >
> > tirggers:
> > iteration 3
> > DROP INDEX
> > DROP INDEX
> > CREATE INDEX
> > CREATE INDEX
> > ERROR: bogus pg_inherit row: inhrelid 16400 inhparent 16399
> > ALTER INDEX
> > 2026-09-26 04:36:22.653 EDT|user|regression|6ab78406.1ddce8|XX000 ERROR:
> > bogus pg_inherit row: inhrelid 16400 inhparent 16399
> >
> > which is described as unexpected:
> > /*
> > * A pg_inherits row exists. If it's the same we
> > want, then we're
> > * good; if it differs, that amounts to a corrupt
> > catalog and
> > * should not happen.
> > */
> > if (inhForm->inhparent != parentOid)
> > {
> > /* unexpected: we should not get called in
> > this case */
> > elog(ERROR, "bogus pg_inherit row: inhrelid
> > %u inhparent %u",
> > inhForm->inhrelid,
> > inhForm->inhparent);
> > }
> >
> > Reproduced starting from 8b08f7d48.
>
> Thanks for the report with repro and bisect.
>
> I think I see how this happens. DefineIndex() calls has_superclass()
> before locking the child index, although its comment says the caller
> *must hold that lock*. If ALTER INDEX ... ATTACH hasn't committed yet,
> CREATE INDEX sees the child as unattached, waits in index_open(), and
> then tries to attach it to its new parent after ATTACH commits.
>
> Would it make sense to open the index before calling has_superclass()?
> Then the check would see the attachment after the wait and skip that
> index.
>
> The below simple diff fixed the issue for me:
>
> ---
> diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
> index 5a0312fe772..561dd124e2c 100644
> --- a/src/backend/commands/indexcmds.c
> +++ b/src/backend/commands/indexcmds.c
> @@ -1453,11 +1453,14 @@ DefineIndex(ParseState *pstate,
> Relation cldidx;
> IndexInfo *cldIdxInfo;
>
> + cldidx = index_open(cldidxid, lockmode);
> /* this index is already partition of another one */
> if (has_superclass(cldidxid))
> + {
> + index_close(cldidx, lockmode);
> continue;
> + }
>
> - cldidx = index_open(cldidxid, lockmode);
> cldIdxInfo = BuildIndexInfo(cldidx);

Post some more testing, attaching patch file with above diff.

Regards,
Ayush

Attachment Content-Type Size
v1-0001-Lock-child-index-before-checking-its-parent.patch application/octet-stream 1.7 KB

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message shihao zhong 2026-09-28 06:37:43 Re: PostgreSQL 18.6/17.11: standby PANIC on restart after VM truncation
Previous Message Peter Geoghegan 2026-09-28 04:13:14 Re: BUG #19686: Rolling back SET TABLESPACE + INSERT leads to index corruption