Skip to content

Commit 7803e93

Browse files
committed
Include previous TLI in end-of-recovery and shutdown checkpoint records.
This isn't used for anything but a sanity check at the moment, but it could be highly valuable for debugging purposes. It could also be used to recreate timeline history by traversing WAL, which seems useful.
1 parent c352ea2 commit 7803e93

File tree

6 files changed

+48
-8
lines changed

6 files changed

+48
-8
lines changed

src/backend/access/rmgrdesc/xlogdesc.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
4141
CheckPoint *checkpoint = (CheckPoint *) rec;
4242

4343
appendStringInfo(buf, "checkpoint: redo %X/%X; "
44-
"tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
44+
"tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
4545
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
4646
"oldest running xid %u; %s",
4747
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
4848
checkpoint->ThisTimeLineID,
49+
checkpoint->PrevTimeLineID,
4950
checkpoint->fullPageWrites ? "true" : "false",
5051
checkpoint->nextXidEpoch, checkpoint->nextXid,
5152
checkpoint->nextOid,
@@ -125,8 +126,8 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
125126
xl_end_of_recovery xlrec;
126127

127128
memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
128-
appendStringInfo(buf, "end_of_recovery: tli %u; time %s",
129-
xlrec.ThisTimeLineID,
129+
appendStringInfo(buf, "end_of_recovery: tli %u; prev tli %u; time %s",
130+
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
130131
timestamptz_to_str(xlrec.end_time));
131132
}
132133
else

src/backend/access/transam/xlog.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,15 @@ typedef struct XLogCtlData
408408
char *pages; /* buffers for unwritten XLOG pages */
409409
XLogRecPtr *xlblocks; /* 1st byte ptr-s + XLOG_BLCKSZ */
410410
int XLogCacheBlck; /* highest allocated xlog buffer index */
411+
412+
/*
413+
* Shared copy of ThisTimeLineID. Does not change after end-of-recovery.
414+
* If we created a new timeline when the system was started up,
415+
* PrevTimeLineID is the old timeline's ID that we forked off from.
416+
* Otherwise it's equal to ThisTimeLineID.
417+
*/
411418
TimeLineID ThisTimeLineID;
419+
TimeLineID PrevTimeLineID;
412420

413421
/*
414422
* archiveCleanupCommand is read from recovery.conf but needs to be in
@@ -613,7 +621,8 @@ static void SetLatestXTime(TimestampTz xtime);
613621
static void SetCurrentChunkStartTime(TimestampTz xtime);
614622
static void CheckRequiredParameterValues(void);
615623
static void XLogReportParameters(void);
616-
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI);
624+
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI,
625+
TimeLineID prevTLI);
617626
static void LocalSetXLogInsertAllowed(void);
618627
static void CreateEndOfRecoveryRecord(void);
619628
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
@@ -3896,6 +3905,7 @@ BootStrapXLOG(void)
38963905
*/
38973906
checkPoint.redo = XLogSegSize + SizeOfXLogLongPHD;
38983907
checkPoint.ThisTimeLineID = ThisTimeLineID;
3908+
checkPoint.PrevTimeLineID = ThisTimeLineID;
38993909
checkPoint.fullPageWrites = fullPageWrites;
39003910
checkPoint.nextXidEpoch = 0;
39013911
checkPoint.nextXid = FirstNormalTransactionId;
@@ -4712,6 +4722,7 @@ StartupXLOG(void)
47124722
checkPointLoc,
47134723
EndOfLog;
47144724
XLogSegNo endLogSegNo;
4725+
TimeLineID PrevTimeLineID;
47154726
XLogRecord *record;
47164727
uint32 freespace;
47174728
TransactionId oldestActiveXID;
@@ -5431,6 +5442,7 @@ StartupXLOG(void)
54315442
if (record->xl_rmid == RM_XLOG_ID)
54325443
{
54335444
TimeLineID newTLI = ThisTimeLineID;
5445+
TimeLineID prevTLI = ThisTimeLineID;
54345446
uint8 info = record->xl_info & ~XLR_INFO_MASK;
54355447

54365448
if (info == XLOG_CHECKPOINT_SHUTDOWN)
@@ -5439,19 +5451,21 @@ StartupXLOG(void)
54395451

54405452
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
54415453
newTLI = checkPoint.ThisTimeLineID;
5454+
prevTLI = checkPoint.PrevTimeLineID;
54425455
}
54435456
else if (info == XLOG_END_OF_RECOVERY)
54445457
{
54455458
xl_end_of_recovery xlrec;
54465459

54475460
memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
54485461
newTLI = xlrec.ThisTimeLineID;
5462+
prevTLI = xlrec.PrevTimeLineID;
54495463
}
54505464

54515465
if (newTLI != ThisTimeLineID)
54525466
{
54535467
/* Check that it's OK to switch to this TLI */
5454-
checkTimeLineSwitch(EndRecPtr, newTLI);
5468+
checkTimeLineSwitch(EndRecPtr, newTLI, prevTLI);
54555469

54565470
/* Following WAL records should be run with new TLI */
54575471
ThisTimeLineID = newTLI;
@@ -5620,6 +5634,7 @@ StartupXLOG(void)
56205634
*
56215635
* In a normal crash recovery, we can just extend the timeline we were in.
56225636
*/
5637+
PrevTimeLineID = ThisTimeLineID;
56235638
if (InArchiveRecovery)
56245639
{
56255640
char reason[200];
@@ -5655,6 +5670,7 @@ StartupXLOG(void)
56555670

56565671
/* Save the selected TimeLineID in shared memory, too */
56575672
XLogCtl->ThisTimeLineID = ThisTimeLineID;
5673+
XLogCtl->PrevTimeLineID = PrevTimeLineID;
56585674

56595675
/*
56605676
* We are now done reading the old WAL. Turn off archive fetching if it
@@ -6690,6 +6706,11 @@ CreateCheckPoint(int flags)
66906706
LocalSetXLogInsertAllowed();
66916707

66926708
checkPoint.ThisTimeLineID = ThisTimeLineID;
6709+
if (flags & CHECKPOINT_END_OF_RECOVERY)
6710+
checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6711+
else
6712+
checkPoint.PrevTimeLineID = ThisTimeLineID;
6713+
66936714
checkPoint.fullPageWrites = Insert->fullPageWrites;
66946715

66956716
/*
@@ -6980,7 +7001,11 @@ CreateEndOfRecoveryRecord(void)
69807001
elog(ERROR, "can only be used to end recovery");
69817002

69827003
xlrec.end_time = time(NULL);
7004+
7005+
LWLockAcquire(WALInsertLock, LW_SHARED);
69837006
xlrec.ThisTimeLineID = ThisTimeLineID;
7007+
xlrec.PrevTimeLineID = XLogCtl->PrevTimeLineID;
7008+
LWLockRelease(WALInsertLock);
69847009

69857010
LocalSetXLogInsertAllowed();
69867011

@@ -7535,8 +7560,13 @@ UpdateFullPageWrites(void)
75357560
* replay. (Currently, timeline can only change at a shutdown checkpoint).
75367561
*/
75377562
static void
7538-
checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI)
7563+
checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI)
75397564
{
7565+
/* Check that the record agrees on what the current (old) timeline is */
7566+
if (prevTLI != ThisTimeLineID)
7567+
ereport(PANIC,
7568+
(errmsg("unexpected prev timeline ID %u (current timeline ID %u) in checkpoint record",
7569+
prevTLI, ThisTimeLineID)));
75407570
/*
75417571
* The new timeline better be in the list of timelines we expect
75427572
* to see, according to the timeline history. It should also not

src/bin/pg_controldata/pg_controldata.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ main(int argc, char *argv[])
215215
xlogfilename);
216216
printf(_("Latest checkpoint's TimeLineID: %u\n"),
217217
ControlFile.checkPointCopy.ThisTimeLineID);
218+
printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
219+
ControlFile.checkPointCopy.PrevTimeLineID);
218220
printf(_("Latest checkpoint's full_page_writes: %s\n"),
219221
ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
220222
printf(_("Latest checkpoint's NextXID: %u/%u\n"),

src/bin/pg_resetxlog/pg_resetxlog.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,10 @@ main(int argc, char *argv[])
340340
ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;
341341

342342
if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
343+
{
343344
ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
345+
ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
346+
}
344347

345348
if (minXlogSegNo > newXlogSegNo)
346349
newXlogSegNo = minXlogSegNo;
@@ -490,6 +493,7 @@ GuessControlValues(void)
490493

491494
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
492495
ControlFile.checkPointCopy.ThisTimeLineID = 1;
496+
ControlFile.checkPointCopy.PrevTimeLineID = 1;
493497
ControlFile.checkPointCopy.fullPageWrites = false;
494498
ControlFile.checkPointCopy.nextXidEpoch = 0;
495499
ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;

src/include/access/xlog_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ typedef struct xl_restore_point
221221
typedef struct xl_end_of_recovery
222222
{
223223
TimestampTz end_time;
224-
TimeLineID ThisTimeLineID;
224+
TimeLineID ThisTimeLineID; /* new TLI */
225+
TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
225226
} xl_end_of_recovery;
226227

227228
/*

src/include/catalog/pg_control.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222

2323
/* Version identifier for this pg_control format */
24-
#define PG_CONTROL_VERSION 933
24+
#define PG_CONTROL_VERSION 934
2525

2626
/*
2727
* Body of CheckPoint XLOG records. This is declared here because we keep
@@ -33,6 +33,8 @@ typedef struct CheckPoint
3333
XLogRecPtr redo; /* next RecPtr available when we began to
3434
* create CheckPoint (i.e. REDO start point) */
3535
TimeLineID ThisTimeLineID; /* current TLI */
36+
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
37+
* timeline (equals ThisTimeLineID otherwise) */
3638
bool fullPageWrites; /* current full_page_writes */
3739
uint32 nextXidEpoch; /* higher-order bits of nextXid */
3840
TransactionId nextXid; /* next free XID */

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