On Tue, Nov 30, 2021 at 7:50 PM Andy Fan <zhihui.fan1...@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