Hello hackers

find_all_inheritors() with NoLock doesn't lock anything below the
given relation, but it still calls find_inheritance_children() on
every relation it found, which starts with has_subclass(), and that
errors out if the pg_class row is gone:

ERROR:  cache lookup failed for relation 16398

This needs a sub-partitioned table below the first level (root -> p1
-> p2, we hold a lock on root only, DROP TABLE p2 only locks p1 and
p2) to be dropped after it was found, but before it is expanded.

There are 5 callers using NoLock: VACUUM, ANALYZE, REPACK/CLUSTER and
LOCK TABLE on a partitioned table, and pg_get_publication_tables().

Dropping old sub-partitions while something vacuums the root seems
like a realistic way to hit it, the window grows with the number of
partitions.

The attached patch makes find_inheritance_children_extended() return
an empty list if the relation is gone, instead of erroring out.
It also adds an injection point before the pg_inherits scan, and a TAP
test which fails without the fix.

Found while working on the REPACK foreign partition warning patch [1].

[1]: 
https://www.postgresql.org/message-id/CAN4CZFM1g0oDs5Ee_5OWzf3YF-01rQDAak6ut_OWxEJJ%2BUmnXA%40mail.gmail.com

Attachment: v1-0001-Fix-find_all_inheritors-with-NoLock-against-concu.patch
Description: Binary data

Reply via email to