磨砺技术珠矶,践行数据之道,追求卓越价值
回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页
看代码:
/* File path names (all relative to $PGDATA) */
#define BACKUP_LABEL_FILE backup_label
#define BACKUP_LABEL_OLD backup_label.old
在特定条件下,会有一个文件,名为 backup_label
在StartupXLOG执行时,通过 read_backup_label 函数来进行读取:
/* * read_backup_label: check to see if a backup_label file is present * If we see a backup_label during recovery, we assume that we are recovering * from a backup dump file, and we therefore roll forward from the checkpoint * identified by the label file, NOT what pg_control says. This avoids the * problem that pg_control might have been archived one or more checkpoints * later than the start of the dump, and so if we rely on it as the start * point, we will fail to restore a consistent database state. * * Returns TRUE if a backup_label was found (and fills the checkpoint * location and its REDO location into *checkPointLoc and RedoStartLSN, * respectively); returns FALSE if not. If this backup_label came from a * streamed backup, *backupEndRequired is set to TRUE. */
static bool read_backup_label(XLogRecPtr *checkPointLoc, bool *backupEndRequired) { char startxlogfilename[MAXFNAMELEN]; TimeLineID tli; FILE *lfp; char ch; char backuptype[20]; *backupEndRequired = false; /* * See if label file is present */ lfp = AllocateFile(BACKUP_LABEL_FILE, "r"); if (!lfp) { if (errno != ENOENT) ereport(FATAL, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE))); return false; /* it's not there, all is fine */ } /* * Read and parse the START WAL LOCATION and CHECKPOINT lines (this code * is pretty crude, but we are not expecting any variability in the file * format). */
if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c", &RedoStartLSN.xlogid, &RedoStartLSN.xrecoff, &tli, startxlogfilename, &ch) != 5 || ch != '\n') ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE))); if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%X%c", &checkPointLoc->xlogid, &checkPointLoc->xrecoff, &ch) != 3 || ch != '\n') ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE))); /* * BACKUP METHOD line didn't exist in 9.1beta3 and earlier, so don't * error out if it doesn't exist. */
if (fscanf(lfp, "BACKUP METHOD: %19s", backuptype) == 1) { if (strcmp(backuptype, "streamed") == 0) *backupEndRequired = true; } if (ferror(lfp) || FreeFile(lfp)) ereport(FATAL, (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE))); return true; }
看StarupXLOG函数:
/* * This must be called ONCE during postmaster or standalone-backend startup */
void StartupXLOG(void) { … if (read_backup_label(&checkPointLoc, &backupEndRequired)) { /* * When a backup_label file is present, we want to roll forward from * the checkpoint it identifies, rather than using pg_control. */ record = ReadCheckpointRecord(checkPointLoc, 0); if (record != NULL) { memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN); ereport(DEBUG1, (errmsg("checkpoint record is at %X/%X", checkPointLoc.xlogid, checkPointLoc.xrecoff))); InRecovery = true; /* force recovery even if SHUTDOWNED */
/* * Make sure that REDO location exists. This may not be the case * if there was a crash during an online backup, which left a * backup_label around that references a WAL segment that's * already been archived. */
if (XLByteLT(checkPoint.redo, checkPointLoc)) { if (!ReadRecord(&(checkPoint.redo), LOG, false)) ereport(FATAL, (errmsg("could not find redo location referenced by checkpoint record"), errhint("If you are not restoring from a backup,
try removing the file \"%s/backup_label\".", DataDir))); } } else { ereport(FATAL, (errmsg("could not locate required checkpoint record"), errhint("If you are not restoring from a backup,
try removing the file \"%s/backup_label\".", DataDir))); wasShutdown = false; /* keep compiler quiet */ } /* set flag to delete it later */ haveBackupLabel = true; } else { /* * Get the last valid checkpoint record. If the latest one according * to pg_control is broken, try the next-to-last one. */ checkPointLoc = ControlFile->checkPoint; RedoStartLSN = ControlFile->checkPointCopy.redo; record = ReadCheckpointRecord(checkPointLoc, 1); if (record != NULL) { ereport(DEBUG1, (errmsg("checkpoint record is at %X/%X", checkPointLoc.xlogid, checkPointLoc.xrecoff))); } else if (StandbyMode) { /* * The last valid checkpoint record required for a streaming * recovery exists in neither standby nor the primary. */ ereport(PANIC, (errmsg("could not locate a valid checkpoint record"))); } else { checkPointLoc = ControlFile->prevCheckPoint; record = ReadCheckpointRecord(checkPointLoc, 2); if (record != NULL) { ereport(LOG, (errmsg("using previous checkpoint record at %X/%X", checkPointLoc.xlogid, checkPointLoc.xrecoff))); InRecovery = true; /* force recovery even if SHUTDOWNED */ } else ereport(PANIC, (errmsg("could not locate a valid checkpoint record"))); } memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint)); wasShutdown = (record->xl_info == XLOG_CHECKPOINT_SHUTDOWN); } … }
通过运行发现,上一次正常关闭或者崩溃,都不会产生 backup_label 文件。
关于这个文件,大家都是这么说的:
http://jsoc.stanford.edu/production/postgres_backup_restore.html.bk!
http://raghavt.blogspot.com/2011/05/postgresql-90-backup-recovery.html
http://www.network-theory.co.uk/docs/postgresql/vol3/MakingaBaseBackup.html
就是:pg_start_backup,会生成 backup_label文件。pg_stop_backup,会删除backup_label文件。
而如果StartupXLOG函数运行时,发现了backup_label文件,那么意味着它处正在从online backup中恢复的过程中。
回到上一级页面:PostgreSQL内部结构与源代码研究索引页 回到顶级页面:PostgreSQL索引页
磨砺技术珠矶,践行数据之道,追求卓越价值