mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
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.
This commit is contained in:
parent
c352ea2d74
commit
7803e9327d
@ -41,11 +41,12 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
||||
CheckPoint *checkpoint = (CheckPoint *) rec;
|
||||
|
||||
appendStringInfo(buf, "checkpoint: redo %X/%X; "
|
||||
"tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
|
||||
"tli %u; prev tli %u; fpw %s; xid %u/%u; oid %u; multi %u; offset %u; "
|
||||
"oldest xid %u in DB %u; oldest multi %u in DB %u; "
|
||||
"oldest running xid %u; %s",
|
||||
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
|
||||
checkpoint->ThisTimeLineID,
|
||||
checkpoint->PrevTimeLineID,
|
||||
checkpoint->fullPageWrites ? "true" : "false",
|
||||
checkpoint->nextXidEpoch, checkpoint->nextXid,
|
||||
checkpoint->nextOid,
|
||||
@ -125,8 +126,8 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
||||
xl_end_of_recovery xlrec;
|
||||
|
||||
memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
|
||||
appendStringInfo(buf, "end_of_recovery: tli %u; time %s",
|
||||
xlrec.ThisTimeLineID,
|
||||
appendStringInfo(buf, "end_of_recovery: tli %u; prev tli %u; time %s",
|
||||
xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
|
||||
timestamptz_to_str(xlrec.end_time));
|
||||
}
|
||||
else
|
||||
|
@ -408,7 +408,15 @@ typedef struct XLogCtlData
|
||||
char *pages; /* buffers for unwritten XLOG pages */
|
||||
XLogRecPtr *xlblocks; /* 1st byte ptr-s + XLOG_BLCKSZ */
|
||||
int XLogCacheBlck; /* highest allocated xlog buffer index */
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
TimeLineID ThisTimeLineID;
|
||||
TimeLineID PrevTimeLineID;
|
||||
|
||||
/*
|
||||
* archiveCleanupCommand is read from recovery.conf but needs to be in
|
||||
@ -613,7 +621,8 @@ static void SetLatestXTime(TimestampTz xtime);
|
||||
static void SetCurrentChunkStartTime(TimestampTz xtime);
|
||||
static void CheckRequiredParameterValues(void);
|
||||
static void XLogReportParameters(void);
|
||||
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI);
|
||||
static void checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI,
|
||||
TimeLineID prevTLI);
|
||||
static void LocalSetXLogInsertAllowed(void);
|
||||
static void CreateEndOfRecoveryRecord(void);
|
||||
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags);
|
||||
@ -3896,6 +3905,7 @@ BootStrapXLOG(void)
|
||||
*/
|
||||
checkPoint.redo = XLogSegSize + SizeOfXLogLongPHD;
|
||||
checkPoint.ThisTimeLineID = ThisTimeLineID;
|
||||
checkPoint.PrevTimeLineID = ThisTimeLineID;
|
||||
checkPoint.fullPageWrites = fullPageWrites;
|
||||
checkPoint.nextXidEpoch = 0;
|
||||
checkPoint.nextXid = FirstNormalTransactionId;
|
||||
@ -4712,6 +4722,7 @@ StartupXLOG(void)
|
||||
checkPointLoc,
|
||||
EndOfLog;
|
||||
XLogSegNo endLogSegNo;
|
||||
TimeLineID PrevTimeLineID;
|
||||
XLogRecord *record;
|
||||
uint32 freespace;
|
||||
TransactionId oldestActiveXID;
|
||||
@ -5431,6 +5442,7 @@ StartupXLOG(void)
|
||||
if (record->xl_rmid == RM_XLOG_ID)
|
||||
{
|
||||
TimeLineID newTLI = ThisTimeLineID;
|
||||
TimeLineID prevTLI = ThisTimeLineID;
|
||||
uint8 info = record->xl_info & ~XLR_INFO_MASK;
|
||||
|
||||
if (info == XLOG_CHECKPOINT_SHUTDOWN)
|
||||
@ -5439,6 +5451,7 @@ StartupXLOG(void)
|
||||
|
||||
memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
|
||||
newTLI = checkPoint.ThisTimeLineID;
|
||||
prevTLI = checkPoint.PrevTimeLineID;
|
||||
}
|
||||
else if (info == XLOG_END_OF_RECOVERY)
|
||||
{
|
||||
@ -5446,12 +5459,13 @@ StartupXLOG(void)
|
||||
|
||||
memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_end_of_recovery));
|
||||
newTLI = xlrec.ThisTimeLineID;
|
||||
prevTLI = xlrec.PrevTimeLineID;
|
||||
}
|
||||
|
||||
if (newTLI != ThisTimeLineID)
|
||||
{
|
||||
/* Check that it's OK to switch to this TLI */
|
||||
checkTimeLineSwitch(EndRecPtr, newTLI);
|
||||
checkTimeLineSwitch(EndRecPtr, newTLI, prevTLI);
|
||||
|
||||
/* Following WAL records should be run with new TLI */
|
||||
ThisTimeLineID = newTLI;
|
||||
@ -5620,6 +5634,7 @@ StartupXLOG(void)
|
||||
*
|
||||
* In a normal crash recovery, we can just extend the timeline we were in.
|
||||
*/
|
||||
PrevTimeLineID = ThisTimeLineID;
|
||||
if (InArchiveRecovery)
|
||||
{
|
||||
char reason[200];
|
||||
@ -5655,6 +5670,7 @@ StartupXLOG(void)
|
||||
|
||||
/* Save the selected TimeLineID in shared memory, too */
|
||||
XLogCtl->ThisTimeLineID = ThisTimeLineID;
|
||||
XLogCtl->PrevTimeLineID = PrevTimeLineID;
|
||||
|
||||
/*
|
||||
* We are now done reading the old WAL. Turn off archive fetching if it
|
||||
@ -6690,6 +6706,11 @@ CreateCheckPoint(int flags)
|
||||
LocalSetXLogInsertAllowed();
|
||||
|
||||
checkPoint.ThisTimeLineID = ThisTimeLineID;
|
||||
if (flags & CHECKPOINT_END_OF_RECOVERY)
|
||||
checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
|
||||
else
|
||||
checkPoint.PrevTimeLineID = ThisTimeLineID;
|
||||
|
||||
checkPoint.fullPageWrites = Insert->fullPageWrites;
|
||||
|
||||
/*
|
||||
@ -6980,7 +7001,11 @@ CreateEndOfRecoveryRecord(void)
|
||||
elog(ERROR, "can only be used to end recovery");
|
||||
|
||||
xlrec.end_time = time(NULL);
|
||||
|
||||
LWLockAcquire(WALInsertLock, LW_SHARED);
|
||||
xlrec.ThisTimeLineID = ThisTimeLineID;
|
||||
xlrec.PrevTimeLineID = XLogCtl->PrevTimeLineID;
|
||||
LWLockRelease(WALInsertLock);
|
||||
|
||||
LocalSetXLogInsertAllowed();
|
||||
|
||||
@ -7535,8 +7560,13 @@ UpdateFullPageWrites(void)
|
||||
* replay. (Currently, timeline can only change at a shutdown checkpoint).
|
||||
*/
|
||||
static void
|
||||
checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI)
|
||||
checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI)
|
||||
{
|
||||
/* Check that the record agrees on what the current (old) timeline is */
|
||||
if (prevTLI != ThisTimeLineID)
|
||||
ereport(PANIC,
|
||||
(errmsg("unexpected prev timeline ID %u (current timeline ID %u) in checkpoint record",
|
||||
prevTLI, ThisTimeLineID)));
|
||||
/*
|
||||
* The new timeline better be in the list of timelines we expect
|
||||
* to see, according to the timeline history. It should also not
|
||||
|
@ -215,6 +215,8 @@ main(int argc, char *argv[])
|
||||
xlogfilename);
|
||||
printf(_("Latest checkpoint's TimeLineID: %u\n"),
|
||||
ControlFile.checkPointCopy.ThisTimeLineID);
|
||||
printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
|
||||
ControlFile.checkPointCopy.PrevTimeLineID);
|
||||
printf(_("Latest checkpoint's full_page_writes: %s\n"),
|
||||
ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
|
||||
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
|
||||
|
@ -340,7 +340,10 @@ main(int argc, char *argv[])
|
||||
ControlFile.checkPointCopy.nextMultiOffset = set_mxoff;
|
||||
|
||||
if (minXlogTli > ControlFile.checkPointCopy.ThisTimeLineID)
|
||||
{
|
||||
ControlFile.checkPointCopy.ThisTimeLineID = minXlogTli;
|
||||
ControlFile.checkPointCopy.PrevTimeLineID = minXlogTli;
|
||||
}
|
||||
|
||||
if (minXlogSegNo > newXlogSegNo)
|
||||
newXlogSegNo = minXlogSegNo;
|
||||
@ -490,6 +493,7 @@ GuessControlValues(void)
|
||||
|
||||
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
|
||||
ControlFile.checkPointCopy.ThisTimeLineID = 1;
|
||||
ControlFile.checkPointCopy.PrevTimeLineID = 1;
|
||||
ControlFile.checkPointCopy.fullPageWrites = false;
|
||||
ControlFile.checkPointCopy.nextXidEpoch = 0;
|
||||
ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
|
||||
|
@ -221,7 +221,8 @@ typedef struct xl_restore_point
|
||||
typedef struct xl_end_of_recovery
|
||||
{
|
||||
TimestampTz end_time;
|
||||
TimeLineID ThisTimeLineID;
|
||||
TimeLineID ThisTimeLineID; /* new TLI */
|
||||
TimeLineID PrevTimeLineID; /* previous TLI we forked off from */
|
||||
} xl_end_of_recovery;
|
||||
|
||||
/*
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
|
||||
/* Version identifier for this pg_control format */
|
||||
#define PG_CONTROL_VERSION 933
|
||||
#define PG_CONTROL_VERSION 934
|
||||
|
||||
/*
|
||||
* Body of CheckPoint XLOG records. This is declared here because we keep
|
||||
@ -33,6 +33,8 @@ typedef struct CheckPoint
|
||||
XLogRecPtr redo; /* next RecPtr available when we began to
|
||||
* create CheckPoint (i.e. REDO start point) */
|
||||
TimeLineID ThisTimeLineID; /* current TLI */
|
||||
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
|
||||
* timeline (equals ThisTimeLineID otherwise) */
|
||||
bool fullPageWrites; /* current full_page_writes */
|
||||
uint32 nextXidEpoch; /* higher-order bits of nextXid */
|
||||
TransactionId nextXid; /* next free XID */
|
||||
|
Loading…
Reference in New Issue
Block a user