Skip to content

Commit 8771634

Browse files
committed
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).
1 parent aceedd8 commit 8771634

File tree

1 file changed

+60
-55
lines changed
  • src/backend/access/transam

1 file changed

+60
-55
lines changed

src/backend/access/transam/xlog.c

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.428 2010/07/03 20:43:57 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.429 2010/07/03 22:15:45 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -184,7 +184,6 @@ static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
184184
static bool recoveryTargetInclusive = true;
185185
static TransactionId recoveryTargetXid;
186186
static TimestampTz recoveryTargetTime;
187-
static TimestampTz recoveryLastXTime = 0;
188187

189188
/* options taken from recovery.conf for XLOG streaming */
190189
static bool StandbyMode = false;
@@ -403,10 +402,10 @@ typedef struct XLogCtlData
403402

404403
/* end+1 of the last record replayed (or being replayed) */
405404
XLogRecPtr replayEndRecPtr;
406-
/* timestamp of last record replayed (or being replayed) */
407-
TimestampTz recoveryLastXTime;
408405
/* end+1 of the last record replayed */
409406
XLogRecPtr recoveryLastRecPtr;
407+
/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
408+
TimestampTz recoveryLastXTime;
410409

411410
slock_t info_lck; /* locks shared variables shown above */
412411
} XLogCtlData;
@@ -554,6 +553,8 @@ static void readRecoveryCommandFile(void);
554553
static void exitArchiveRecovery(TimeLineID endTLI,
555554
uint32 endLogId, uint32 endLogSeg);
556555
static bool recoveryStopsHere(XLogRecord *record, bool *includeThis);
556+
static void SetLatestXTime(TimestampTz xtime);
557+
static TimestampTz GetLatestXTime(void);
557558
static void CheckRequiredParameterValues(void);
558559
static void XLogReportParameters(void);
559560
static void LocalSetXLogInsertAllowed(void);
@@ -5440,7 +5441,7 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg)
54405441
* *includeThis is set TRUE if we should apply this record before stopping.
54415442
*
54425443
* We also track the timestamp of the latest applied COMMIT/ABORT record
5443-
* in recoveryLastXTime, for logging purposes.
5444+
* in XLogCtl->recoveryLastXTime, for logging purposes.
54445445
* Also, some information is saved in recoveryStopXid et al for use in
54455446
* annotating the new timeline's history file.
54465447
*/
@@ -5452,51 +5453,30 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
54525453
TimestampTz recordXtime;
54535454

54545455
/* We only consider stopping at COMMIT or ABORT records */
5455-
if (record->xl_rmid == RM_XACT_ID)
5456+
if (record->xl_rmid != RM_XACT_ID)
5457+
return false;
5458+
record_info = record->xl_info & ~XLR_INFO_MASK;
5459+
if (record_info == XLOG_XACT_COMMIT)
54565460
{
5457-
record_info = record->xl_info & ~XLR_INFO_MASK;
5458-
if (record_info == XLOG_XACT_COMMIT)
5459-
{
5460-
xl_xact_commit *recordXactCommitData;
5461+
xl_xact_commit *recordXactCommitData;
54615462

5462-
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
5463-
recordXtime = recordXactCommitData->xact_time;
5464-
}
5465-
else if (record_info == XLOG_XACT_ABORT)
5466-
{
5467-
xl_xact_abort *recordXactAbortData;
5468-
5469-
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
5470-
recordXtime = recordXactAbortData->xact_time;
5471-
}
5472-
else
5473-
return false;
5463+
recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
5464+
recordXtime = recordXactCommitData->xact_time;
54745465
}
5475-
else if (record->xl_rmid == RM_XLOG_ID)
5466+
else if (record_info == XLOG_XACT_ABORT)
54765467
{
5477-
record_info = record->xl_info & ~XLR_INFO_MASK;
5478-
if (record_info == XLOG_CHECKPOINT_SHUTDOWN ||
5479-
record_info == XLOG_CHECKPOINT_ONLINE)
5480-
{
5481-
CheckPoint checkPoint;
5468+
xl_xact_abort *recordXactAbortData;
54825469

5483-
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
5484-
recoveryLastXTime = time_t_to_timestamptz(checkPoint.time);
5485-
}
5486-
5487-
/*
5488-
* We don't want to stop recovery on a checkpoint record, but we do
5489-
* want to update recoveryLastXTime. So return is unconditional.
5490-
*/
5491-
return false;
5470+
recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
5471+
recordXtime = recordXactAbortData->xact_time;
54925472
}
54935473
else
54945474
return false;
54955475

54965476
/* Do we have a PITR target at all? */
54975477
if (recoveryTarget == RECOVERY_TARGET_UNSET)
54985478
{
5499-
recoveryLastXTime = recordXtime;
5479+
SetLatestXTime(recordXtime);
55005480
return false;
55015481
}
55025482

@@ -5564,37 +5544,56 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
55645544
}
55655545

55665546
if (recoveryStopAfter)
5567-
recoveryLastXTime = recordXtime;
5547+
SetLatestXTime(recordXtime);
55685548
}
55695549
else
5570-
recoveryLastXTime = recordXtime;
5550+
SetLatestXTime(recordXtime);
55715551

55725552
return stopsHere;
55735553
}
55745554

55755555
/*
5576-
* Returns bool with current recovery mode, a global state.
5556+
* Save timestamp of latest processed commit/abort record.
5557+
*
5558+
* We keep this in XLogCtl, not a simple static variable, so that it can be
5559+
* seen by processes other than the startup process. Note in particular
5560+
* that CreateRestartPoint is executed in the bgwriter.
55775561
*/
5578-
Datum
5579-
pg_is_in_recovery(PG_FUNCTION_ARGS)
5562+
static void
5563+
SetLatestXTime(TimestampTz xtime)
55805564
{
5581-
PG_RETURN_BOOL(RecoveryInProgress());
5565+
/* use volatile pointer to prevent code rearrangement */
5566+
volatile XLogCtlData *xlogctl = XLogCtl;
5567+
5568+
SpinLockAcquire(&xlogctl->info_lck);
5569+
xlogctl->recoveryLastXTime = xtime;
5570+
SpinLockRelease(&xlogctl->info_lck);
55825571
}
55835572

55845573
/*
5585-
* Returns timestamp of last recovered commit/abort record.
5574+
* Fetch timestamp of latest processed commit/abort record.
55865575
*/
55875576
static TimestampTz
5588-
GetLatestXLogTime(void)
5577+
GetLatestXTime(void)
55895578
{
55905579
/* use volatile pointer to prevent code rearrangement */
55915580
volatile XLogCtlData *xlogctl = XLogCtl;
5581+
TimestampTz xtime;
55925582

55935583
SpinLockAcquire(&xlogctl->info_lck);
5594-
recoveryLastXTime = xlogctl->recoveryLastXTime;
5584+
xtime = xlogctl->recoveryLastXTime;
55955585
SpinLockRelease(&xlogctl->info_lck);
55965586

5597-
return recoveryLastXTime;
5587+
return xtime;
5588+
}
5589+
5590+
/*
5591+
* Returns bool with current recovery mode, a global state.
5592+
*/
5593+
Datum
5594+
pg_is_in_recovery(PG_FUNCTION_ARGS)
5595+
{
5596+
PG_RETURN_BOOL(RecoveryInProgress());
55985597
}
55995598

56005599
/*
@@ -6078,7 +6077,8 @@ StartupXLOG(void)
60786077
}
60796078

60806079
/*
6081-
* Initialize shared replayEndRecPtr and recoveryLastRecPtr.
6080+
* Initialize shared replayEndRecPtr, recoveryLastRecPtr, and
6081+
* recoveryLastXTime.
60826082
*
60836083
* This is slightly confusing if we're starting from an online
60846084
* checkpoint; we've just read and replayed the chekpoint record,
@@ -6091,6 +6091,7 @@ StartupXLOG(void)
60916091
SpinLockAcquire(&xlogctl->info_lck);
60926092
xlogctl->replayEndRecPtr = ReadRecPtr;
60936093
xlogctl->recoveryLastRecPtr = ReadRecPtr;
6094+
xlogctl->recoveryLastXTime = 0;
60946095
SpinLockRelease(&xlogctl->info_lck);
60956096

60966097
/* Also ensure XLogReceiptTime has a sane value */
@@ -6140,6 +6141,7 @@ StartupXLOG(void)
61406141
bool recoveryContinue = true;
61416142
bool recoveryApply = true;
61426143
ErrorContextCallback errcontext;
6144+
TimestampTz xtime;
61436145

61446146
InRedo = true;
61456147

@@ -6210,7 +6212,6 @@ StartupXLOG(void)
62106212
*/
62116213
SpinLockAcquire(&xlogctl->info_lck);
62126214
xlogctl->replayEndRecPtr = EndRecPtr;
6213-
xlogctl->recoveryLastXTime = recoveryLastXTime;
62146215
SpinLockRelease(&xlogctl->info_lck);
62156216

62166217
/* If we are attempting to enter Hot Standby mode, process XIDs we see */
@@ -6243,10 +6244,11 @@ StartupXLOG(void)
62436244
ereport(LOG,
62446245
(errmsg("redo done at %X/%X",
62456246
ReadRecPtr.xlogid, ReadRecPtr.xrecoff)));
6246-
if (recoveryLastXTime)
6247+
xtime = GetLatestXTime();
6248+
if (xtime)
62476249
ereport(LOG,
62486250
(errmsg("last completed transaction was at log time %s",
6249-
timestamptz_to_str(recoveryLastXTime))));
6251+
timestamptz_to_str(xtime))));
62506252
InRedo = false;
62516253
}
62526254
else
@@ -7553,6 +7555,7 @@ CreateRestartPoint(int flags)
75537555
CheckPoint lastCheckPoint;
75547556
uint32 _logId;
75557557
uint32 _logSeg;
7558+
TimestampTz xtime;
75567559

75577560
/* use volatile pointer to prevent code rearrangement */
75587561
volatile XLogCtlData *xlogctl = XLogCtl;
@@ -7705,10 +7708,12 @@ CreateRestartPoint(int flags)
77057708
if (log_checkpoints)
77067709
LogCheckpointEnd(true);
77077710

7711+
xtime = GetLatestXTime();
77087712
ereport((log_checkpoints ? LOG : DEBUG2),
7709-
(errmsg("recovery restart point at %X/%X with latest known log time %s",
7710-
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff,
7711-
timestamptz_to_str(GetLatestXLogTime()))));
7713+
(errmsg("recovery restart point at %X/%X",
7714+
lastCheckPoint.redo.xlogid, lastCheckPoint.redo.xrecoff),
7715+
xtime ? errdetail("last completed transaction was at log time %s",
7716+
timestamptz_to_str(xtime)) : 0));
77127717

77137718
LWLockRelease(CheckpointLock);
77147719

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy