*** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** *** 190,198 **** static const int MultiXactStatusLock[MaxMultiXactStatus + 1] = /* Get the LockTupleMode for a given MultiXactStatus */ #define TUPLOCK_from_mxstatus(status) \ (MultiXactStatusLock[(status)]) - /* Get the is_update bit for a given MultiXactStatus */ - #define ISUPDATE_from_mxstatus(status) \ - ((status) > MultiXactStatusForUpdate) /* ---------------------------------------------------------------- * heap support routines --- 190,195 ---- *** a/src/backend/access/transam/multixact.c --- b/src/backend/access/transam/multixact.c *************** *** 457,463 **** MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) for (i = 0, j = 0; i < nmembers; i++) { if (TransactionIdIsInProgress(members[i].xid) || ! ((members[i].status > MultiXactStatusForUpdate) && TransactionIdDidCommit(members[i].xid))) { newMembers[j].xid = members[i].xid; --- 457,463 ---- for (i = 0, j = 0; i < nmembers; i++) { if (TransactionIdIsInProgress(members[i].xid) || ! (ISUPDATE_from_mxstatus(members[i].status) && TransactionIdDidCommit(members[i].xid))) { newMembers[j].xid = members[i].xid; *************** *** 713,718 **** MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) --- 713,734 ---- return multi; } + /* Verify that there is a single update Xid among the given members. */ + { + int i; + bool has_update = false; + + for (i = 0; i < nmembers; i++) + { + if (ISUPDATE_from_mxstatus(members[i].status)) + { + if (has_update) + elog(ERROR, "new multixact has more than one updating member"); + has_update = true; + } + } + } + /* * Assign the MXID and offsets range to use, and make sure there is space * in the OFFSETs and MEMBERs files. NB: this routine does *** a/src/include/access/multixact.h --- b/src/include/access/multixact.h *************** *** 48,53 **** typedef enum --- 48,57 ---- #define MaxMultiXactStatus MultiXactStatusUpdate + /* does a status value correspond to a tuple update? */ + #define ISUPDATE_from_mxstatus(status) \ + ((status) > MultiXactStatusForUpdate) + typedef struct MultiXactMember {