Re: Test publication.sql racing with subscription.sql might fail due to cache lookup error

From: vignesh C <vignesh21(at)gmail(dot)com>
To: "Hayato Kuroda (Fujitsu)" <kuroda(dot)hayato(at)fujitsu(dot)com>
Cc: Zhijie Hou <houzhijie22(at)gmail(dot)com>, Alexander Lakhin <exclusion(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Test publication.sql racing with subscription.sql might fail due to cache lookup error
Date: 2026-11-03 14:51:17
Message-ID: CALDaNm1rX0EFjBX3j1Dsj9n_rhW0w-j83H=UjoH3ErDj-WtfOw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, 2 Nov 2026 at 15:26, Hayato Kuroda (Fujitsu)
<kuroda(dot)hayato(at)fujitsu(dot)com> wrote:
>
> Hi Vignesh,
>
> > Thanks for reporting this issue, I was able to reproduce this. It was
> > reachable because for a partitioned table OpenTableList() does not
> > lock the partitions (only a non-partitioned inheritance parent gets
> > find_all_inheritors() with ShareUpdateExclusiveLock), so ADD TABLE
> > holds a lock on the root only. The partitions are collected later in
> > GetPubPartitionOptionRelations() with find_all_inheritors(NoLock).
> > Dropping a partition takes AccessExclusiveLock on the partition and on
> > its direct parent, so a direct child conflicts with the ALTER through
> > the root, but a grandchild does not.
> > The updated v3 version patch has the changes to handle the same.
>
> While investigating this issue, I found another case where a cache lookup can
> fail. Unlike the previously discussed case, this failure occurs while
> find_all_inheritors() is still building the relation list, before
> InvalidatePublicationRels() is called. Do you think we should also fix,
> or should be done in other places?
>
> The issue can be reproduced with a multi-level partition tree [1]. Note that p1
> must be created before p2. Brief steps:
>
> 0. Run "ALTER PUBLICATION ADD TABLE root".
> 1. find_all_inheritors(root, NoLock, ...) adds root to rels_list.
> 2. It processes "root" and appends "p1" and "p2" to rels_list.
> 3. It processes "p1" and appends "trigger".
> 4. It processes "p2" and appends "victim".
> 5. Another backend drops "victim". This cannot be conflicted because the DROP command
> acquires locks only for the table (victim) and its direct parent (p2).
> 6. The first backend processes "trigger". Invalidation messages can be handled
> here because the table has a child and system catalog is opened.
> 7. It processes "victim". Since it's dropped and the inval message is handled,
> it causes the cache lookup failure.
>
> [1]
> root
> |---- p1
> | +---- trigger
> | +---- other
> +---- p2
> +---- victim

Thanks, I was able to reproduce the issue.
I looked further and found that the same issue can occur when callers
operate on a partition tree with NoLock in the following cases: a)
VACUUM / ANALYZE on a partitioned table b) LOCK TABLE on a partitioned
table c) REPACK / CLUSTER on a partitioned table
I tried the same scenario with VACUUM and LOCK TABLE and was able to
reproduce the issue. The test is attached.

The current error, cache lookup failed for relation, is an internal
error and is not very helpful to the user. It would be better to
report a clearer error, such as relation may have been dropped
concurrently, when the caller cannot tolerate a missing relation. If
the caller can tolerate it, the missing child relation could simply be
skipped.
Thoughts?

Regards,
Vignesh

Attachment Content-Type Size
0001-Test-to-reproduce-cache-lookup-failure-with-vacuum-a.patch application/octet-stream 6.9 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Fujii Masao 2026-11-03 14:53:12 Re: [Bug Report + Patch] File descriptor leak when io_method=io_uring
Previous Message Zhijie Hou 2026-11-03 14:37:04 Re: Proposal: Conflict log history table for Logical Replication