diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 9da22c8bdfc49e3318283d19f529f919b0e153f7..2cdfed4945eb1e2eef0d0ec74eb28fd439c3b6f4 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -133,6 +133,19 @@
 #define MULTIXACT_MEMBERS_PER_PAGE	\
 	(MULTIXACT_MEMBERGROUPS_PER_PAGE * MULTIXACT_MEMBERS_PER_MEMBERGROUP)
 
+/*
+ * Because the number of items per page is not a divisor of the last item
+ * number (member 0xFFFFFFFF), the last segment does not use the maximum number
+ * of pages, and moreover the last used page therein does not use the same
+ * number of items as previous pages.  (Another way to say it is that the
+ * 0xFFFFFFFF member is somewhere in the middle of the last page, so the page
+ * has some empty space after that item.)
+ *
+ * This constant is the number of members in the last page of the last segment.
+ */
+#define MAX_MEMBERS_IN_LAST_MEMBERS_PAGE \
+		((uint32) ((0xFFFFFFFF % MULTIXACT_MEMBERS_PER_PAGE) + 1))
+
 /* page in which a member is to be found */
 #define MXOffsetToMemberPage(xid) ((xid) / (TransactionId) MULTIXACT_MEMBERS_PER_PAGE)
 
@@ -2278,6 +2291,7 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 	{
 		int			flagsoff;
 		int			flagsbit;
+		uint32		difference;
 
 		/*
 		 * Only zero when at first entry of a page.
@@ -2299,24 +2313,29 @@ ExtendMultiXactMember(MultiXactOffset offset, int nmembers)
 		}
 
 		/*
-		 * Advance to next page, taking care to properly handle the wraparound
-		 * case.  OK if nmembers goes negative.
+		 * Compute the number of items till end of current page.  Careful: if
+		 * addition of unsigned ints wraps around, we're at the last page of
+		 * the last segment; since that page holds a different number of items
+		 * than other pages, we need to do it differently.
 		 */
-		if ((unsigned int) (offset + nmembers) < offset)
+		if (offset + MAX_MEMBERS_IN_LAST_MEMBERS_PAGE < offset)
 		{
-			uint32		difference = offset + MULTIXACT_MEMBERS_PER_PAGE;
-
-			nmembers -= (unsigned int) (MULTIXACT_MEMBERS_PER_PAGE - difference);
-			offset = 0;
+			/*
+			 * This is the last page of the last segment; we can compute the
+			 * number of items left to allocate in it without modulo
+			 * arithmetic.
+			 */
+			difference = MaxMultiXactOffset - offset + 1;
 		}
 		else
-		{
-			int			difference;
-
 			difference = MULTIXACT_MEMBERS_PER_PAGE - offset % MULTIXACT_MEMBERS_PER_PAGE;
-			nmembers -= difference;
-			offset += difference;
-		}
+
+		/*
+		 * Advance to next page, taking care to properly handle the wraparound
+		 * case.  OK if nmembers goes negative.
+		 */
+		nmembers -= difference;
+		offset += difference;
 	}
 }
 
diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h
index 1f048e8ed5d43c8717fda85cd83f46208dd6142f..80c70748cf202e9e36ab289fa7ea229ec13d2db9 100644
--- a/src/include/access/multixact.h
+++ b/src/include/access/multixact.h
@@ -25,6 +25,8 @@
 
 #define MultiXactIdIsValid(multi) ((multi) != InvalidMultiXactId)
 
+#define MaxMultiXactOffset	((MultiXactOffset) 0xFFFFFFFF)
+
 /* Number of SLRU buffers to use for multixact */
 #define NUM_MXACTOFFSET_BUFFERS		8
 #define NUM_MXACTMEMBER_BUFFERS		16