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)
2010 elog(
FATAL,
"mismatching overwritten LSN %X/%X -> %X/%X",
2019 (
errmsg(
"successfully skipped missing contrecord at %X/%X, overwritten at %s",
2042 elog(
DEBUG1,
"end of backup record reached");
2047 elog(
DEBUG1,
"saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
2073 while ((de =
ReadDir(dir,
"pg_tblspc")) != NULL)
2078 if (strspn(de->
d_name,
"0123456789") != strlen(de->
d_name))
2086 errmsg(
"unexpected directory entry \"%s\" found in %s",
2087 de->
d_name,
"pg_tblspc/"),
2088 errdetail(
"All directory entries in pg_tblspc/ should be symbolic links."),
2089 errhint(
"Remove those directories, or set allow_in_place_tablespaces to ON transiently to let recovery complete.")));
2163 (
errmsg(
"consistent recovery state reached at %X/%X",
2264 &rlocator, &forknum, &blk, NULL))
2297 if (prevTLI != replayTLI)
2299 (
errmsg(
"unexpected previous timeline ID %u (current timeline ID %u) in checkpoint record",
2300 prevTLI, replayTLI)));
2308 (
errmsg(
"unexpected timeline ID %u (after %u) in checkpoint record",
2309 newTLI, replayTLI)));
2324 (
errmsg(
"unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
2397 &rlocator, &forknum, &blkno, NULL))
2456 (
errcode(ERRCODE_INTERNAL_ERROR),
2473 "inconsistent page found, rel %u/%u/%u, forknum %u, blkno %u",
2491 bool stopsHere =
false;
2508 (
errmsg(
"recovery stopping after reaching consistency")));
2529 (
errmsg(
"recovery stopping before WAL location (LSN) \"%X/%X\"",
2619 (
errmsg(
"recovery stopping before commit of transaction %u, time %s",
2626 (
errmsg(
"recovery stopping before abort of transaction %u, time %s",
2679 (
errmsg(
"recovery stopping at restore point \"%s\", time %s",
2697 (
errmsg(
"recovery stopping after WAL location (LSN) \"%X/%X\"",
2702 if (rmid != RM_XACT_ID)
2764 (
errmsg(
"recovery stopping after commit of transaction %u, time %s",
2772 (
errmsg(
"recovery stopping after abort of transaction %u, time %s",
2784 (
errmsg(
"recovery stopping after reaching consistency")));
2808 "%s transaction %u",
2823 "at restore point \"%s\"",
2826 snprintf(reason,
sizeof(reason),
"reached consistency");
2828 snprintf(reason,
sizeof(reason),
"no recovery target specified");
2853 (
errmsg(
"pausing at the end of recovery"),
2854 errhint(
"Execute pg_wal_replay_resume() to promote.")));
2857 (
errmsg(
"recovery has paused"),
2858 errhint(
"Execute pg_wal_replay_resume() to continue.")));
2879 WAIT_EVENT_RECOVERY_PAUSE);
2972 elog(
DEBUG2,
"recovery apply delay %ld milliseconds", msecs);
2977 WAIT_EVENT_RECOVERY_APPLY_DELAY);
3055 private->fetching_ckpt = fetching_ckpt;
3056 private->emode = emode;
3058 private->replayTLI = replayTLI;
3121 (
errmsg(
"unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
3155 (
errmsg_internal(
"reached end of WAL in pg_wal, entering archive recovery")));
3219 int emode = private->emode;
3268 private->randAccess,
3269 private->fetching_ckpt,
3303 if (((targetPagePtr) / XLOG_BLCKSZ) != (
flushedUpto / XLOG_BLCKSZ))
3317 if (r != XLOG_BLCKSZ)
3320 int save_errno = errno;
3329 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: %m",
3336 errmsg(
"could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu",
3339 goto next_record_is_invalid;
3394 goto next_record_is_invalid;
3399 next_record_is_invalid:
3464 bool streaming_reply_sent =
false;
3504 bool startWalReceiver =
false;
3551 startWalReceiver =
true;
3614 elog(
LOG,
"waiting for WAL to become available at %X/%X",
3624 WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL);
3631 last_fail_time =
now;
3651 elog(
DEBUG2,
"switched WAL source from %s to %s after %s",
3725 startWalReceiver =
true;
3738 if (startWalReceiver &&
3760 elog(
ERROR,
"according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
3803 if (latestChunkStart <= RecPtr)
3880 if (!streaming_reply_sent)
3883 streaming_reply_sent =
true;
3899 WAIT_EVENT_RECOVERY_WAL_STREAM);
3952 if (RecPtr == lastComplaint)
3955 lastComplaint = RecPtr;
3976 (
errmsg(
"invalid checkpoint location")));
3986 (
errmsg(
"invalid checkpoint record")));
3989 if (record->
xl_rmid != RM_XLOG_ID)
3992 (
errmsg(
"invalid resource manager ID in checkpoint record")));
4000 (
errmsg(
"invalid xl_info in checkpoint record")));
4006 (
errmsg(
"invalid length of checkpoint record")));
4022 List *newExpectedTLEs;
4047 foreach(cell, newExpectedTLEs)
4060 (
errmsg(
"new timeline %u is not a child of database system timeline %u",
4071 if (currentTle->
end < replayLSN)
4074 (
errmsg(
"new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
4093 (
errmsg(
"new target timeline is %u",
4121 snprintf(activitymsg,
sizeof(activitymsg),
"waiting for %s",
4163 snprintf(activitymsg,
sizeof(activitymsg),
"recovering %s",
4176 if (errno != ENOENT || !notfoundOk)
4179 errmsg(
"could not open file \"%s\": %m", path)));
4247 if (segno < beginseg)
4257 elog(
DEBUG1,
"got WAL segment from archive");
4282 errmsg(
"could not open file \"%s\": %m", path)));
4296 (
errmsg(
"WAL receiver process shutdown requested")));
4381 struct stat stat_buf;
4489 *replayEndTLI = tli;
4577 if (currValue < minValue)
4581 bool warned_for_promote =
false;
4584 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4585 errmsg(
"hot standby is not possible because of insufficient parameter settings"),
4586 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4594 (
errmsg(
"recovery has paused"),
4595 errdetail(
"If recovery is unpaused, the server will shut down."),
4596 errhint(
"You can then restart the server after making the necessary configuration changes.")));
4604 if (!warned_for_promote)
4606 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4607 errmsg(
"promotion is not possible because of insufficient parameter settings"),
4613 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4617 errhint(
"Restart the server after making the necessary configuration changes.")));
4618 warned_for_promote =
true;
4634 WAIT_EVENT_RECOVERY_PAUSE);
4640 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4641 errmsg(
"recovery aborted because of insufficient parameter settings"),
4643 errdetail(
"%s = %d is a lower setting than on the primary server, where its value was %d.",
4647 errhint(
"You can restart the server after making the necessary configuration changes.")));
4685 error_multiple_recovery_targets(
void)
4688 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4689 errmsg(
"multiple recovery targets specified"),
4690 errdetail(
"At most one of recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time, recovery_target_xid may be set.")));
4699 if (strcmp(*
newval,
"immediate") != 0 && strcmp(*
newval,
"") != 0)
4715 error_multiple_recovery_targets();
4729 if (strcmp(*
newval,
"") != 0)
4733 bool have_error =
false;
4741 *extra = (
void *) myextra;
4754 error_multiple_recovery_targets();
4789 error_multiple_recovery_targets();
4812 if (strcmp(*
newval,
"") != 0)
4815 if (strcmp(*
newval,
"now") == 0 ||
4816 strcmp(*
newval,
"today") == 0 ||
4817 strcmp(*
newval,
"tomorrow") == 0 ||
4818 strcmp(*
newval,
"yesterday") == 0)
4845 &dtype,
tm, &fsec, &tz, &dtextra);
4869 error_multiple_recovery_targets();
4886 if (strcmp(*
newval,
"current") == 0)
4888 else if (strcmp(*
newval,
"latest") == 0)
4895 strtoul(*
newval, NULL, 0);
4896 if (errno == EINVAL || errno == ERANGE)
4905 *extra = (
void *) myextra;
4929 if (strcmp(*
newval,
"") != 0)
4936 if (errno == EINVAL || errno == ERANGE)
4941 *extra = (
void *) myextra;
4954 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 PG_USED_FOR_ASSERTS_ONLY
#define strtou64(str, endptr, base)
void RequestCheckpoint(int flags)
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
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