编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

PostgreSQL如何删除XLOG文件「补充」

wxchong 2024-08-18 00:53:33 开源技术 10 ℃ 0 评论
StartupXLOG:
	do{
		bool		switchedTLI = false;
		...
		/*
		 在回放记录前,检查该wal记录是否会引起时间线的改变。
		 该记录被视为新时间线的一部分,因此需要在回放前更新时间线。
		*/
		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){
				CheckPoint	checkPoint;
				memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
				newTLI = checkPoint.ThisTimeLineID;
				prevTLI = checkPoint.PrevTimeLineID;
			}else if (info == XLOG_END_OF_RECOVERY){
				xl_end_of_recovery xlrec;
				memcpy(&xlrec, XLogRecGetData(xlogreader), 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, prevTLI);
 
				/* Following WAL records should be run with new TLI */
				ThisTimeLineID = newTLI;
				switchedTLI = true;
			}
		}
 
		/*
		 * Update shared replayEndRecPtr before replaying this record,
		 * so that XLogFlush will update minRecoveryPoint correctly.
		 */
		SpinLockAcquire(&XLogCtl->info_lck);
		XLogCtl->replayEndRecPtr = EndRecPtr;//上一次读取的WAL记录末尾
		XLogCtl->replayEndTLI = ThisTimeLineID;
		SpinLockRelease(&XLogCtl->info_lck);
		...
 
		//回放
		RmgrTable[record->xl_rmid].rm_redo(xlogreader);
		...
		if ((record->xl_info & XLR_CHECK_CONSISTENCY) != 0)
			checkXLogConsistency(xlogreader);//检查是否到达一致性位置
 
		/*
		 * Update lastReplayedEndRecPtr after this record has been successfully replayed.
		 */
		SpinLockAcquire(&XLogCtl->info_lck);
		XLogCtl->lastReplayedEndRecPtr = EndRecPtr;
		XLogCtl->lastReplayedTLI = ThisTimeLineID;
		SpinLockRelease(&XLogCtl->info_lck);
		...
 
		/* Remember this record as the last-applied one */
		LastRec = ReadRecPtr;
 
		/* 如果到达一致性位置,允许只读连接 */
		CheckRecoveryConsistency();
 
		/* Is this a timeline switch? */
		if (switchedTLI){
			/*
			 * Before we continue on the new timeline, clean up any
			 * (possibly bogus) future WAL segments on the old
			 * timeline.
			 */
			RemoveNonParentXlogFiles(EndRecPtr, ThisTimeLineID);
			...
		}
		/* Else, try to fetch the next WAL record */
		record = ReadRecord(xlogreader, InvalidXLogRecPtr, LOG, false);
	}
/*
 * WAL文件不在时间线历史里面,删除这样的文件。
 * 恢复过程中,回放wal到下一个时间线时以及恢复结束创建一个新时间线时,调用该函数
 * We wouldn't otherwise care about extra WAL files lying in pg_wal, but they
 * might be leftover pre-allocated or recycled WAL segments on the old timeline
 * that we haven't used yet, and contain garbage. If we just leave them in
 * pg_wal, they will eventually be archived, and we can't let that happen.
 * Files that belong to our timeline history are valid, because we have
 * successfully replayed them, but from others we can't be sure.
 *
 * 'switchpoint' is the current point in WAL where we switch to new timeline,
 * and 'newTLI' is the new timeline we switch to.
 */
static void
RemoveNonParentXlogFiles(XLogRecPtr switchpoint, TimeLineID newTLI)
{
 
	XLByteToPrevSeg(switchpoint, endLogSegNo);
 
	xldir = AllocateDir(XLOGDIR);
	if (xldir == NULL)
		ereport(ERROR,(errcode_for_file_access(), errmsg("could not open write-ahead log directory \"%s\": %m",XLOGDIR)));
 
	/*
	 * Construct a filename of the last segment to be kept.
	 */
	XLogFileName(switchseg, newTLI, endLogSegNo);
 
	elog(DEBUG2, "attempting to remove WAL segments newer than log file %s",
		 switchseg);
 
	while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL){
		/* Ignore files that are not XLOG segments */
		if (!IsXLogFileName(xlde->d_name))
			continue;
 
		/*
		 * Remove files that are on a timeline older than the new one we're
		 * switching to, but with a segment number >= the first segment on the
		 * new timeline.
		 */
		if (strncmp(xlde->d_name, switchseg, 8) < 0 && strcmp(xlde->d_name + 8, switchseg + 8) > 0){
			/*
			 * If the file has already been marked as .ready, however, don't
			 * remove it yet. It should be OK to remove it - files that are
			 * not part of our timeline history are not required for recovery
			 * - but seems safer to let them be archived and removed later.
			 */
			if (!XLogArchiveIsReady(xlde->d_name))
				RemoveXlogFile(xlde->d_name, InvalidXLogRecPtr, switchpoint);
		}
	}
 
	FreeDir(xldir);
}


Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表