Keep shared-memory copy of ThisTimeLineID in sync at all times.
authorRobert Haas <[email protected]>
Wed, 27 Oct 2021 16:56:34 +0000 (12:56 -0400)
committerRobert Haas <[email protected]>
Thu, 28 Oct 2021 18:55:18 +0000 (14:55 -0400)
Previously, the startup process set the global variable ThisTimeLineID
for each record replayed, while leaving the corresponding shared-memory
variable uninitialized. Now, XLogCtl->ThisTimeLineID is always
the same as ThisTimeLineID, and XLogCtl->PrevTimeLineID is also
the same unless a promotion has occurred since server startup.

src/backend/access/transam/xlog.c

index f547efd2944172ea7c2258006dfa5436d0088e7d..c94ddd3756dd147fdf89196e762c071ef143e128 100644 (file)
@@ -634,9 +634,19 @@ typedef struct XLogCtlData
 
        /*
         * Shared copy of ThisTimeLineID. Does not change after end-of-recovery.
-        * If we created a new timeline when the system was started up,
-        * PrevTimeLineID is the old timeline's ID that we forked off from.
-        * Otherwise it's equal to ThisTimeLineID.
+        *
+        * During recovery, ThisTimeLineID and PrevTimeLineID both hold the
+        * timeline of the last record we replayed; they will always be equal.
+        *
+        * At the end of recovery, if we create a new time line, ThisTimeLineID
+        * will be set to the newly-created timeline, and PrevTimeLineID will be
+        * the timeline from which it branched off. If we do not create a new
+        * timeline, ThisTimeLineID will be equal to PrevTimeLineID, and both
+        * will be equal either to the timeline of the last WAL record we replayed,
+        * or the timeline in the checkpoint from which we started up.
+        *
+        * At any point when it's possible to insert new WAL, ThisTimeLineID is
+        * always the timeline that should be used to do that.
         */
        TimeLineID      ThisTimeLineID;
        TimeLineID      PrevTimeLineID;
@@ -6627,7 +6637,6 @@ StartupXLOG(void)
                                checkPointLoc,
                                EndOfLog;
        TimeLineID      EndOfLogTLI;
-       TimeLineID      PrevTimeLineID;
        XLogRecord *record;
        TransactionId oldestActiveXID;
        bool            backupEndRequired = false;
@@ -7140,9 +7149,11 @@ StartupXLOG(void)
        /*
         * We must replay WAL entries using the same TimeLineID they were created
         * under, so temporarily adopt the TLI indicated by the checkpoint (see
-        * also xlog_redo()).
+        * also xlog_redo()). Update shared memory, too.
         */
        ThisTimeLineID = checkPoint.ThisTimeLineID;
+       XLogCtl->ThisTimeLineID = ThisTimeLineID;
+       XLogCtl->PrevTimeLineID = ThisTimeLineID;
 
        /*
         * Copy any missing timeline history files between 'now' and the recovery
@@ -7628,6 +7639,8 @@ StartupXLOG(void)
 
                                                /* Following WAL records should be run with new TLI */
                                                ThisTimeLineID = newTLI;
+                                               XLogCtl->ThisTimeLineID = ThisTimeLineID;
+                                               XLogCtl->PrevTimeLineID = ThisTimeLineID;
                                                switchedTLI = true;
                                        }
                                }
@@ -7917,7 +7930,6 @@ StartupXLOG(void)
         *
         * In a normal crash recovery, we can just extend the timeline we were in.
         */
-       PrevTimeLineID = ThisTimeLineID;
        if (ArchiveRecoveryRequested)
        {
                char       *reason;
@@ -7926,6 +7938,7 @@ StartupXLOG(void)
                Assert(InArchiveRecovery);
 
                ThisTimeLineID = findNewestTimeLine(recoveryTargetTLI) + 1;
+               XLogCtl->ThisTimeLineID = ThisTimeLineID;
                ereport(LOG,
                                (errmsg("selected new timeline ID: %u", ThisTimeLineID)));
 
@@ -7964,10 +7977,6 @@ StartupXLOG(void)
                unlink(recoveryPath);   /* ignore any error */
        }
 
-       /* Save the selected TimeLineID in shared memory, too */
-       XLogCtl->ThisTimeLineID = ThisTimeLineID;
-       XLogCtl->PrevTimeLineID = PrevTimeLineID;
-
        /*
         * Actually, if WAL ended in an incomplete record, skip the parts that
         * made it through and start writing after the portion that persisted.