demo.diff

application/octet-stream

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index f825579e888..8899d5ac63d 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -888,8 +888,6 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 	MultiXactOffset *next_offptr;
 	MultiXactOffset next_offset;
 
-	LWLockAcquire(MultiXactOffsetSLRULock, LW_EXCLUSIVE);
-
 	/* position of this multixid in the offsets SLRU area  */
 	pageno = MultiXactIdToOffsetPage(multi);
 	entryno = MultiXactIdToOffsetEntry(multi);
@@ -907,6 +905,9 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 	 * multixid was assigned.  If we're replaying WAL that was generated by
 	 * such a version, the next page might not be initialized yet.  Initialize
 	 * it now.
+	 *
+	 * This block runs before acquiring MultiXactOffsetSLRULock because
+	 * SimpleLruWriteAll() needs to acquire the same lock internally.
 	 */
 	if (InRecovery && next_pageno != pageno)
 	{
@@ -951,6 +952,8 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 		{
 			elog(DEBUG1, "next offsets page is not initialized, initializing it now");
 
+			LWLockAcquire(MultiXactOffsetSLRULock, LW_EXCLUSIVE);
+
 			/* Create and zero the page */
 			slotno = SimpleLruZeroPage(MultiXactOffsetCtl, next_pageno);
 
@@ -958,6 +961,8 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 			SimpleLruWritePage(MultiXactOffsetCtl, slotno);
 			Assert(!MultiXactOffsetCtl->shared->page_dirty[slotno]);
 
+			LWLockRelease(MultiXactOffsetSLRULock);
+
 			/*
 			 * Remember that we initialized the page, so that we don't zero it
 			 * again at the XLOG_MULTIXACT_ZERO_OFF_PAGE record.
@@ -967,6 +972,8 @@ RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset,
 		}
 	}
 
+	LWLockAcquire(MultiXactOffsetSLRULock, LW_EXCLUSIVE);
+
 	/*
 	 * Set the starting offset of this multixid's members.
 	 *