]> granicus.if.org Git - postgresql/commitdiff
Truncate the predicate lock SLRU to empty, instead of almost empty.
authorRobert Haas <rhaas@postgresql.org>
Fri, 8 Apr 2011 20:51:45 +0000 (16:51 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 8 Apr 2011 20:52:19 +0000 (16:52 -0400)
Otherwise, the SLRU machinery can get confused and think that the SLRU
has wrapped around.  Along the way, regardless of whether we're
truncating all of the SLRU or just some of it, flush pages after
truncating, rather than before.

Kevin Grittner

src/backend/storage/lmgr/predicate.c

index 11dede9e70b8805635a98f8def33ffd4caf89177..7978bef996ded620a43b68ee6051d7ae330f0168 100644 (file)
@@ -920,26 +920,38 @@ CheckPointPredicate(void)
        else
        {
                /*
-                * The SLRU is no longer needed. Truncate everything but the last
-                * page. We don't dare to touch the last page in case the SLRU is
-                * taken back to use, and the new tail falls on the same page.
+                * The SLRU is no longer needed. Truncate everything.  If we try to
+                * leave the head page around to avoid re-zeroing it, we might not
+                * use the SLRU again until we're past the wrap-around point, which
+                * makes SLRU unhappy.
+                *
+                * While the API asks you to specify truncation by page, it silently
+                * ignores the request unless the specified page is in a segment
+                * past some allocated portion of the SLRU.  We don't care which
+                * page in a later segment we hit, so just add the number of pages
+                * per segment to the head page to land us *somewhere* in the next
+                * segment.
                 */
-               tailPage = oldSerXidControl->headPage;
+               tailPage = oldSerXidControl->headPage + SLRU_PAGES_PER_SEGMENT;
                oldSerXidControl->headPage = -1;
        }
 
        LWLockRelease(OldSerXidLock);
 
+       /* Truncate away pages that are no longer required */
+       SimpleLruTruncate(OldSerXidSlruCtl, tailPage);
+
        /*
         * Flush dirty SLRU pages to disk
         *
         * This is not actually necessary from a correctness point of view. We do
         * it merely as a debugging aid.
+        *
+        * We're doing this after the truncation to avoid writing pages right
+        * before deleting the file in which they sit, which would be completely
+        * pointless.
         */
        SimpleLruFlush(OldSerXidSlruCtl, true);
-
-       /* Truncate away pages that are no longer required */
-       SimpleLruTruncate(OldSerXidSlruCtl, tailPage);
 }
 
 /*------------------------------------------------------------------------*/