Don't set reachedMinRecoveryPoint during crash recovery. In crash recovery,
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 9 Dec 2011 12:32:42 +0000 (14:32 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 9 Dec 2011 13:21:12 +0000 (15:21 +0200)
we don't reach consistency before replaying all of the WAL. Rename the
variable to reachedConsistency, to make its intention clearer.

In master, that was an active bug because of the recent patch to
immediately PANIC if a reference to a missing page is found in WAL after
reaching consistency, as Tom Lane's test case demonstrated. In 9.1 and 9.0,
the only consequence was a misleading "consistent recovery state reached at
%X/%X" message in the log at the beginning of crash recovery (the database
is not consistent at that point yet). In 8.4, the log message was not
printed in crash recovery, even though there was a similar
reachedMinRecoveryPoint local variable that was also set early. So,
backpatch to 9.1 and 9.0.

src/backend/access/transam/xlog.c
src/backend/access/transam/xlogutils.c
src/include/access/xlog.h

index 9bec6609921842c3edfe21dc7e25bf866e35e669..9d96044cbdc48828e3f1d057582174f8576ce05d 100644 (file)
@@ -562,7 +562,13 @@ static TimeLineID lastPageTLI = 0;
 static XLogRecPtr minRecoveryPoint;        /* local copy of
                                         * ControlFile->minRecoveryPoint */
 static bool updateMinRecoveryPoint = true;
-bool reachedMinRecoveryPoint = false;
+
+/*
+ * Have we reached a consistent database state? In crash recovery, we have
+ * to replay all the WAL, so reachedConsistency is never set. During archive
+ * recovery, the database is consistent once minRecoveryPoint is reached.
+ */
+bool reachedConsistency = false;
 
 static bool InRedo = false;
 
@@ -6893,10 +6899,17 @@ StartupXLOG(void)
 static void
 CheckRecoveryConsistency(void)
 {
+   /*
+    * During crash recovery, we don't reach a consistent state until we've
+    * replayed all the WAL.
+    */
+   if (XLogRecPtrIsInvalid(minRecoveryPoint))
+       return;
+
    /*
     * Have we passed our safe starting point?
     */
-   if (!reachedMinRecoveryPoint &&
+   if (!reachedConsistency &&
        XLByteLE(minRecoveryPoint, EndRecPtr) &&
        XLogRecPtrIsInvalid(ControlFile->backupStartPoint))
    {
@@ -6906,7 +6919,7 @@ CheckRecoveryConsistency(void)
         */
        XLogCheckInvalidPages();
 
-       reachedMinRecoveryPoint = true;
+       reachedConsistency = true;
        ereport(LOG,
                (errmsg("consistent recovery state reached at %X/%X",
                        EndRecPtr.xlogid, EndRecPtr.xrecoff)));
@@ -6919,7 +6932,7 @@ CheckRecoveryConsistency(void)
     */
    if (standbyState == STANDBY_SNAPSHOT_READY &&
        !LocalHotStandbyActive &&
-       reachedMinRecoveryPoint &&
+       reachedConsistency &&
        IsUnderPostmaster)
    {
        /* use volatile pointer to prevent code rearrangement */
index 350d434562a1d91ea0da96a8973678a918bc9b4a..b280434a82969dfc4f2a3b00b22f7e4cec5304e0 100644 (file)
@@ -85,7 +85,7 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
     * linger in the hash table until the end of recovery and PANIC there,
     * which might come only much later if this is a standby server.
     */
-   if (reachedMinRecoveryPoint)
+   if (reachedConsistency)
    {
        report_invalid_page(WARNING, node, forkno, blkno, present);
        elog(PANIC, "WAL contains references to invalid pages");
index 1fb56cdfd543c33b15ea155dc32329e948ef96ad..1b31414060de8c0217cc7671c30f0209e4ea12d3 100644 (file)
@@ -190,7 +190,7 @@ typedef enum
 
 extern XLogRecPtr XactLastRecEnd;
 
-extern bool reachedMinRecoveryPoint;
+extern bool reachedConsistency;
 
 /* these variables are GUC parameters related to XLOG */
 extern int CheckPointSegments;