]> granicus.if.org Git - postgresql/commitdiff
Maintain ThisTimeLineID correctly in checkpointer
authorSimon Riggs <simon@2ndQuadrant.com>
Tue, 21 May 2013 20:17:04 +0000 (21:17 +0100)
committerSimon Riggs <simon@2ndQuadrant.com>
Tue, 21 May 2013 20:17:04 +0000 (21:17 +0100)
checkpointer needs to reset ThisTimeLineID after
a restartpoint to allow installing/recycling new
WAL files. If recovery has already ended this
would leave ThisTimeLineID set incorrectly and
so we must reset it otherwise later checkpoints
do not have the correct timeline.

Bug report by Heikki Linnakangas.
Further investigation by Heikki and myself.

src/backend/access/transam/xlog.c

index 7d34218bef09ef6eb0b42b8dfb966b43c900d7ce..3950a02667989946e08f50d4c733fa5e69c709f2 100644 (file)
@@ -5970,6 +5970,17 @@ StartupXLOG(void)
                                if (record != NULL)
                                {
                                        fast_promoted = true;
+
+                                       /*
+                                        * Insert a special WAL record to mark the end of recovery,
+                                        * since we aren't doing a checkpoint. That means that the
+                                        * checkpointer process may likely be in the middle of a
+                                        * time-smoothed restartpoint and could continue to be for
+                                        * minutes after this. That sounds strange, but the effect
+                                        * is roughly the same and it would be stranger to try to
+                                        * come out of the restartpoint and then checkpoint.
+                                        * We request a checkpoint later anyway, just for safety.
+                                        */
                                        CreateEndOfRecoveryRecord();
                                }
                        }
@@ -7465,7 +7476,16 @@ CreateRestartPoint(int flags)
                 * after this, the pre-allocated WAL segments on this timeline will
                 * not be used, and will go wasted until recycled on the next
                 * restartpoint. We'll live with that.
+                *
+                * It's possible or perhaps even likely that we finish recovery while
+                * a restartpoint is in progress. That means we may get to this point
+                * some minutes afterwards. Setting ThisTimeLineID at that time would
+                * actually set it backwards, so we don't want that to persist; if
+                * we do reset it here, make sure to reset it back afterwards. This
+                * doesn't look very clean or principled, but its the best of about
+                * five different ways of handling this edge case.
                 */
+               if (RecoveryInProgress())
                (void) GetXLogReplayRecPtr(&ThisTimeLineID);
 
                RemoveOldXlogFiles(_logSegNo, endptr);
@@ -7475,6 +7495,12 @@ CreateRestartPoint(int flags)
                 * segments, since that may supply some of the needed files.)
                 */
                PreallocXlogFiles(endptr);
+
+               /*
+                * Reset this always, in case we set ThisTimeLineID backwards above.
+                * Requires no locking; see InitXLOGAccess()
+                */
+               ThisTimeLineID = XLogCtl->ThisTimeLineID;
        }
 
        /*