]> granicus.if.org Git - postgresql/commitdiff
Dept of second thoughts: the !scan_all exit mustn't increase scanned_pages.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Dec 2015 22:32:23 +0000 (17:32 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 30 Dec 2015 22:32:23 +0000 (17:32 -0500)
In the extreme edge case where contended pages are the only ones that
escape being scanned, the previous commit would have allowed us to think
that relfrozenxid could be advanced, which is exactly wrong.

src/backend/commands/vacuumlazy.c

index a93d4a1f23823c03dc0a1c69e788819126b414a6..2a8cab746a943e5712782d30434ef3d836d6a90c 100644 (file)
@@ -666,7 +666,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                         * to use lazy_check_needs_freeze() for both situations, though.
                         */
                        LockBuffer(buf, BUFFER_LOCK_SHARE);
-                       if (!lazy_check_needs_freeze(buf, &hastup) || !scan_all)
+                       if (!lazy_check_needs_freeze(buf, &hastup))
                        {
                                UnlockReleaseBuffer(buf);
                                vacrelstats->scanned_pages++;
@@ -675,6 +675,18 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                                        vacrelstats->nonempty_pages = blkno + 1;
                                continue;
                        }
+                       if (!scan_all)
+                       {
+                               /*
+                                * Here, we must not advance scanned_pages; that would amount
+                                * to claiming that the page contains no freezable tuples.
+                                */
+                               UnlockReleaseBuffer(buf);
+                               vacrelstats->pinskipped_pages++;
+                               if (hastup)
+                                       vacrelstats->nonempty_pages = blkno + 1;
+                               continue;
+                       }
                        LockBuffer(buf, BUFFER_LOCK_UNLOCK);
                        LockBufferForCleanup(buf);
                        /* drop through to normal processing */