diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c
index 424624cf0d..d0986a59de 100644
--- a/src/backend/utils/cache/relmapper.c
+++ b/src/backend/utils/cache/relmapper.c
@@ -136,7 +136,7 @@ static void apply_map_update(RelMapFile *map, Oid relationId, Oid fileNode,
 							 bool add_okay);
 static void merge_map_updates(RelMapFile *map, const RelMapFile *updates,
 							  bool add_okay);
-static void load_relmap_file(bool shared);
+static void load_relmap_file(bool shared, bool lock_held);
 static void write_relmap_file(bool shared, RelMapFile *newmap,
 							  bool write_wal, bool send_sinval, bool preserve_files,
 							  Oid dbid, Oid tsid, const char *dbpath);
@@ -405,12 +405,12 @@ RelationMapInvalidate(bool shared)
 	if (shared)
 	{
 		if (shared_map.magic == RELMAPPER_FILEMAGIC)
-			load_relmap_file(true);
+			load_relmap_file(true, false);
 	}
 	else
 	{
 		if (local_map.magic == RELMAPPER_FILEMAGIC)
-			load_relmap_file(false);
+			load_relmap_file(false, false);
 	}
 }
 
@@ -425,9 +425,9 @@ void
 RelationMapInvalidateAll(void)
 {
 	if (shared_map.magic == RELMAPPER_FILEMAGIC)
-		load_relmap_file(true);
+		load_relmap_file(true, false);
 	if (local_map.magic == RELMAPPER_FILEMAGIC)
-		load_relmap_file(false);
+		load_relmap_file(false, false);
 }
 
 /*
@@ -612,7 +612,7 @@ RelationMapInitializePhase2(void)
 	/*
 	 * Load the shared map file, die on error.
 	 */
-	load_relmap_file(true);
+	load_relmap_file(true, false);
 }
 
 /*
@@ -633,7 +633,7 @@ RelationMapInitializePhase3(void)
 	/*
 	 * Load the local map file, die on error.
 	 */
-	load_relmap_file(false);
+	load_relmap_file(false, false);
 }
 
 /*
@@ -695,7 +695,7 @@ RestoreRelationMap(char *startAddress)
  * Note that the local case requires DatabasePath to be set up.
  */
 static void
-load_relmap_file(bool shared)
+load_relmap_file(bool shared, bool lock_held)
 {
 	RelMapFile *map;
 	char		mapfilename[MAXPGPATH];
@@ -725,12 +725,18 @@ load_relmap_file(bool shared)
 						mapfilename)));
 
 	/*
-	 * Note: we could take RelationMappingLock in shared mode here, but it
-	 * seems unnecessary since our read() should be atomic against any
-	 * concurrent updater's write().  If the file is updated shortly after we
-	 * look, the sinval signaling mechanism will make us re-read it before we
-	 * are able to access any relation that's affected by the change.
+	 * Grab the lock to prevent the file from being updated while we read it,
+	 * unless the caller is already holding the lock.  This shouldn't be
+	 * necessary. The file is small so the read() should be atomic against any
+	 * concurrent updater's write().  But better safe than sorry.
+	 *
+	 * If the file is updated shortly after we look, the sinval signaling
+	 * mechanism will make us re-read it before we are able to access any
+	 * relation that's affected by the change.
 	 */
+	if (!lock_held)
+		LWLockAcquire(RelationMappingLock, LW_SHARED);
+
 	pgstat_report_wait_start(WAIT_EVENT_RELATION_MAP_READ);
 	r = read(fd, map, sizeof(RelMapFile));
 	if (r != sizeof(RelMapFile))
@@ -747,6 +753,9 @@ load_relmap_file(bool shared)
 	}
 	pgstat_report_wait_end();
 
+	if (!lock_held)
+		LWLockRelease(RelationMappingLock);
+
 	if (CloseTransientFile(fd) != 0)
 		ereport(FATAL,
 				(errcode_for_file_access(),
@@ -969,7 +978,7 @@ perform_relmap_update(bool shared, const RelMapFile *updates)
 	LWLockAcquire(RelationMappingLock, LW_EXCLUSIVE);
 
 	/* Be certain we see any other updates just made */
-	load_relmap_file(shared);
+	load_relmap_file(shared, true);
 
 	/* Prepare updated data in a local variable */
 	if (shared)
