]> granicus.if.org Git - postgresql/commitdiff
Correct epoch of txid_current() when executed on a Hot Standby server.
authorSimon Riggs <simon@2ndQuadrant.com>
Thu, 29 Mar 2012 13:55:30 +0000 (14:55 +0100)
committerSimon Riggs <simon@2ndQuadrant.com>
Thu, 29 Mar 2012 13:55:30 +0000 (14:55 +0100)
Initialise ckptXidEpoch from starting checkpoint and maintain the correct
value as we roll forwards. This allows GetNextXidAndEpoch() to return the
correct epoch when executed during recovery. Backpatch to 9.0 when the
problem is first observable by a user.

Bug report from Daniel Farina

src/backend/access/transam/xlog.c

index ff7f521a1b1bb33b010221c0deef1a7ec8591266..d2680149f49b0273e1eb74d206da27c089b31307 100644 (file)
@@ -6320,6 +6320,10 @@ StartupXLOG(void)
                /* No need to hold ControlFileLock yet, we aren't up far enough */
                UpdateControlFile();
 
+               /* initialize shared-memory copy of latest checkpoint XID/epoch */
+               XLogCtl->ckptXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
+               XLogCtl->ckptXid = ControlFile->checkPointCopy.nextXid;
+
                /* initialize our local copy of minRecoveryPoint */
                minRecoveryPoint = ControlFile->minRecoveryPoint;
 
@@ -6915,10 +6919,6 @@ StartupXLOG(void)
        /* start the archive_timeout timer running */
        XLogCtl->Write.lastSegSwitchTime = (pg_time_t) time(NULL);
 
-       /* initialize shared-memory copy of latest checkpoint XID/epoch */
-       XLogCtl->ckptXidEpoch = ControlFile->checkPointCopy.nextXidEpoch;
-       XLogCtl->ckptXid = ControlFile->checkPointCopy.nextXid;
-
        /* also initialize latestCompletedXid, to nextXid - 1 */
        LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
        ShmemVariableCache->latestCompletedXid = ShmemVariableCache->nextXid;
@@ -8601,6 +8601,17 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
                ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch;
                ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
 
+               /* Update shared-memory copy of checkpoint XID/epoch */
+               {
+                       /* use volatile pointer to prevent code rearrangement */
+                       volatile XLogCtlData *xlogctl = XLogCtl;
+
+                       SpinLockAcquire(&xlogctl->info_lck);
+                       xlogctl->ckptXidEpoch = checkPoint.nextXidEpoch;
+                       xlogctl->ckptXid = checkPoint.nextXid;
+                       SpinLockRelease(&xlogctl->info_lck);
+               }
+
                /*
                 * TLI may change in a shutdown checkpoint, but it shouldn't decrease
                 */
@@ -8645,6 +8656,17 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
                ControlFile->checkPointCopy.nextXidEpoch = checkPoint.nextXidEpoch;
                ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
 
+               /* Update shared-memory copy of checkpoint XID/epoch */
+               {
+                       /* use volatile pointer to prevent code rearrangement */
+                       volatile XLogCtlData *xlogctl = XLogCtl;
+
+                       SpinLockAcquire(&xlogctl->info_lck);
+                       xlogctl->ckptXidEpoch = checkPoint.nextXidEpoch;
+                       xlogctl->ckptXid = checkPoint.nextXid;
+                       SpinLockRelease(&xlogctl->info_lck);
+               }
+
                /* TLI should not change in an on-line checkpoint */
                if (checkPoint.ThisTimeLineID != ThisTimeLineID)
                        ereport(PANIC,