From 505095e742d180f5316ad60de3be21657480f140 Mon Sep 17 00:00:00 2001 From: shihao zhong 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)