Fix corner case in autovacuum-forcing logic for multixact wraparound.
authorRobert Haas <rhaas@postgresql.org>
Fri, 19 Jun 2015 15:28:30 +0000 (11:28 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 19 Jun 2015 15:38:46 +0000 (11:38 -0400)
Since find_multixact_start() relies on SimpleLruDoesPhysicalPageExist(),
and that function looks only at the on-disk state, it's possible for it
to fail to find a page that exists in the in-memory SLRU that has not
been written yet.  If that happens, SetOffsetVacuumLimit() will
erroneously decide to force emergency autovacuuming immediately.

We should probably fix find_multixact_start() to consider the data
cached in memory as well as on the on-disk state, but that's no excuse
for SetOffsetVacuumLimit() to be stupid about the case where it can
no longer read the value after having previously succeeded in doing so.

Report by Andres Freund.

src/backend/access/transam/multixact.c

index 0fea40cccbb6670dffa365e90a7b14af24ceae30..5c25c2f67404185d050a0c737a05d3524d0f70e4 100644 (file)
@@ -2680,6 +2680,18 @@ SetOffsetVacuumLimit(bool finish_setup)
                    (errmsg("oldest MultiXactId member offset unknown")));
    }
 
+   /*
+    * If we failed to get the oldest offset this time, but we have a value
+    * from a previous pass through this function, assess the need for
+    * autovacuum based on that old value rather than automatically forcing
+    * it.
+    */
+   if (prevOldestOffsetKnown && !oldestOffsetKnown)
+   {
+       oldestOffset = prevOldestOffset;
+       oldestOffsetKnown = true;
+   }
+
    /*
     * Do we need an emergency autovacuum?  If we're not sure, assume yes.
     */