|
7 | 7 | * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
8 | 8 | * Portions Copyright (c) 1994, Regents of the University of California
|
9 | 9 | *
|
10 |
| - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.356 2010/01/02 16:57:35 momjian Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.357 2010/01/04 12:50:49 heikki Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -515,8 +515,7 @@ static void xlog_outrec(StringInfo buf, XLogRecord *record);
|
515 | 515 | #endif
|
516 | 516 | static void issue_xlog_fsync(void);
|
517 | 517 | static void pg_start_backup_callback(int code, Datum arg);
|
518 |
| -static bool read_backup_label(XLogRecPtr *checkPointLoc, |
519 |
| - XLogRecPtr *minRecoveryLoc); |
| 518 | +static bool read_backup_label(XLogRecPtr *checkPointLoc); |
520 | 519 | static void rm_redo_error_callback(void *arg);
|
521 | 520 | static int get_sync_bit(int method);
|
522 | 521 |
|
@@ -5355,7 +5354,6 @@ StartupXLOG(void)
|
5355 | 5354 | bool haveBackupLabel = false;
|
5356 | 5355 | XLogRecPtr RecPtr,
|
5357 | 5356 | checkPointLoc,
|
5358 |
| - backupStopLoc, |
5359 | 5357 | EndOfLog;
|
5360 | 5358 | uint32 endLogId;
|
5361 | 5359 | uint32 endLogSeg;
|
@@ -5454,7 +5452,7 @@ StartupXLOG(void)
|
5454 | 5452 | recoveryTargetTLI,
|
5455 | 5453 | ControlFile->checkPointCopy.ThisTimeLineID)));
|
5456 | 5454 |
|
5457 |
| - if (read_backup_label(&checkPointLoc, &backupStopLoc)) |
| 5455 | + if (read_backup_label(&checkPointLoc)) |
5458 | 5456 | {
|
5459 | 5457 | /*
|
5460 | 5458 | * When a backup_label file is present, we want to roll forward from
|
@@ -5597,11 +5595,23 @@ StartupXLOG(void)
|
5597 | 5595 | ControlFile->prevCheckPoint = ControlFile->checkPoint;
|
5598 | 5596 | ControlFile->checkPoint = checkPointLoc;
|
5599 | 5597 | ControlFile->checkPointCopy = checkPoint;
|
5600 |
| - if (backupStopLoc.xlogid != 0 || backupStopLoc.xrecoff != 0) |
| 5598 | + if (InArchiveRecovery) |
| 5599 | + { |
| 5600 | + /* initialize minRecoveryPoint if not set yet */ |
| 5601 | + if (XLByteLT(ControlFile->minRecoveryPoint, checkPoint.redo)) |
| 5602 | + ControlFile->minRecoveryPoint = checkPoint.redo; |
| 5603 | + } |
| 5604 | + else |
5601 | 5605 | {
|
5602 |
| - if (XLByteLT(ControlFile->minRecoveryPoint, backupStopLoc)) |
5603 |
| - ControlFile->minRecoveryPoint = backupStopLoc; |
| 5606 | + XLogRecPtr InvalidXLogRecPtr = {0, 0}; |
| 5607 | + ControlFile->minRecoveryPoint = InvalidXLogRecPtr; |
5604 | 5608 | }
|
| 5609 | + /* |
| 5610 | + * set backupStartupPoint if we're starting archive recovery from a |
| 5611 | + * base backup |
| 5612 | + */ |
| 5613 | + if (haveBackupLabel) |
| 5614 | + ControlFile->backupStartPoint = checkPoint.redo; |
5605 | 5615 | ControlFile->time = (pg_time_t) time(NULL);
|
5606 | 5616 | /* No need to hold ControlFileLock yet, we aren't up far enough */
|
5607 | 5617 | UpdateControlFile();
|
@@ -5703,15 +5713,9 @@ StartupXLOG(void)
|
5703 | 5713 |
|
5704 | 5714 | InRedo = true;
|
5705 | 5715 |
|
5706 |
| - if (minRecoveryPoint.xlogid == 0 && minRecoveryPoint.xrecoff == 0) |
5707 |
| - ereport(LOG, |
5708 |
| - (errmsg("redo starts at %X/%X", |
5709 |
| - ReadRecPtr.xlogid, ReadRecPtr.xrecoff))); |
5710 |
| - else |
5711 |
| - ereport(LOG, |
5712 |
| - (errmsg("redo starts at %X/%X, consistency will be reached at %X/%X", |
5713 |
| - ReadRecPtr.xlogid, ReadRecPtr.xrecoff, |
5714 |
| - minRecoveryPoint.xlogid, minRecoveryPoint.xrecoff))); |
| 5716 | + ereport(LOG, |
| 5717 | + (errmsg("redo starts at %X/%X", |
| 5718 | + ReadRecPtr.xlogid, ReadRecPtr.xrecoff))); |
5715 | 5719 |
|
5716 | 5720 | /*
|
5717 | 5721 | * Let postmaster know we've started redo now, so that it can
|
@@ -5771,7 +5775,8 @@ StartupXLOG(void)
|
5771 | 5775 | * Have we passed our safe starting point?
|
5772 | 5776 | */
|
5773 | 5777 | if (!reachedMinRecoveryPoint &&
|
5774 |
| - XLByteLE(minRecoveryPoint, EndRecPtr)) |
| 5778 | + XLByteLE(minRecoveryPoint, EndRecPtr) && |
| 5779 | + XLogRecPtrIsInvalid(ControlFile->backupStartPoint)) |
5775 | 5780 | {
|
5776 | 5781 | reachedMinRecoveryPoint = true;
|
5777 | 5782 | ereport(LOG,
|
@@ -5877,7 +5882,9 @@ StartupXLOG(void)
|
5877 | 5882 | * be further ahead --- ControlFile->minRecoveryPoint cannot have been
|
5878 | 5883 | * advanced beyond the WAL we processed.
|
5879 | 5884 | */
|
5880 |
| - if (InRecovery && XLByteLT(EndOfLog, minRecoveryPoint)) |
| 5885 | + if (InArchiveRecovery && |
| 5886 | + (XLByteLT(EndOfLog, minRecoveryPoint) || |
| 5887 | + !XLogRecPtrIsInvalid(ControlFile->backupStartPoint))) |
5881 | 5888 | {
|
5882 | 5889 | if (reachedStopPoint) /* stopped because of stop request */
|
5883 | 5890 | ereport(FATAL,
|
@@ -7312,6 +7319,32 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record)
|
7312 | 7319 | {
|
7313 | 7320 | /* nothing to do here */
|
7314 | 7321 | }
|
| 7322 | + else if (info == XLOG_BACKUP_END) |
| 7323 | + { |
| 7324 | + XLogRecPtr startpoint; |
| 7325 | + memcpy(&startpoint, XLogRecGetData(record), sizeof(startpoint)); |
| 7326 | + |
| 7327 | + if (XLByteEQ(ControlFile->backupStartPoint, startpoint)) |
| 7328 | + { |
| 7329 | + /* |
| 7330 | + * We have reached the end of base backup, the point where |
| 7331 | + * pg_stop_backup() was done. The data on disk is now consistent. |
| 7332 | + * Reset backupStartPoint, and update minRecoveryPoint to make |
| 7333 | + * sure we don't allow starting up at an earlier point even if |
| 7334 | + * recovery is stopped and restarted soon after this. |
| 7335 | + */ |
| 7336 | + elog(DEBUG1, "end of backup reached"); |
| 7337 | + |
| 7338 | + LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); |
| 7339 | + |
| 7340 | + if (XLByteLT(ControlFile->minRecoveryPoint, lsn)) |
| 7341 | + ControlFile->minRecoveryPoint = lsn; |
| 7342 | + MemSet(&ControlFile->backupStartPoint, 0, sizeof(XLogRecPtr)); |
| 7343 | + UpdateControlFile(); |
| 7344 | + |
| 7345 | + LWLockRelease(ControlFileLock); |
| 7346 | + } |
| 7347 | + } |
7315 | 7348 | }
|
7316 | 7349 |
|
7317 | 7350 | void
|
@@ -7353,6 +7386,14 @@ xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
|
7353 | 7386 | {
|
7354 | 7387 | appendStringInfo(buf, "xlog switch");
|
7355 | 7388 | }
|
| 7389 | + else if (info == XLOG_BACKUP_END) |
| 7390 | + { |
| 7391 | + XLogRecPtr startpoint; |
| 7392 | + |
| 7393 | + memcpy(&startpoint, rec, sizeof(XLogRecPtr)); |
| 7394 | + appendStringInfo(buf, "backup end: %X/%X", |
| 7395 | + startpoint.xlogid, startpoint.xrecoff); |
| 7396 | + } |
7356 | 7397 | else
|
7357 | 7398 | appendStringInfo(buf, "UNKNOWN");
|
7358 | 7399 | }
|
@@ -7688,17 +7729,22 @@ pg_start_backup_callback(int code, Datum arg)
|
7688 | 7729 | /*
|
7689 | 7730 | * pg_stop_backup: finish taking an on-line backup dump
|
7690 | 7731 | *
|
7691 |
| - * We remove the backup label file created by pg_start_backup, and instead |
7692 |
| - * create a backup history file in pg_xlog (whence it will immediately be |
7693 |
| - * archived). The backup history file contains the same info found in |
7694 |
| - * the label file, plus the backup-end time and WAL location. |
| 7732 | + * We write an end-of-backup WAL record, and remove the backup label file |
| 7733 | + * created by pg_start_backup, creating a backup history file in pg_xlog |
| 7734 | + * instead (whence it will immediately be archived). The backup history file |
| 7735 | + * contains the same info found in the label file, plus the backup-end time |
| 7736 | + * and WAL location. Before 8.5, the backup-end time was read from the backup |
| 7737 | + * history file at the beginning of archive recovery, but we now use the WAL |
| 7738 | + * record for that and the file is for informational and debug purposes only. |
| 7739 | + * |
7695 | 7740 | * Note: different from CancelBackup which just cancels online backup mode.
|
7696 | 7741 | */
|
7697 | 7742 | Datum
|
7698 | 7743 | pg_stop_backup(PG_FUNCTION_ARGS)
|
7699 | 7744 | {
|
7700 | 7745 | XLogRecPtr startpoint;
|
7701 | 7746 | XLogRecPtr stoppoint;
|
| 7747 | + XLogRecData rdata; |
7702 | 7748 | pg_time_t stamp_time;
|
7703 | 7749 | char strfbuf[128];
|
7704 | 7750 | char histfilepath[MAXPGPATH];
|
@@ -7739,22 +7785,6 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
7739 | 7785 | XLogCtl->Insert.forcePageWrites = false;
|
7740 | 7786 | LWLockRelease(WALInsertLock);
|
7741 | 7787 |
|
7742 |
| - /* |
7743 |
| - * Force a switch to a new xlog segment file, so that the backup is valid |
7744 |
| - * as soon as archiver moves out the current segment file. We'll report |
7745 |
| - * the end address of the XLOG SWITCH record as the backup stopping point. |
7746 |
| - */ |
7747 |
| - stoppoint = RequestXLogSwitch(); |
7748 |
| - |
7749 |
| - XLByteToSeg(stoppoint, _logId, _logSeg); |
7750 |
| - XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg); |
7751 |
| - |
7752 |
| - /* Use the log timezone here, not the session timezone */ |
7753 |
| - stamp_time = (pg_time_t) time(NULL); |
7754 |
| - pg_strftime(strfbuf, sizeof(strfbuf), |
7755 |
| - "%Y-%m-%d %H:%M:%S %Z", |
7756 |
| - pg_localtime(&stamp_time, log_timezone)); |
7757 |
| - |
7758 | 7788 | /*
|
7759 | 7789 | * Open the existing label file
|
7760 | 7790 | */
|
@@ -7782,6 +7812,30 @@ pg_stop_backup(PG_FUNCTION_ARGS)
|
7782 | 7812 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
7783 | 7813 | errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
|
7784 | 7814 |
|
| 7815 | + /* |
| 7816 | + * Write the backup-end xlog record |
| 7817 | + */ |
| 7818 | + rdata.data = (char *) (&startpoint); |
| 7819 | + rdata.len = sizeof(startpoint); |
| 7820 | + rdata.buffer = InvalidBuffer; |
| 7821 | + rdata.next = NULL; |
| 7822 | + stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END, &rdata); |
| 7823 | + |
| 7824 | + /* |
| 7825 | + * Force a switch to a new xlog segment file, so that the backup is valid |
| 7826 | + * as soon as archiver moves out the current segment file. |
| 7827 | + */ |
| 7828 | + RequestXLogSwitch(); |
| 7829 | + |
| 7830 | + XLByteToSeg(stoppoint, _logId, _logSeg); |
| 7831 | + XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg); |
| 7832 | + |
| 7833 | + /* Use the log timezone here, not the session timezone */ |
| 7834 | + stamp_time = (pg_time_t) time(NULL); |
| 7835 | + pg_strftime(strfbuf, sizeof(strfbuf), |
| 7836 | + "%Y-%m-%d %H:%M:%S %Z", |
| 7837 | + pg_localtime(&stamp_time, log_timezone)); |
| 7838 | + |
7785 | 7839 | /*
|
7786 | 7840 | * Write the backup history file
|
7787 | 7841 | */
|
@@ -8088,33 +8142,18 @@ pg_xlogfile_name(PG_FUNCTION_ARGS)
|
8088 | 8142 | * later than the start of the dump, and so if we rely on it as the start
|
8089 | 8143 | * point, we will fail to restore a consistent database state.
|
8090 | 8144 | *
|
8091 |
| - * We also attempt to retrieve the corresponding backup history file. |
8092 |
| - * If successful, set *minRecoveryLoc to constrain valid PITR stopping |
8093 |
| - * points. |
8094 |
| - * |
8095 | 8145 | * Returns TRUE if a backup_label was found (and fills the checkpoint
|
8096 | 8146 | * location into *checkPointLoc); returns FALSE if not.
|
8097 | 8147 | */
|
8098 | 8148 | static bool
|
8099 |
| -read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *minRecoveryLoc) |
| 8149 | +read_backup_label(XLogRecPtr *checkPointLoc) |
8100 | 8150 | {
|
8101 | 8151 | XLogRecPtr startpoint;
|
8102 |
| - XLogRecPtr stoppoint; |
8103 |
| - char histfilename[MAXFNAMELEN]; |
8104 |
| - char histfilepath[MAXPGPATH]; |
8105 | 8152 | char startxlogfilename[MAXFNAMELEN];
|
8106 |
| - char stopxlogfilename[MAXFNAMELEN]; |
8107 | 8153 | TimeLineID tli;
|
8108 |
| - uint32 _logId; |
8109 |
| - uint32 _logSeg; |
8110 | 8154 | FILE *lfp;
|
8111 |
| - FILE *fp; |
8112 | 8155 | char ch;
|
8113 | 8156 |
|
8114 |
| - /* Default is to not constrain recovery stop point */ |
8115 |
| - minRecoveryLoc->xlogid = 0; |
8116 |
| - minRecoveryLoc->xrecoff = 0; |
8117 |
| - |
8118 | 8157 | /*
|
8119 | 8158 | * See if label file is present
|
8120 | 8159 | */
|
@@ -8152,45 +8191,6 @@ read_backup_label(XLogRecPtr *checkPointLoc, XLogRecPtr *minRecoveryLoc)
|
8152 | 8191 | errmsg("could not read file \"%s\": %m",
|
8153 | 8192 | BACKUP_LABEL_FILE)));
|
8154 | 8193 |
|
8155 |
| - /* |
8156 |
| - * Try to retrieve the backup history file (no error if we can't) |
8157 |
| - */ |
8158 |
| - XLByteToSeg(startpoint, _logId, _logSeg); |
8159 |
| - BackupHistoryFileName(histfilename, tli, _logId, _logSeg, |
8160 |
| - startpoint.xrecoff % XLogSegSize); |
8161 |
| - |
8162 |
| - if (InArchiveRecovery) |
8163 |
| - RestoreArchivedFile(histfilepath, histfilename, "RECOVERYHISTORY", 0); |
8164 |
| - else |
8165 |
| - BackupHistoryFilePath(histfilepath, tli, _logId, _logSeg, |
8166 |
| - startpoint.xrecoff % XLogSegSize); |
8167 |
| - |
8168 |
| - fp = AllocateFile(histfilepath, "r"); |
8169 |
| - if (fp) |
8170 |
| - { |
8171 |
| - /* |
8172 |
| - * Parse history file to identify stop point. |
8173 |
| - */ |
8174 |
| - if (fscanf(fp, "START WAL LOCATION: %X/%X (file %24s)%c", |
8175 |
| - &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename, |
8176 |
| - &ch) != 4 || ch != '\n') |
8177 |
| - ereport(FATAL, |
8178 |
| - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
8179 |
| - errmsg("invalid data in file \"%s\"", histfilename))); |
8180 |
| - if (fscanf(fp, "STOP WAL LOCATION: %X/%X (file %24s)%c", |
8181 |
| - &stoppoint.xlogid, &stoppoint.xrecoff, stopxlogfilename, |
8182 |
| - &ch) != 4 || ch != '\n') |
8183 |
| - ereport(FATAL, |
8184 |
| - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
8185 |
| - errmsg("invalid data in file \"%s\"", histfilename))); |
8186 |
| - *minRecoveryLoc = stoppoint; |
8187 |
| - if (ferror(fp) || FreeFile(fp)) |
8188 |
| - ereport(FATAL, |
8189 |
| - (errcode_for_file_access(), |
8190 |
| - errmsg("could not read file \"%s\": %m", |
8191 |
| - histfilepath))); |
8192 |
| - } |
8193 |
| - |
8194 | 8194 | return true;
|
8195 | 8195 | }
|
8196 | 8196 |
|
|
0 commit comments