aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/utils/cache/relcache.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index dfc758c1695..d0234a26d03 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -2104,11 +2104,11 @@ RelationCacheInvalidateEntry(Oid relationId)
* so hash_seq_search will complete safely; (b) during the second pass we
* only hold onto pointers to nondeletable entries.
*
- * The two-phase approach also makes it easy to ensure that we process
- * nailed-in-cache indexes before other nondeletable items, and that we
- * process pg_class_oid_index first of all. In scenarios where a nailed
- * index has been given a new relfilenode, we have to detect that update
- * before the nailed index is used in reloading any other relcache entry.
+ * The two-phase approach also makes it easy to update relfilenodes for
+ * mapped relations before we do anything else, and to ensure that the
+ * second pass processes nailed-in-cache items before other nondeletable
+ * items. This should ensure that system catalogs are up to date before
+ * we attempt to use them to reload information about other open relations.
*/
void
RelationCacheInvalidate(void)
@@ -2120,6 +2120,11 @@ RelationCacheInvalidate(void)
List *rebuildList = NIL;
ListCell *l;
+ /*
+ * Reload relation mapping data before starting to reconstruct cache.
+ */
+ RelationMapInvalidateAll();
+
/* Phase 1 */
hash_seq_init(&status, RelationIdCache);
@@ -2130,7 +2135,7 @@ RelationCacheInvalidate(void)
/* Must close all smgr references to avoid leaving dangling ptrs */
RelationCloseSmgr(relation);
- /* Ignore new relations, since they are never SI targets */
+ /* Ignore new relations, since they are never cross-backend targets */
if (relation->rd_createSubid != InvalidSubTransactionId)
continue;
@@ -2145,21 +2150,32 @@ RelationCacheInvalidate(void)
else
{
/*
+ * If it's a mapped relation, immediately update its rd_node in
+ * case its relfilenode changed. We must do this during phase 1
+ * in case the relation is consulted during rebuild of other
+ * relcache entries in phase 2. It's safe since consulting the
+ * map doesn't involve any access to relcache entries.
+ */
+ if (RelationIsMapped(relation))
+ RelationInitPhysicalAddr(relation);
+
+ /*
* Add this entry to list of stuff to rebuild in second pass.
- * pg_class_oid_index goes on the front of rebuildFirstList, other
- * nailed indexes on the back, and everything else into
- * rebuildList (in no particular order).
+ * pg_class goes to the front of rebuildFirstList while
+ * pg_class_oid_index goes to the back of rebuildFirstList, so
+ * they are done first and second respectively. Other nailed
+ * relations go to the front of rebuildList, so they'll be done
+ * next in no particular order; and everything else goes to the
+ * back of rebuildList.
*/
- if (relation->rd_isnailed &&
- relation->rd_rel->relkind == RELKIND_INDEX)
- {
- if (RelationGetRelid(relation) == ClassOidIndexId)
- rebuildFirstList = lcons(relation, rebuildFirstList);
- else
- rebuildFirstList = lappend(rebuildFirstList, relation);
- }
- else
+ if (RelationGetRelid(relation) == RelationRelationId)
+ rebuildFirstList = lcons(relation, rebuildFirstList);
+ else if (RelationGetRelid(relation) == ClassOidIndexId)
+ rebuildFirstList = lappend(rebuildFirstList, relation);
+ else if (relation->rd_isnailed)
rebuildList = lcons(relation, rebuildList);
+ else
+ rebuildList = lappend(rebuildList, relation);
}
}
@@ -2170,11 +2186,6 @@ RelationCacheInvalidate(void)
*/
smgrcloseall();
- /*
- * Reload relation mapping data before starting to reconstruct cache.
- */
- RelationMapInvalidateAll();
-
/* Phase 2: rebuild the items found to need rebuild in phase 1 */
foreach(l, rebuildFirstList)
{