Commit 87716346 authored by Tom Lane's avatar Tom Lane

Don't set recoveryLastXTime when replaying a checkpoint --- that was a bogus

idea from the start since the variable is only meant to track commit/abort
events.  This patch reverts the logic around the variable to what it was in
8.4, except that the value is now kept in shared memory rather than a static
variable, so that it can be reported correctly by CreateRestartPoint (which is
executed in the bgwriter).
parent aceedd88
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.428 2010/07/03 20:43:57 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.429 2010/07/03 22:15:45 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -184,7 +184,6 @@ static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET; ...@@ -184,7 +184,6 @@ static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
static bool recoveryTargetInclusive = true; static bool recoveryTargetInclusive = true;
static TransactionId recoveryTargetXid; static TransactionId recoveryTargetXid;
static TimestampTz recoveryTargetTime; static TimestampTz recoveryTargetTime;
static TimestampTz recoveryLastXTime = 0;
/* options taken from recovery.conf for XLOG streaming */ /* options taken from recovery.conf for XLOG streaming */
static bool StandbyMode = false; static bool StandbyMode = false;
...@@ -403,10 +402,10 @@ typedef struct XLogCtlData ...@@ -403,10 +402,10 @@ typedef struct XLogCtlData
/* end+1 of the last record replayed (or being replayed) */ /* end+1 of the last record replayed (or being replayed) */
XLogRecPtr replayEndRecPtr; XLogRecPtr replayEndRecPtr;
/* timestamp of last record replayed (or being replayed) */
TimestampTz recoveryLastXTime;
/* end+1 of the last record replayed */ /* end+1 of the last record replayed */
XLogRecPtr recoveryLastRecPtr; XLogRecPtr recoveryLastRecPtr;
/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
TimestampTz recoveryLastXTime;
slock_t info_lck; /* locks shared variables shown above */ slock_t info_lck; /* locks shared variables shown above */
} XLogCtlData; } XLogCtlData;
...@@ -554,6 +553,8 @@ static void readRecoveryCommandFile(void); ...@@ -554,6 +553,8 @@ static void readRecoveryCommandFile(void);
static void exitArchiveRecovery(TimeLineID endTLI, static void exitArchiveRecovery(TimeLineID endTLI,
uint32 endLogId, uint32 endLogSeg); uint32 endLogId, uint32 endLogSeg);
static bool recoveryStopsHere(XLogRecord *record, bool *includeThis); static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
static void SetLatestXTime(TimestampTz xtime);
static TimestampTz GetLatestXTime(void);
static void CheckRequiredParameterValues(void); static void CheckRequiredParameterValues(void);
static void XLogReportParameters(void); static void XLogReportParameters(void);
static void LocalSetXLogInsertAllowed(void); static void LocalSetXLogInsertAllowed(void);
...@@ -5440,7 +5441,7 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) ...@@ -5440,7 +5441,7 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
* *includeThis is set TRUE if we should apply this record before stopping. * *includeThis is set TRUE if we should apply this record before stopping.
* *
* We also track the timestamp of the latest applied COMMIT/ABORT record * We also track the timestamp of the latest applied COMMIT/ABORT record
* in recoveryLastXTime, for logging purposes. * in XLogCtl->recoveryLastXTime, for logging purposes.
* Also, some information is saved in recoveryStopXid et al for use in * Also, some information is saved in recoveryStopXid et al for use in
* annotating the new timeline's history file. * annotating the new timeline's history file.
*/ */
...@@ -5452,43 +5453,22 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5452,43 +5453,22 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
TimestampTz recordXtime; TimestampTz recordXtime;
/* We only consider stopping at COMMIT or ABORT records */ /* We only consider stopping at COMMIT or ABORT records */
if (record->xl_rmid == RM_XACT_ID) if (record->xl_rmid != RM_XACT_ID)
return false;
record_info = record->xl_info & ~XLR_INFO_MASK;
if (record_info == XLOG_XACT_COMMIT)
{ {
record_info = record->xl_info & ~XLR_INFO_MASK; xl_xact_commit *recordXactCommitData;
if (record_info == XLOG_XACT_COMMIT)
{
xl_xact_commit *recordXactCommitData;
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record); recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
recordXtime = recordXactCommitData->xact_time; recordXtime = recordXactCommitData->xact_time;
}
else if (record_info == XLOG_XACT_ABORT)
{
xl_xact_abort *recordXactAbortData;
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
recordXtime = recordXactAbortData->xact_time;
}
else
return false;
} }
else if (record->xl_rmid == RM_XLOG_ID) else if (record_info == XLOG_XACT_ABORT)
{ {
record_info = record->xl_info & ~XLR_INFO_MASK; xl_xact_abort *recordXactAbortData;
if (record_info == XLOG_CHECKPOINT_SHUTDOWN ||
record_info == XLOG_CHECKPOINT_ONLINE)
{
CheckPoint checkPoint;
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
recoveryLastXTime = time_t_to_timestamptz(checkPoint.time); recordXtime = recordXactAbortData->xact_time;
}
/*
* We don't want to stop recovery on a checkpoint record, but we do
* want to update recoveryLastXTime. So return is unconditional.
*/
return false;
} }
else else
return false; return false;
...@@ -5496,7 +5476,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5496,7 +5476,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
/* Do we have a PITR target at all? */ /* Do we have a PITR target at all? */
if (recoveryTarget == RECOVERY_TARGET_UNSET) if (recoveryTarget == RECOVERY_TARGET_UNSET)
{ {
recoveryLastXTime = recordXtime; SetLatestXTime(recordXtime);
return false; return false;
} }
...@@ -5564,37 +5544,56 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) ...@@ -5564,37 +5544,56 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
} }
if (recoveryStopAfter) if (recoveryStopAfter)
recoveryLastXTime = recordXtime; SetLatestXTime(recordXtime);
} }
else else
recoveryLastXTime = recordXtime; SetLatestXTime(recordXtime);
return stopsHere; return stopsHere;
} }
/* /*
* Returns bool with current recovery mode, a global state. * Save timestamp of latest processed commit/abort record.
*
* We keep this in XLogCtl, not a simple static variable, so that it can be
* seen by processes other than the startup process. Note in particular
* that CreateRestartPoint is executed in the bgwriter.
*/ */
Datum static void
pg_is_in_recovery(PG_FUNCTION_ARGS) SetLatestXTime(TimestampTz xtime)
{ {
PG_RETURN_BOOL(RecoveryInProgress()); /* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
SpinLockAcquire(&xlogctl->info_lck);
xlogctl->recoveryLastXTime = xtime;
SpinLockRelease(&xlogctl->info_lck);
} }
/* /*
* Returns timestamp of last recovered commit/abort record. * Fetch timestamp of latest processed commit/abort record.
*/ */
static TimestampTz static TimestampTz
GetLatestXLogTime(void) GetLatestXTime(void)
{ {
/* use volatile pointer to prevent code rearrangement */ /* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl; volatile XLogCtlData *xlogctl = XLogCtl;
TimestampTz xtime;
SpinLockAcquire(&xlogctl->info_lck); SpinLockAcquire(&xlogctl->info_lck);
recoveryLastXTime = xlogctl->recoveryLastXTime; xtime = xlogctl->recoveryLastXTime;
SpinLockRelease(&xlogctl->info_lck); SpinLockRelease(&xlogctl->info_lck);
return recoveryLastXTime; return xtime;
}
/*
* Returns bool with current recovery mode, a global state.
*/
Datum
pg_is_in_recovery(PG_FUNCTION_ARGS)
{
PG_RETURN_BOOL(RecoveryInProgress());
} }
/* /*
...@@ -6078,7 +6077,8 @@ StartupXLOG(void) ...@@ -6078,7 +6077,8 @@ StartupXLOG(void)
} }
/* /*
* Initialize shared replayEndRecPtr and recoveryLastRecPtr. * Initialize shared replayEndRecPtr, recoveryLastRecPtr, and
* recoveryLastXTime.
* *
* This is slightly confusing if we're starting from an online * This is slightly confusing if we're starting from an online
* checkpoint; we've just read and replayed the chekpoint record, * checkpoint; we've just read and replayed the chekpoint record,
...@@ -6091,6 +6091,7 @@ StartupXLOG(void) ...@@ -6091,6 +6091,7 @@ StartupXLOG(void)
SpinLockAcquire(&xlogctl->info_lck); SpinLockAcquire(&xlogctl->info_lck);
xlogctl->replayEndRecPtr = ReadRecPtr; xlogctl->replayEndRecPtr = ReadRecPtr;
xlogctl->recoveryLastRecPtr = ReadRecPtr; xlogctl->recoveryLastRecPtr = ReadRecPtr;
xlogctl->recoveryLastXTime = 0;
SpinLockRelease(&xlogctl->info_lck); SpinLockRelease(&xlogctl->info_lck);
/* Also ensure XLogReceiptTime has a sane value */ /* Also ensure XLogReceiptTime has a sane value */
...@@ -6140,6 +6141,7 @@ StartupXLOG(void) ...@@ -6140,6 +6141,7 @@ StartupXLOG(void)
bool recoveryContinue = true; bool recoveryContinue = true;
bool recoveryApply = true; bool recoveryApply = true;
ErrorContextCallback errcontext; ErrorContextCallback errcontext;
TimestampTz xtime;
InRedo = true; InRedo = true;
...@@ -6210,7 +6212,6 @@ StartupXLOG(void) ...@@ -6210,7 +6212,6 @@ StartupXLOG(void)
*/ */
SpinLockAcquire(&xlogctl->info_lck); SpinLockAcquire(&xlogctl->info_lck);
xlogctl->replayEndRecPtr = EndRecPtr; xlogctl->replayEndRecPtr = EndRecPtr;
xlogctl->recoveryLastXTime = recoveryLastXTime;
SpinLockRelease(&xlogctl->info_lck); SpinLockRelease(&xlogctl->info_lck);
/* If we are attempting to enter Hot Standby mode, process XIDs we see */ /* If we are attempting to enter Hot Standby mode, process XIDs we see */
...@@ -6243,10 +6244,11 @@ StartupXLOG(void) ...@@ -6243,10 +6244,11 @@ StartupXLOG(void)
ereport(LOG, ereport(LOG,
(errmsg("redo done at %X/%X", (errmsg("redo done at %X/%X",
ReadRecPtr.xlogid, ReadRecPtr.xrecoff))); ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
if (recoveryLastXTime) xtime = GetLatestXTime();
if (xtime)
ereport(LOG, ereport(LOG,
(errmsg("last completed transaction was at log time %s", (errmsg("last completed transaction was at log time %s",
timestamptz_to_str(recoveryLastXTime)))); timestamptz_to_str(xtime))));
InRedo = false; InRedo = false;
} }
else else
...@@ -7553,6 +7555,7 @@ CreateRestartPoint(int flags) ...@@ -7553,6 +7555,7 @@ CreateRestartPoint(int flags)
CheckPoint lastCheckPoint; CheckPoint lastCheckPoint;
uint32 _logId; uint32 _logId;
uint32 _logSeg; uint32 _logSeg;
TimestampTz xtime;
/* use volatile pointer to prevent code rearrangement */ /* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl; volatile XLogCtlData *xlogctl = XLogCtl;
...@@ -7705,10 +7708,12 @@ CreateRestartPoint(int flags) ...@@ -7705,10 +7708,12 @@ CreateRestartPoint(int flags)
if (log_checkpoints) if (log_checkpoints)
LogCheckpointEnd(true); LogCheckpointEnd(true);
xtime = GetLatestXTime();
ereport((log_checkpoints ? LOG : DEBUG2), ereport((log_checkpoints ? LOG : DEBUG2),
(errmsg("recovery restart point at %X/%X with latest known log time %s", (errmsg("recovery restart point at %X/%X",
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff, lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff),
timestamptz_to_str(GetLatestXLogTime())))); xtime ? errdetail("last completed transaction was at log time %s",
timestamptz_to_str(xtime)) : 0));
LWLockRelease(CheckpointLock); LWLockRelease(CheckpointLock);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment