From 9caa8fc8a10ad65fe0f1fb5ec9a6c3e42668d9f6 Mon Sep 17 00:00:00 2001 From: "duankunren.dkr" 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