From 505095e742d180f5316ad60de3be21657480f140 Mon Sep 17 00:00:00 2001
From: shihao zhong <zhong950419@gmail.com>
Date: Wed, 28 Oct 2026 23:12:31 -0400
Subject: [PATCH 1/2] Delay checkpoint start while creating a multixact

A checkpoint starting between the CREATE_ID record and the SLRU update
could lose the multixact after a crash.

Backpatch-through: 14
---
 src/backend/access/transam/multixact.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 4d5fd9f8eb2..e75c5238295 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -774,6 +774,16 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
 
 	INJECTION_POINT_CACHED("multixact-create-from-members", NULL);
 
+	/*
+	 * Prevent checkpoints from starting between the WAL record and the update
+	 * of the OFFSETs and MEMBERs pages.  Otherwise the checkpoint could flush
+	 * the pages before they hold the new multixact, while recovery after a
+	 * crash would begin after the WAL record, and the multixact would be lost
+	 * even though data pages might already refer to it.
+	 */
+	Assert((MyProc->delayChkptFlags & DELAY_CHKPT_START) == 0);
+	MyProc->delayChkptFlags |= DELAY_CHKPT_START;
+
 	/* Make an XLOG entry describing the new MXID. */
 	xlrec.mid = multi;
 	xlrec.moff = offset;
@@ -794,6 +804,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
 	/* Now enter the information into the OFFSETs and MEMBERs logs */
 	RecordNewMultiXact(multi, offset, nmembers, members);
 
+	MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
+
 	/* Done with critical section */
 	END_CRIT_SECTION();
 
-- 
2.37.1 (Apple Git-137.1)

