Re: Can I assume relation would not be invalid during from ExecutorRun to ExecutorEnd - Mailing list pgsql-hackers

From Robert Haas
Subject Re: Can I assume relation would not be invalid during from ExecutorRun to ExecutorEnd
Date
Msg-id CA+TgmoZfb0GzsRwa-qqnE6aSJUMeGMzb1Phjoaa2Ep8WK7bq3g@mail.gmail.com
Whole thread Raw
In response to Re: Can I assume relation would not be invalid during from ExecutorRun to ExecutorEnd  (Andy Fan <zhihui.fan1213@gmail.com>)
Responses Re: Can I assume relation would not be invalid during from ExecutorRun to ExecutorEnd  (Andy Fan <zhihui.fan1213@gmail.com>)
List pgsql-hackers
On Tue, Nov 30, 2021 at 7:50 PM Andy Fan <zhihui.fan1213@gmail.com> wrote:
> I think you misunderstand me,  I argued with the answer because after I got the
> answer and I rethink my problem, I found my question description is not accurate
> enough,  so I improved the question and willing discussion again. My exception was
> things will continue with something like this:
> 1. In your new described situation,  your solution still does not work because ...
> 2. In your new described situation,  the solution would work for sure
> 3.  your situation is still not cleared enough.

I mean, it's clear to me that you can make a new table get opened at
any time in the execution of a query. Just use CASE or an IF statement
inside of a stored procedure to do nothing for the first 9999 calls
and then on call 10000 access a new relation. And as soon as that
happens, you can AcceptInvalidationMessages(), which can cause
relcache entries to be destroyed or rebuilt. If the relation is open,
the relcache entry can't be destroyed altogether, but it can be
rebuilt: see RelationClearRelation(). Whether that's a problem for
what you are doing I don't know. But the overall point is that access
to a new relation can happen at any point in the query -- and as soon
as it does, we will accept ALL pending invalidation messages for ALL
relations regardless of what locks anyone holds on anything.

So it's generally a mistake to assume that relcache entries are
"stable" across large stretches of code. They are in fact stable in a
certain sense - if we have the relation open, we hold a reference
count on it, and so the Relation pointer itself will remain valid. But
the data it points to can change in various ways, and different
members of the RelationData struct are handled differently. Separately
from the reference count, the heavyweight lock that we also hold on
the relation as a condition of opening it prevents certain kinds of
changes, so that even if the relation cache entry is rebuilt, certain
particular fields will be unaffected. Which fields are protected in
this way will depend on what kind of lock is held. It's hard to speak
in general terms. The best advice I can give you is (1) look exactly
what RelationClearRelation() is going to do to the fields you care
about if a rebuild happens, (2) err on the side of assuming that
things can change under you, and (3) try running your code under
debug_discard_caches = 1. It will be slow that way, but it's pretty
effective in finding places where you've made unsafe assumptions.

-- 
Robert Haas
EDB: http://www.enterprisedb.com



pgsql-hackers by date:

Previous
From: Andrew Dunstan
Date:
Subject: Re: SQL/JSON: functions
Next
From: Robert Haas
Date:
Subject: Re: RecoveryInProgress() has critical side effects