]> granicus.if.org Git - postgresql/commitdiff
Fix DetermineSafeOldestOffset for the case where there are no mxacts.
authorRobert Haas <rhaas@postgresql.org>
Mon, 11 May 2015 01:34:26 +0000 (21:34 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 11 May 2015 01:47:28 +0000 (21:47 -0400)
Commit b69bf30b9bfacafc733a9ba77c9587cf54d06c0c failed to take into
account the possibility that there might be no multixacts in existence
at all.

Report by Thomas Munro; patch by me.

src/backend/access/transam/multixact.c

index 031641e3241dc9080bbe49b74153de18ea35ec15..7ec7f525d1e7a1c24281c567c191b668fa00cf14 100644 (file)
@@ -2511,13 +2511,24 @@ DetermineSafeOldestOffset(MultiXactId oldestMXact)
                return;
 
        /*
-        * We determine the safe upper bound for offsets of new xacts by reading
-        * the offset of the oldest multixact, and going back one segment.  This
-        * way, the sequence of multixact member segments will always have a
-        * one-segment hole at a minimum.  We start spewing warnings a few
-        * complete segments before that.
+        * Determine the offset of the oldest multixact.  Normally, we can read
+        * the offset from the multixact itself, but there's an important special
+        * case: if there are no multixacts in existence at all, oldestMXact
+        * obviously can't point to one.  It will instead point to the multixact
+        * ID that will be assigned the next time one is needed.
         */
-       oldestOffset = find_multixact_start(oldestMXact);
+       LWLockAcquire(MultiXactGenLock, LW_SHARED);
+       if (MultiXactState->nextMXact == oldestMXact)
+       {
+               oldestOffset = MultiXactState->nextOffset;
+               LWLockRelease(MultiXactGenLock);
+       }
+       else
+       {
+               LWLockRelease(MultiXactGenLock);
+               oldestOffset = find_multixact_start(oldestMXact);
+       }
+
        /* move back to start of the corresponding segment */
        oldestOffset -= oldestOffset %
                (MULTIXACT_MEMBERS_PER_PAGE * SLRU_PAGES_PER_SEGMENT);