68 #define RECOVERY_COMMAND_FILE "recovery.conf"
69 #define RECOVERY_COMMAND_DONE "recovery.done"
416 int emode,
bool fetching_ckpt,
420 int reqLen,
XLogRecPtr targetRecPtr,
char *readBuf);
513 bool *haveBackupLabel_ptr,
bool *haveTblspcMap_ptr)
520 bool haveTblspcMap =
false;
521 bool haveBackupLabel =
false;
523 bool backupFromStandby =
false;
547 (
errmsg(
"entering standby mode")));
550 (
errmsg(
"starting point-in-time recovery to XID %u",
554 (
errmsg(
"starting point-in-time recovery to %s",
558 (
errmsg(
"starting point-in-time recovery to \"%s\"",
562 (
errmsg(
"starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
566 (
errmsg(
"starting point-in-time recovery to earliest consistent point")));
569 (
errmsg(
"starting archive recovery")));
583 .segment_open = NULL,
588 (
errcode(ERRCODE_OUT_OF_MEMORY),
590 errdetail(
"Failed while allocating a WAL reading processor.")));
653 (
errmsg(
"could not find redo location referenced by checkpoint record"),
654 errhint(
"If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
655 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
656 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
663 (
errmsg(
"could not locate required checkpoint record"),
664 errhint(
"If you are restoring from a backup, touch \"%s/recovery.signal\" and add required recovery options.\n"
665 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
666 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
676 foreach(lc, tablespaces)
692 errmsg(
"could not create symbolic link \"%s\": %m",
701 haveTblspcMap =
true;
705 haveBackupLabel =
true;
724 (
errmsg(
"ignoring file \"%s\" because no file \"%s\" exists",
726 errdetail(
"File \"%s\" was renamed to \"%s\".",
730 (
errmsg(
"ignoring file \"%s\" because no file \"%s\" exists",
732 errdetail(
"Could not rename file \"%s\" to \"%s\": %m.",
786 (
errmsg(
"could not locate a valid checkpoint record")));
810 (
errmsg(
"requested timeline %u is not a child of this server's history",
812 errdetail(
"Latest checkpoint is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
826 (
errmsg(
"requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
834 wasShutdown ?
"true" :
"false")));
854 (
errmsg(
"invalid next transaction ID")));
859 (
errmsg(
"invalid redo in checkpoint record")));
870 (
errmsg(
"invalid redo record in shutdown checkpoint")));
899 (
errmsg(
"database system was not properly shut down; "
900 "automatic recovery in progress")));
903 (
errmsg(
"crash recovery starts in timeline %u "
904 "and has target timeline %u",
941 if (backupFromStandby)
946 (
errmsg(
"backup_label contains data inconsistent with control file"),
947 errhint(
"This means that the backup is corrupted and you will "
948 "have to use another backup for recovery.")));
975 *wasShutdown_ptr = wasShutdown;
976 *haveBackupLabel_ptr = haveBackupLabel;
977 *haveTblspcMap_ptr = haveTblspcMap;
990 struct stat stat_buf;
1001 errmsg(
"using recovery command file \"%s\" is not supported",
1065 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1066 errmsg(
"standby mode is not supported by single-user servers")));
1083 (
errmsg(
"specified neither primary_conninfo nor restore_command"),
1084 errhint(
"The database server will regularly poll the pg_wal subdirectory to check for files placed there.")));
1091 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1092 errmsg(
"must specify restore_command when standby mode is not enabled")));
1129 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1130 errmsg(
"recovery target timeline %u does not exist",
1177 char backuptype[20];
1178 char backupfrom[20];
1180 char backuptime[128];
1186 *backupLabelTLI = 0;
1188 *backupFromStandby =
false;
1196 if (errno != ENOENT)
1199 errmsg(
"could not read file \"%s\": %m",
1209 if (fscanf(lfp,
"START WAL LOCATION: %X/%X (file %08X%16s)%c",
1210 &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch !=
'\n')
1212 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1216 if (fscanf(lfp,
"CHECKPOINT LOCATION: %X/%X%c",
1217 &hi, &lo, &ch) != 3 || ch !=
'\n')
1219 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1221 *checkPointLoc = ((uint64) hi) << 32 | lo;
1222 *backupLabelTLI = tli_from_walseg;
1234 if (fscanf(lfp,
"BACKUP METHOD: %19s\n", backuptype) == 1)
1236 if (strcmp(backuptype,
"streamed") == 0)
1245 if (fscanf(lfp,
"BACKUP FROM: %19s\n", backupfrom) == 1)
1247 if (strcmp(backupfrom,
"standby") == 0)
1248 *backupFromStandby =
true;
1260 if (fscanf(lfp,
"START TIME: %127[^\n]\n", backuptime) == 1)
1265 if (fscanf(lfp,
"LABEL: %1023[^\n]\n", backuplabel) == 1)
1274 if (fscanf(lfp,
"START TIMELINE: %u\n", &tli_from_file) == 1)
1276 if (tli_from_walseg != tli_from_file)
1278 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1280 errdetail(
"Timeline ID parsed is %u, but expected %u.",
1281 tli_from_file, tli_from_walseg)));
1291 errmsg(
"could not read file \"%s\": %m",
1325 if (errno != ENOENT)
1328 errmsg(
"could not read file \"%s\": %m",
1339 was_backslash =
false;
1340 while ((ch = fgetc(lfp)) != EOF)
1342 if (!was_backslash && (ch ==
'\n' || ch ==
'\r'))
1354 while (
str[n] &&
str[n] !=
' ')
1356 if (n < 1 || n >=
i - 1)
1358 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1365 *tablespaces =
lappend(*tablespaces, ti);
1370 else if (!was_backslash && ch ==
'\\')
1371 was_backslash =
true;
1374 if (
i <
sizeof(
str) - 1)
1376 was_backslash =
false;
1380 if (
i != 0 || was_backslash)
1382 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1388 errmsg(
"could not read file \"%s\": %m",
1494 if (endOfLog % XLOG_BLCKSZ != 0)
1500 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1504 len = endOfLog % XLOG_BLCKSZ;
1564 unlink(recoveryPath);
1568 unlink(recoveryPath);
1588 bool reachedRecoveryTarget =
false;
1662 (
errmsg(
"redo starts at %X/%X",
1722 reachedRecoveryTarget =
true;
1751 reachedRecoveryTarget =
true;
1757 }
while (record != NULL);
1763 if (reachedRecoveryTarget)
1767 (
errmsg(
"requested recovery stop point is before consistent recovery point")));
1799 (
errmsg(
"redo done at %X/%X system usage: %s",
1805 (
errmsg(
"last completed transaction was at log time %s",
1814 (
errmsg(
"redo is not required")));
1823 !reachedRecoveryTarget)
1825 (
errmsg(
"recovery ended before configured recovery target was reached")));
1835 bool switchedTLI =
false;
1856 if (record->
xl_rmid == RM_XLOG_ID)
1879 if (newReplayTLI != *replayTLI)
1883 newReplayTLI, prevReplayTLI, *replayTLI);
1886 *replayTLI = newReplayTLI;
1911 if (record->
xl_rmid == RM_XLOG_ID)
1991 elog(
FATAL,
"mismatching overwritten LSN %X/%X -> %X/%X",
2000 (
errmsg(
"successfully skipped missing contrecord at %X/%X, overwritten at %s",
2023 elog(
DEBUG1,
"end of backup record reached");
2028 elog(
DEBUG1,
"saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
2054 while ((de =
ReadDir(dir,
"pg_tblspc")) != NULL)
2059 if (strspn(de->
d_name,
"0123456789") != strlen(de->
d_name))
2067 errmsg(
"unexpected directory entry \"%s\" found in %s",
2068 de->
d_name,
"pg_tblspc/"),
2069 errdetail(
"All directory entries in pg_tblspc/ should be symbolic links."),
2070 errhint(
"Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete.")));
2144 (
errmsg(
"consistent recovery state reached at %X/%X",
2245 &rlocator, &forknum, &blk, NULL))
2278 if (prevTLI != replayTLI)
2280 (
errmsg(
"unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2281 prevTLI, replayTLI)));
2289 (
errmsg(
"unexpected timeline ID %u (after %u) in checkpoint record",
2290 newTLI, replayTLI)));
2305 (
errmsg(
"unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
2378 &rlocator, &forknum, &blkno, NULL))
2437 (
errcode(ERRCODE_INTERNAL_ERROR),
2454 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2472 bool stopsHere =
false;
2489 (
errmsg(
"recovery stopping after reaching consistency")));
2510 (
errmsg(
"recovery stopping before WAL location (LSN) \"%X/%X\"",
2600 (
errmsg(
"recovery stopping before commit of transaction %u, time %s",
2607 (
errmsg(
"recovery stopping before abort of transaction %u, time %s",
2660 (
errmsg(
"recovery stopping at restore point \"%s\", time %s",
2678 (
errmsg(
"recovery stopping after WAL location (LSN) \"%X/%X\"",
2683 if (rmid != RM_XACT_ID)
2745 (
errmsg(
"recovery stopping after commit of transaction %u, time %s",
2753 (
errmsg(
"recovery stopping after abort of transaction %u, time %s",
2765 (
errmsg(
"recovery stopping after reaching consistency")));
2789 "%s transaction %u",
2804 "at restore point \"%s\"",
2807 snprintf(reason,
sizeof(reason),
"reached consistency");
2809 snprintf(reason,
sizeof(reason),
"no recovery target specified");
2834 (
errmsg(
"pausing at the end of recovery"),
2835 errhint(
"Execute pg_wal_replay_resume() to promote.")));
2838 (
errmsg(
"recovery has paused"),
2839 errhint(
"Execute pg_wal_replay_resume() to continue.")));
2953 elog(
DEBUG2,
"recovery apply delay %ld milliseconds", msecs);
3036 private->fetching_ckpt = fetching_ckpt;
3037 private->emode = emode;
3039 private->replayTLI = replayTLI;
3102 (
errmsg(
"unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
3136 (
errmsg_internal(
"reached end of WAL in pg_wal, entering archive recovery")));
3200 int emode = private->emode;
3249 private->randAccess,
3250 private->fetching_ckpt,
3284 if (((targetPagePtr) / XLOG_BLCKSZ) != (
flushedUpto / XLOG_BLCKSZ))
3298 if (r != XLOG_BLCKSZ)
3301 int save_errno = errno;
3310 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: %m",
3317 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu",
3320 goto next_record_is_invalid;
3375 goto next_record_is_invalid;
3380 next_record_is_invalid:
3445 bool streaming_reply_sent =
false;
3485 bool startWalReceiver =
false;
3532 startWalReceiver =
true;
3595 elog(
LOG,
"waiting for WAL to become available at %X/%X",
3612 last_fail_time =
now;
3632 elog(
DEBUG2,
"switched WAL source from %s to %s after %s",
3706 startWalReceiver =
true;
3719 if (startWalReceiver &&
3741 elog(
ERROR,
"according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3784 if (latestChunkStart <= RecPtr)
3861 if (!streaming_reply_sent)
3864 streaming_reply_sent =
true;
3933 if (RecPtr == lastComplaint)
3936 lastComplaint = RecPtr;
3957 (
errmsg(
"invalid checkpoint location")));
3967 (
errmsg(
"invalid checkpoint record")));
3970 if (record->
xl_rmid != RM_XLOG_ID)
3973 (
errmsg(
"invalid resource manager ID in checkpoint record")));
3981 (
errmsg(
"invalid xl_info in checkpoint record")));
3987 (
errmsg(
"invalid length of checkpoint record")));
4003 List *newExpectedTLEs;
4028 foreach(cell, newExpectedTLEs)
4041 (
errmsg(
"new timeline %u is not a child of database system timeline %u",
4052 if (currentTle->
end < replayLSN)
4055 (
errmsg(
"new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
4074 (
errmsg(
"new target timeline is %u",
4102 snprintf(activitymsg,
sizeof(activitymsg),
"waiting for %s",
4144 snprintf(activitymsg,
sizeof(activitymsg),
"recovering %s",
4157 if (errno != ENOENT || !notfoundOk)
4160 errmsg(
"could not open file \"%s\": %m", path)));
4228 if (segno < beginseg)
4238 elog(
DEBUG1,
"got WAL segment from archive");
4263 errmsg(
"could not open file \"%s\": %m", path)));
4277 (
errmsg(
"WAL receiver process shutdown requested")));
4362 struct stat stat_buf;
4470 *replayEndTLI = tli;
4558 if (currValue < minValue)
4562 bool warned_for_promote =
false;
4565 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4566 errmsg(
"hot standby is not possible because of insufficient parameter settings"),
4567 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4575 (
errmsg(
"recovery has paused"),
4576 errdetail(
"If recovery is unpaused, the server will shut down."),
4577 errhint(
"You can then restart the server after making the necessary configuration changes.")));
4585 if (!warned_for_promote)
4587 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4588 errmsg(
"promotion is not possible because of insufficient parameter settings"),
4594 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4598 errhint(
"Restart the server after making the necessary configuration changes.")));
4599 warned_for_promote =
true;
4621 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4622 errmsg(
"recovery aborted because of insufficient parameter settings"),
4624 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4628 errhint(
"You can restart the server after making the necessary configuration changes.")));
4666 error_multiple_recovery_targets(
void)
4669 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4670 errmsg(
"multiple recovery targets specified"),
4671 errdetail(
"At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set.")));
4680 if (strcmp(*
newval,
"immediate") != 0 && strcmp(*
newval,
"") != 0)
4696 error_multiple_recovery_targets();
4710 if (strcmp(*
newval,
"") != 0)
4714 bool have_error =
false;
4722 *extra = (
void *) myextra;
4735 error_multiple_recovery_targets();
4770 error_multiple_recovery_targets();
4793 if (strcmp(*
newval,
"") != 0)
4796 if (strcmp(*
newval,
"now") == 0 ||
4797 strcmp(*
newval,
"today") == 0 ||
4798 strcmp(*
newval,
"tomorrow") == 0 ||
4799 strcmp(*
newval,
"yesterday") == 0)
4826 &dtype,
tm, &fsec, &tz, &dtextra);
4850 error_multiple_recovery_targets();
4867 if (strcmp(*
newval,
"current") == 0)
4869 else if (strcmp(*
newval,
"latest") == 0)
4876 strtoul(*
newval, NULL, 0);
4877 if (errno == EINVAL || errno == ERANGE)
4886 *extra = (
void *) myextra;
4910 if (strcmp(*
newval,
"") != 0)
4917 if (errno == EINVAL || errno == ERANGE)
4922 *extra = (
void *) myextra;
4935 error_multiple_recovery_targets();
TimeLineID findNewestTimeLine(TimeLineID startTLI)
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
bool existsTimeLineHistory(TimeLineID probeTLI)
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
List * readTimeLineHistory(TimeLineID targetTLI)
bool tliInHistory(TimeLineID tli, List *expectedTLEs)
void remove_tablespace_symlink(const char *linkloc)
bool allow_in_place_tablespaces
void HandleStartupProcInterrupts(void)
void disable_startup_progress_timeout(void)
bool IsPromoteSignaled(void)
void begin_startup_progress_phase(void)
void ResetPromoteSignaled(void)
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Datum timestamptz_in(PG_FUNCTION_ARGS)
TimestampTz GetCurrentTimestamp(void)
Datum now(PG_FUNCTION_ARGS)
const char * timestamptz_to_str(TimestampTz t)
void UnlockReleaseBuffer(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
static Page BufferGetPage(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
static bool BufferIsValid(Buffer bufnum)
static XLogRecPtr PageGetLSN(Page page)
#define strtou64(str, endptr, base)
#define PG_USED_FOR_ASSERTS_ONLY
void RequestCheckpoint(int flags)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableCancelSleep(void)
elog(ERROR, "%s: %s", p2, msg)
int errmsg_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
ErrorContextCallback * error_context_stack
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
struct dirent * ReadDir(DIR *dir, const char *dirname)
FILE * AllocateFile(const char *name, const char *mode)
int BasicOpenFilePerm(const char *fileName, int fileFlags, mode_t fileMode)
int durable_rename(const char *oldfile, const char *newfile, int elevel)
int BasicOpenFile(const char *fileName, int fileFlags)
DIR * AllocateDir(const char *dirname)
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
bool IsPostmasterEnvironment
void * guc_malloc(int elevel, size_t size)
#define GUC_check_errdetail
int trace_recovery_messages
void OwnLatch(Latch *latch)
void DisownLatch(Latch *latch)
void InitSharedLatch(Latch *latch)
void SetLatch(Latch *latch)
void ResetLatch(Latch *latch)
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
#define WL_EXIT_ON_PM_DEATH
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
void list_free_deep(List *list)
char * pstrdup(const char *in)
void pfree(void *pointer)
void * palloc0(Size size)
#define AmStartupProcess()
#define IsBootstrapProcessingMode()
#define ERRCODE_DATA_CORRUPTED
#define XLOG_RESTORE_POINT
#define XLOG_OVERWRITE_CONTRECORD
@ DB_SHUTDOWNED_IN_RECOVERY
#define XLOG_CHECKPOINT_SHUTDOWN
#define XLOG_CHECKPOINT_ONLINE
#define XLOG_END_OF_RECOVERY
XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error)
static rewind_source * source
const char * pg_rusage_show(const PGRUsage *ru0)
void pg_rusage_init(PGRUsage *ru0)
void SendPostmasterSignal(PMSignalReason reason)
@ PMSIGNAL_RECOVERY_STARTED
@ PMSIGNAL_BEGIN_HOT_STANDBY
size_t strlcpy(char *dst, const char *src, size_t siz)
static Datum ObjectIdGetDatum(Oid X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
static int fd(const char *x, int i)
void RecordKnownAssignedTransactionIds(TransactionId xid)
void KnownAssignedTransactionIdsIdleMaintenance(void)
static void set_ps_display(const char *activity)
char * psprintf(const char *fmt,...)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
bool ReplicationSlotValidateName(const char *name, int elevel)
#define SpinLockInit(lock)
#define SpinLockRelease(lock)
#define SpinLockAcquire(lock)
#define ereport_startup_progress(msg,...)
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
MultiXactOffset nextMultiOffset
TransactionId newestCommitTsXid
TimeLineID PrevTimeLineID
TimeLineID ThisTimeLineID
FullTransactionId nextXid
TransactionId oldestCommitTsXid
XLogRecPtr backupStartPoint
CheckPoint checkPointCopy
XLogRecPtr backupEndPoint
XLogRecPtr minRecoveryPoint
TimeLineID minRecoveryPointTLI
bool standby_signal_file_found
XLogRecPtr lastPageBeginPtr
char * recoveryStopReason
XLogRecPtr missingContrecPtr
bool recovery_signal_file_found
struct ErrorContextCallback * previous
void(* callback)(void *arg)
void(* rm_mask)(char *pagedata, BlockNumber blkno)
void(* rm_redo)(XLogReaderState *record)
const char *(* rm_identify)(uint8 info)
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
XLogRecPtr missingContrecPtr
XLogRecPtr overwrittenRecPtr
ConditionVariable recoveryNotPausedCV
XLogRecPtr lastReplayedEndRecPtr
bool SharedHotStandbyActive
TimeLineID lastReplayedTLI
bool SharedPromoteIsTriggered
TimestampTz currentChunkStartTime
XLogRecPtr replayEndRecPtr
Latch recoveryWakeupLatch
TimestampTz recoveryLastXTime
RecoveryPauseState recoveryPauseState
XLogRecPtr lastReplayedReadRecPtr
TimeLineID PrevTimeLineID
TimeLineID ThisTimeLineID
TimestampTz overwrite_time
XLogRecPtr overwritten_lsn