From 9caa8fc8a10ad65fe0f1fb5ec9a6c3e42668d9f6 Mon Sep 17 00:00:00 2001
From: "duankunren.dkr" <duankunren.dkr@alibaba-inc.com>
Date: Thu, 19 Mar 2026 23:19:19 +0800
Subject: [PATCH] Sleep injection for multixact compat logic bug reproduction

Inject a 60s sleep in MultiXactIdCreateFromMembers() between
GetNewMultiXactId() and XLogInsert(CREATE_ID), triggered when
the allocated multi is the last entry on an offset page (entry 2047).

This creates a deterministic window where CHECKPOINT can capture
nextMulti=N+1 while CREATE_ID:N has not yet been written to WAL,
reproducing the WAL disorder that triggers the compat logic bug
in commit 8ba61bc0638.

Apply to REL_16_11 (or any unpatched minor version) to build the
primary for the reproduction test.
---
 src/backend/access/transam/multixact.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 3a2d7055c42..cb3f8f207ae 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -822,6 +822,21 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
 	 */
 	multi = GetNewMultiXactId(nmembers, &offset);
 
+
+	/*
+	 * BUG REPRODUCTION: Sleep 60s before writing CREATE_ID WAL when
+	 * this multi is the last entry on its offset page (entry 2047).
+	 * Only activates when /tmp/mxact_sleep_enabled exists, so the
+	 * batch phase can advance multixacts without hitting the sleep.
+	 */
+	if (MultiXactIdToOffsetEntry(multi) == MULTIXACT_OFFSETS_PER_PAGE - 1 &&
+		access("/tmp/mxact_sleep_enabled", F_OK) == 0)
+	{
+		elog(LOG, "MXACT_DELAY: multi=%u is last entry on page %d, sleeping 60s",
+			 multi, MultiXactIdToOffsetPage(multi));
+		pg_usleep(60000000L);
+		elog(LOG, "MXACT_DELAY: multi=%u woke up, writing CREATE_ID now", multi);
+	}
 	/* Make an XLOG entry describing the new MXID. */
 	xlrec.mid = multi;
 	xlrec.moff = offset;
-- 
2.32.0.3.g01195cf9f

