PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
xlogrecovery.h File Reference
#include "access/xlogreader.h"
#include "catalog/pg_control.h"
#include "lib/stringinfo.h"
#include "utils/timestamp.h"
Include dependency graph for xlogrecovery.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  EndOfWalRecoveryInfo
 

Typedefs

typedef enum RecoveryPauseState RecoveryPauseState
 

Enumerations

enum  RecoveryTargetType {
  RECOVERY_TARGET_UNSET , RECOVERY_TARGET_XID , RECOVERY_TARGET_TIME , RECOVERY_TARGET_NAME ,
  RECOVERY_TARGET_LSN , RECOVERY_TARGET_IMMEDIATE
}
 
enum  RecoveryTargetTimeLineGoal { RECOVERY_TARGET_TIMELINE_CONTROLFILE , RECOVERY_TARGET_TIMELINE_LATEST , RECOVERY_TARGET_TIMELINE_NUMERIC }
 
enum  RecoveryPauseState { RECOVERY_NOT_PAUSED , RECOVERY_PAUSE_REQUESTED , RECOVERY_PAUSED }
 

Functions

Size XLogRecoveryShmemSize (void)
 
void XLogRecoveryShmemInit (void)
 
void InitWalRecovery (ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
 
void PerformWalRecovery (void)
 
EndOfWalRecoveryInfoFinishWalRecovery (void)
 
void ShutdownWalRecovery (void)
 
void RemovePromoteSignalFiles (void)
 
bool HotStandbyActive (void)
 
XLogRecPtr GetXLogReplayRecPtr (TimeLineID *replayTLI)
 
RecoveryPauseState GetRecoveryPauseState (void)
 
void SetRecoveryPause (bool recoveryPause)
 
void GetXLogReceiptTime (TimestampTz *rtime, bool *fromStream)
 
TimestampTz GetLatestXTime (void)
 
TimestampTz GetCurrentChunkReplayStartTime (void)
 
XLogRecPtr GetCurrentReplayRecPtr (TimeLineID *replayEndTLI)
 
bool PromoteIsTriggered (void)
 
bool CheckPromoteSignal (void)
 
void WakeupRecovery (void)
 
void StartupRequestWalReceiverRestart (void)
 
void XLogRequestWalReceiverReply (void)
 
void RecoveryRequiresIntParameter (const char *param_name, int currValue, int minValue)
 
void xlog_outdesc (StringInfo buf, XLogReaderState *record)
 

Variables

PGDLLIMPORT bool recoveryTargetInclusive
 
PGDLLIMPORT int recoveryTargetAction
 
PGDLLIMPORT int recovery_min_apply_delay
 
PGDLLIMPORT char * PrimaryConnInfo
 
PGDLLIMPORT char * PrimarySlotName
 
PGDLLIMPORT char * recoveryRestoreCommand
 
PGDLLIMPORT char * recoveryEndCommand
 
PGDLLIMPORT char * archiveCleanupCommand
 
PGDLLIMPORT TransactionId recoveryTargetXid
 
PGDLLIMPORT char * recovery_target_time_string
 
PGDLLIMPORT TimestampTz recoveryTargetTime
 
PGDLLIMPORT const char * recoveryTargetName
 
PGDLLIMPORT XLogRecPtr recoveryTargetLSN
 
PGDLLIMPORT RecoveryTargetType recoveryTarget
 
PGDLLIMPORT bool wal_receiver_create_temp_slot
 
PGDLLIMPORT RecoveryTargetTimeLineGoal recoveryTargetTimeLineGoal
 
PGDLLIMPORT TimeLineID recoveryTargetTLIRequested
 
PGDLLIMPORT TimeLineID recoveryTargetTLI
 
PGDLLIMPORT bool reachedConsistency
 
PGDLLIMPORT bool StandbyMode
 

Typedef Documentation

◆ RecoveryPauseState

Enumeration Type Documentation

◆ RecoveryPauseState

Enumerator
RECOVERY_NOT_PAUSED 
RECOVERY_PAUSE_REQUESTED 
RECOVERY_PAUSED 

Definition at line 44 of file xlogrecovery.h.

45{
46 RECOVERY_NOT_PAUSED, /* pause not requested */
47 RECOVERY_PAUSE_REQUESTED, /* pause requested, but not yet paused */
48 RECOVERY_PAUSED, /* recovery is paused */
RecoveryPauseState
Definition: xlogrecovery.h:45
@ RECOVERY_PAUSED
Definition: xlogrecovery.h:48
@ RECOVERY_NOT_PAUSED
Definition: xlogrecovery.h:46
@ RECOVERY_PAUSE_REQUESTED
Definition: xlogrecovery.h:47

◆ RecoveryTargetTimeLineGoal

Enumerator
RECOVERY_TARGET_TIMELINE_CONTROLFILE 
RECOVERY_TARGET_TIMELINE_LATEST 
RECOVERY_TARGET_TIMELINE_NUMERIC 

Definition at line 36 of file xlogrecovery.h.

◆ RecoveryTargetType

Enumerator
RECOVERY_TARGET_UNSET 
RECOVERY_TARGET_XID 
RECOVERY_TARGET_TIME 
RECOVERY_TARGET_NAME 
RECOVERY_TARGET_LSN 
RECOVERY_TARGET_IMMEDIATE 

Definition at line 23 of file xlogrecovery.h.

24{
RecoveryTargetType
Definition: xlogrecovery.h:24
@ RECOVERY_TARGET_IMMEDIATE
Definition: xlogrecovery.h:30
@ RECOVERY_TARGET_TIME
Definition: xlogrecovery.h:27
@ RECOVERY_TARGET_UNSET
Definition: xlogrecovery.h:25
@ RECOVERY_TARGET_XID
Definition: xlogrecovery.h:26
@ RECOVERY_TARGET_LSN
Definition: xlogrecovery.h:29
@ RECOVERY_TARGET_NAME
Definition: xlogrecovery.h:28

Function Documentation

◆ CheckPromoteSignal()

bool CheckPromoteSignal ( void  )

Definition at line 4463 of file xlogrecovery.c.

4464{
4465 struct stat stat_buf;
4466
4467 if (stat(PROMOTE_SIGNAL_FILE, &stat_buf) == 0)
4468 return true;
4469
4470 return false;
4471}
#define stat
Definition: win32_port.h:274
#define PROMOTE_SIGNAL_FILE
Definition: xlog.h:309

References PROMOTE_SIGNAL_FILE, and stat.

Referenced by CheckForStandbyTrigger(), and process_pm_pmsignal().

◆ FinishWalRecovery()

EndOfWalRecoveryInfo * FinishWalRecovery ( void  )

Definition at line 1458 of file xlogrecovery.c.

1459{
1461 XLogRecPtr lastRec;
1462 TimeLineID lastRecTLI;
1463 XLogRecPtr endOfLog;
1464
1465 /*
1466 * Kill WAL receiver, if it's still running, before we continue to write
1467 * the startup checkpoint and aborted-contrecord records. It will trump
1468 * over these records and subsequent ones if it's still alive when we
1469 * start writing WAL.
1470 */
1472
1473 /*
1474 * Shutdown the slot sync worker to drop any temporary slots acquired by
1475 * it and to prevent it from keep trying to fetch the failover slots.
1476 *
1477 * We do not update the 'synced' column in 'pg_replication_slots' system
1478 * view from true to false here, as any failed update could leave 'synced'
1479 * column false for some slots. This could cause issues during slot sync
1480 * after restarting the server as a standby. While updating the 'synced'
1481 * column after switching to the new timeline is an option, it does not
1482 * simplify the handling for the 'synced' column. Therefore, we retain the
1483 * 'synced' column as true after promotion as it may provide useful
1484 * information about the slot origin.
1485 */
1487
1488 /*
1489 * We are now done reading the xlog from stream. Turn off streaming
1490 * recovery to force fetching the files (which would be required at end of
1491 * recovery, e.g., timeline history file) from archive or pg_wal.
1492 *
1493 * Note that standby mode must be turned off after killing WAL receiver,
1494 * i.e., calling XLogShutdownWalRcv().
1495 */
1497 StandbyMode = false;
1498
1499 /*
1500 * Determine where to start writing WAL next.
1501 *
1502 * Re-fetch the last valid or last applied record, so we can identify the
1503 * exact endpoint of what we consider the valid portion of WAL. There may
1504 * be an incomplete continuation record after that, in which case
1505 * 'abortedRecPtr' and 'missingContrecPtr' are set and the caller will
1506 * write a special OVERWRITE_CONTRECORD message to mark that the rest of
1507 * it is intentionally missing. See CreateOverwriteContrecordRecord().
1508 *
1509 * An important side-effect of this is to load the last page into
1510 * xlogreader. The caller uses it to initialize the WAL for writing.
1511 */
1512 if (!InRecovery)
1513 {
1514 lastRec = CheckPointLoc;
1515 lastRecTLI = CheckPointTLI;
1516 }
1517 else
1518 {
1520 lastRecTLI = XLogRecoveryCtl->lastReplayedTLI;
1521 }
1523 (void) ReadRecord(xlogprefetcher, PANIC, false, lastRecTLI);
1524 endOfLog = xlogreader->EndRecPtr;
1525
1526 /*
1527 * Remember the TLI in the filename of the XLOG segment containing the
1528 * end-of-log. It could be different from the timeline that endOfLog
1529 * nominally belongs to, if there was a timeline switch in that segment,
1530 * and we were reading the old WAL from a segment belonging to a higher
1531 * timeline.
1532 */
1533 result->endOfLogTLI = xlogreader->seg.ws_tli;
1534
1536 {
1537 /*
1538 * We are no longer in archive recovery state.
1539 *
1540 * We are now done reading the old WAL. Turn off archive fetching if
1541 * it was active.
1542 */
1544 InArchiveRecovery = false;
1545
1546 /*
1547 * If the ending log segment is still open, close it (to avoid
1548 * problems on Windows with trying to rename or delete an open file).
1549 */
1550 if (readFile >= 0)
1551 {
1552 close(readFile);
1553 readFile = -1;
1554 }
1555 }
1556
1557 /*
1558 * Copy the last partial block to the caller, for initializing the WAL
1559 * buffer for appending new WAL.
1560 */
1561 if (endOfLog % XLOG_BLCKSZ != 0)
1562 {
1563 char *page;
1564 int len;
1565 XLogRecPtr pageBeginPtr;
1566
1567 pageBeginPtr = endOfLog - (endOfLog % XLOG_BLCKSZ);
1569
1570 /* Copy the valid part of the last block */
1571 len = endOfLog % XLOG_BLCKSZ;
1572 page = palloc(len);
1573 memcpy(page, xlogreader->readBuf, len);
1574
1575 result->lastPageBeginPtr = pageBeginPtr;
1576 result->lastPage = page;
1577 }
1578 else
1579 {
1580 /* There is no partial block to copy. */
1581 result->lastPageBeginPtr = endOfLog;
1582 result->lastPage = NULL;
1583 }
1584
1585 /*
1586 * Create a comment for the history file to explain why and where timeline
1587 * changed.
1588 */
1590
1591 result->lastRec = lastRec;
1592 result->lastRecTLI = lastRecTLI;
1593 result->endOfLog = endOfLog;
1594
1595 result->abortedRecPtr = abortedRecPtr;
1597
1600
1601 return result;
1602}
#define Assert(condition)
Definition: c.h:815
#define PANIC
Definition: elog.h:42
#define close(a)
Definition: win32.h:12
void * palloc(Size size)
Definition: mcxt.c:1317
const void size_t len
void ShutDownSlotSync(void)
Definition: slotsync.c:1561
XLogRecPtr lastPageBeginPtr
Definition: xlogrecovery.h:111
XLogRecPtr abortedRecPtr
Definition: xlogrecovery.h:120
XLogRecPtr missingContrecPtr
Definition: xlogrecovery.h:121
TimeLineID endOfLogTLI
Definition: xlogrecovery.h:109
TimeLineID ws_tli
Definition: xlogreader.h:49
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
WALOpenSegment seg
Definition: xlogreader.h:272
TimeLineID lastReplayedTLI
Definition: xlogrecovery.c:340
XLogRecPtr lastReplayedReadRecPtr
Definition: xlogrecovery.c:338
bool WalRcvStreaming(void)
int wal_segment_size
Definition: xlog.c:143
void XLogShutdownWalRcv(void)
Definition: xlog.c:9473
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
uint32 TimeLineID
Definition: xlogdefs.h:59
void XLogPrefetcherBeginRead(XLogPrefetcher *prefetcher, XLogRecPtr recPtr)
static char * getRecoveryStopReason(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
bool InArchiveRecovery
Definition: xlogrecovery.c:138
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:373
static XLogRecoveryCtlData * XLogRecoveryCtl
Definition: xlogrecovery.c:364
static uint32 readOff
Definition: xlogrecovery.c:232
static bool standby_signal_file_found
Definition: xlogrecovery.c:150
bool StandbyMode
Definition: xlogrecovery.c:147
static int readFile
Definition: xlogrecovery.c:230
static XLogRecPtr abortedRecPtr
Definition: xlogrecovery.c:372
static XLogRecord * ReadRecord(XLogPrefetcher *xlogprefetcher, int emode, bool fetching_ckpt, TimeLineID replayTLI)
static XLogRecPtr CheckPointLoc
Definition: xlogrecovery.c:167
static bool recovery_signal_file_found
Definition: xlogrecovery.c:151
static XLogPrefetcher * xlogprefetcher
Definition: xlogrecovery.c:191
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188
static TimeLineID CheckPointTLI
Definition: xlogrecovery.c:168
bool InRecovery
Definition: xlogutils.c:50

References abortedRecPtr, EndOfWalRecoveryInfo::abortedRecPtr, ArchiveRecoveryRequested, Assert, CheckPointLoc, CheckPointTLI, close, EndOfWalRecoveryInfo::endOfLog, EndOfWalRecoveryInfo::endOfLogTLI, XLogReaderState::EndRecPtr, getRecoveryStopReason(), InArchiveRecovery, InRecovery, EndOfWalRecoveryInfo::lastPage, EndOfWalRecoveryInfo::lastPageBeginPtr, EndOfWalRecoveryInfo::lastRec, EndOfWalRecoveryInfo::lastRecTLI, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, len, missingContrecPtr, EndOfWalRecoveryInfo::missingContrecPtr, palloc(), PANIC, XLogReaderState::readBuf, readFile, readOff, ReadRecord(), recovery_signal_file_found, EndOfWalRecoveryInfo::recovery_signal_file_found, EndOfWalRecoveryInfo::recoveryStopReason, XLogReaderState::seg, ShutDownSlotSync(), standby_signal_file_found, EndOfWalRecoveryInfo::standby_signal_file_found, StandbyMode, wal_segment_size, WalRcvStreaming(), WALOpenSegment::ws_tli, xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogRecoveryCtl, XLogSegmentOffset, and XLogShutdownWalRcv().

Referenced by StartupXLOG().

◆ GetCurrentChunkReplayStartTime()

TimestampTz GetCurrentChunkReplayStartTime ( void  )

Definition at line 4626 of file xlogrecovery.c.

4627{
4628 TimestampTz xtime;
4629
4633
4634 return xtime;
4635}
int64 TimestampTz
Definition: timestamp.h:39
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
TimestampTz currentChunkStartTime
Definition: xlogrecovery.c:356

References XLogRecoveryCtlData::currentChunkStartTime, XLogRecoveryCtlData::info_lck, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by GetReplicationApplyDelay().

◆ GetCurrentReplayRecPtr()

XLogRecPtr GetCurrentReplayRecPtr ( TimeLineID replayEndTLI)

Definition at line 4562 of file xlogrecovery.c.

4563{
4564 XLogRecPtr recptr;
4565 TimeLineID tli;
4566
4571
4572 if (replayEndTLI)
4573 *replayEndTLI = tli;
4574 return recptr;
4575}
TimeLineID replayEndTLI
Definition: xlogrecovery.c:348
XLogRecPtr replayEndRecPtr
Definition: xlogrecovery.c:347

References XLogRecoveryCtlData::info_lck, XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by UpdateMinRecoveryPoint(), and xlog_redo().

◆ GetLatestXTime()

◆ GetRecoveryPauseState()

◆ GetXLogReceiptTime()

void GetXLogReceiptTime ( TimestampTz rtime,
bool *  fromStream 
)

Definition at line 4642 of file xlogrecovery.c.

4643{
4644 /*
4645 * This must be executed in the startup process, since we don't export the
4646 * relevant state to shared memory.
4647 */
4649
4650 *rtime = XLogReceiptTime;
4651 *fromStream = (XLogReceiptSource == XLOG_FROM_STREAM);
4652}
static XLogSource XLogReceiptSource
Definition: xlogrecovery.c:259
@ XLOG_FROM_STREAM
Definition: xlogrecovery.c:214
static TimestampTz XLogReceiptTime
Definition: xlogrecovery.c:258

References Assert, InRecovery, XLOG_FROM_STREAM, XLogReceiptSource, and XLogReceiptTime.

Referenced by GetStandbyLimitTime().

◆ GetXLogReplayRecPtr()

◆ HotStandbyActive()

bool HotStandbyActive ( void  )

Definition at line 4502 of file xlogrecovery.c.

4503{
4504 /*
4505 * We check shared state each time only until Hot Standby is active. We
4506 * can't de-activate Hot Standby, so there's no need to keep checking
4507 * after the shared variable has once been seen true.
4508 */
4510 return true;
4511 else
4512 {
4513 /* spinlock is essential on machines with weak memory ordering! */
4517
4518 return LocalHotStandbyActive;
4519 }
4520}
static bool LocalHotStandbyActive
Definition: xlogrecovery.c:176

References XLogRecoveryCtlData::info_lck, LocalHotStandbyActive, XLogRecoveryCtlData::SharedHotStandbyActive, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by XLogWalRcvSendHSFeedback().

◆ InitWalRecovery()

void InitWalRecovery ( ControlFileData ControlFile,
bool *  wasShutdown_ptr,
bool *  haveBackupLabel_ptr,
bool *  haveTblspcMap_ptr 
)

Definition at line 512 of file xlogrecovery.c.

514{
515 XLogPageReadPrivate *private;
516 struct stat st;
517 bool wasShutdown;
518 XLogRecord *record;
519 DBState dbstate_at_startup;
520 bool haveTblspcMap = false;
521 bool haveBackupLabel = false;
522 CheckPoint checkPoint;
523 bool backupFromStandby = false;
524
525 dbstate_at_startup = ControlFile->state;
526
527 /*
528 * Initialize on the assumption we want to recover to the latest timeline
529 * that's active according to pg_control.
530 */
534 else
536
537 /*
538 * Check for signal files, and if so set up state for offline recovery
539 */
542
543 /*
544 * Take ownership of the wakeup latch if we're going to sleep during
545 * recovery, if required.
546 */
549
550 /*
551 * Set the WAL reading processor now, as it will be needed when reading
552 * the checkpoint record required (backup_label or not).
553 */
554 private = palloc0(sizeof(XLogPageReadPrivate));
555 xlogreader =
557 XL_ROUTINE(.page_read = &XLogPageRead,
558 .segment_open = NULL,
559 .segment_close = wal_segment_close),
560 private);
561 if (!xlogreader)
563 (errcode(ERRCODE_OUT_OF_MEMORY),
564 errmsg("out of memory"),
565 errdetail("Failed while allocating a WAL reading processor.")));
567
568 /*
569 * Set the WAL decode buffer size. This limits how far ahead we can read
570 * in the WAL.
571 */
573
574 /* Create a WAL prefetcher. */
576
577 /*
578 * Allocate two page buffers dedicated to WAL consistency checks. We do
579 * it this way, rather than just making static arrays, for two reasons:
580 * (1) no need to waste the storage in most instantiations of the backend;
581 * (2) a static char array isn't guaranteed to have any particular
582 * alignment, whereas palloc() will provide MAXALIGN'd storage.
583 */
584 replay_image_masked = (char *) palloc(BLCKSZ);
585 primary_image_masked = (char *) palloc(BLCKSZ);
586
587 /*
588 * Read the backup_label file. We want to run this part of the recovery
589 * process after checking for signal files and after performing validation
590 * of the recovery parameters.
591 */
593 &backupFromStandby))
594 {
595 List *tablespaces = NIL;
596
597 /*
598 * Archive recovery was requested, and thanks to the backup label
599 * file, we know how far we need to replay to reach consistency. Enter
600 * archive recovery directly.
601 */
602 InArchiveRecovery = true;
605
606 /*
607 * Omitting backup_label when creating a new replica, PITR node etc.
608 * unfortunately is a common cause of corruption. Logging that
609 * backup_label was used makes it a bit easier to exclude that as the
610 * cause of observed corruption.
611 *
612 * Do so before we try to read the checkpoint record (which can fail),
613 * as otherwise it can be hard to understand why a checkpoint other
614 * than ControlFile->checkPoint is used.
615 */
616 ereport(LOG,
617 (errmsg("starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
620 CheckPointTLI)));
621
622 /*
623 * When a backup_label file is present, we want to roll forward from
624 * the checkpoint it identifies, rather than using pg_control.
625 */
628 if (record != NULL)
629 {
630 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
631 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
633 (errmsg_internal("checkpoint record is at %X/%X",
635 InRecovery = true; /* force recovery even if SHUTDOWNED */
636
637 /*
638 * Make sure that REDO location exists. This may not be the case
639 * if there was a crash during an online backup, which left a
640 * backup_label around that references a WAL segment that's
641 * already been archived.
642 */
643 if (checkPoint.redo < CheckPointLoc)
644 {
646 if (!ReadRecord(xlogprefetcher, LOG, false,
647 checkPoint.ThisTimeLineID))
649 (errmsg("could not find redo location %X/%X referenced by checkpoint record at %X/%X",
651 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
652 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
653 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
655 }
656 }
657 else
658 {
660 (errmsg("could not locate required checkpoint record at %X/%X",
662 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
663 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
664 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
666 wasShutdown = false; /* keep compiler quiet */
667 }
668
669 /* Read the tablespace_map file if present and create symlinks. */
670 if (read_tablespace_map(&tablespaces))
671 {
672 ListCell *lc;
673
674 foreach(lc, tablespaces)
675 {
676 tablespaceinfo *ti = lfirst(lc);
677 char *linkloc;
678
679 linkloc = psprintf("%s/%u", PG_TBLSPC_DIR, ti->oid);
680
681 /*
682 * Remove the existing symlink if any and Create the symlink
683 * under PGDATA.
684 */
686
687 if (symlink(ti->path, linkloc) < 0)
690 errmsg("could not create symbolic link \"%s\": %m",
691 linkloc)));
692
693 pfree(ti->path);
694 pfree(ti);
695 }
696
697 /* tell the caller to delete it later */
698 haveTblspcMap = true;
699 }
700
701 /* tell the caller to delete it later */
702 haveBackupLabel = true;
703 }
704 else
705 {
706 /* No backup_label file has been found if we are here. */
707
708 /*
709 * If tablespace_map file is present without backup_label file, there
710 * is no use of such file. There is no harm in retaining it, but it
711 * is better to get rid of the map file so that we don't have any
712 * redundant file in data directory and it will avoid any sort of
713 * confusion. It seems prudent though to just rename the file out of
714 * the way rather than delete it completely, also we ignore any error
715 * that occurs in rename operation as even if map file is present
716 * without backup_label file, it is harmless.
717 */
718 if (stat(TABLESPACE_MAP, &st) == 0)
719 {
720 unlink(TABLESPACE_MAP_OLD);
722 ereport(LOG,
723 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
725 errdetail("File \"%s\" was renamed to \"%s\".",
727 else
728 ereport(LOG,
729 (errmsg("ignoring file \"%s\" because no file \"%s\" exists",
731 errdetail("Could not rename file \"%s\" to \"%s\": %m.",
733 }
734
735 /*
736 * It's possible that archive recovery was requested, but we don't
737 * know how far we need to replay the WAL before we reach consistency.
738 * This can happen for example if a base backup is taken from a
739 * running server using an atomic filesystem snapshot, without calling
740 * pg_backup_start/stop. Or if you just kill a running primary server
741 * and put it into archive recovery by creating a recovery signal
742 * file.
743 *
744 * Our strategy in that case is to perform crash recovery first,
745 * replaying all the WAL present in pg_wal, and only enter archive
746 * recovery after that.
747 *
748 * But usually we already know how far we need to replay the WAL (up
749 * to minRecoveryPoint, up to backupEndPoint, or until we see an
750 * end-of-backup record), and we can enter archive recovery directly.
751 */
757 {
758 InArchiveRecovery = true;
761 }
762
763 /*
764 * For the same reason as when starting up with backup_label present,
765 * emit a log message when we continue initializing from a base
766 * backup.
767 */
769 ereport(LOG,
770 (errmsg("restarting backup recovery with redo LSN %X/%X",
772
773 /* Get the last valid checkpoint record. */
780 if (record != NULL)
781 {
783 (errmsg_internal("checkpoint record is at %X/%X",
785 }
786 else
787 {
788 /*
789 * We used to attempt to go back to a secondary checkpoint record
790 * here, but only when not in standby mode. We now just fail if we
791 * can't read the last checkpoint because this allows us to
792 * simplify processing around checkpoints.
793 */
795 (errmsg("could not locate a valid checkpoint record at %X/%X",
797 }
798 memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
799 wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
800 }
801
803 {
805 ereport(LOG,
806 (errmsg("entering standby mode")));
808 ereport(LOG,
809 (errmsg("starting point-in-time recovery to XID %u",
812 ereport(LOG,
813 (errmsg("starting point-in-time recovery to %s",
816 ereport(LOG,
817 (errmsg("starting point-in-time recovery to \"%s\"",
820 ereport(LOG,
821 (errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
824 ereport(LOG,
825 (errmsg("starting point-in-time recovery to earliest consistent point")));
826 else
827 ereport(LOG,
828 (errmsg("starting archive recovery")));
829 }
830
831 /*
832 * If the location of the checkpoint record is not on the expected
833 * timeline in the history of the requested timeline, we cannot proceed:
834 * the backup is not part of the history of the requested timeline.
835 */
836 Assert(expectedTLEs); /* was initialized by reading checkpoint
837 * record */
840 {
841 XLogRecPtr switchpoint;
842
843 /*
844 * tliSwitchPoint will throw an error if the checkpoint's timeline is
845 * not in expectedTLEs at all.
846 */
849 (errmsg("requested timeline %u is not a child of this server's history",
851 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.",
854 LSN_FORMAT_ARGS(switchpoint))));
855 }
856
857 /*
858 * The min recovery point should be part of the requested timeline's
859 * history, too.
860 */
865 (errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
869
871 (errmsg_internal("redo record is at %X/%X; shutdown %s",
872 LSN_FORMAT_ARGS(checkPoint.redo),
873 wasShutdown ? "true" : "false")));
875 (errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
877 checkPoint.nextOid)));
879 (errmsg_internal("next MultiXactId: %u; next MultiXactOffset: %u",
880 checkPoint.nextMulti, checkPoint.nextMultiOffset)));
882 (errmsg_internal("oldest unfrozen transaction ID: %u, in database %u",
883 checkPoint.oldestXid, checkPoint.oldestXidDB)));
885 (errmsg_internal("oldest MultiXactId: %u, in database %u",
886 checkPoint.oldestMulti, checkPoint.oldestMultiDB)));
888 (errmsg_internal("commit timestamp Xid oldest/newest: %u/%u",
889 checkPoint.oldestCommitTsXid,
890 checkPoint.newestCommitTsXid)));
893 (errmsg("invalid next transaction ID")));
894
895 /* sanity check */
896 if (checkPoint.redo > CheckPointLoc)
898 (errmsg("invalid redo in checkpoint record")));
899
900 /*
901 * Check whether we need to force recovery from WAL. If it appears to
902 * have been a clean shutdown and we did not have a recovery signal file,
903 * then assume no recovery needed.
904 */
905 if (checkPoint.redo < CheckPointLoc)
906 {
907 if (wasShutdown)
909 (errmsg("invalid redo record in shutdown checkpoint")));
910 InRecovery = true;
911 }
912 else if (ControlFile->state != DB_SHUTDOWNED)
913 InRecovery = true;
915 {
916 /* force recovery due to presence of recovery signal file */
917 InRecovery = true;
918 }
919
920 /*
921 * If recovery is needed, update our in-memory copy of pg_control to show
922 * that we are recovering and to show the selected checkpoint as the place
923 * we are starting from. We also mark pg_control with any minimum recovery
924 * stop point obtained from a backup history file.
925 *
926 * We don't write the changes to disk yet, though. Only do that after
927 * initializing various subsystems.
928 */
929 if (InRecovery)
930 {
932 {
934 }
935 else
936 {
937 ereport(LOG,
938 (errmsg("database system was not properly shut down; "
939 "automatic recovery in progress")));
941 ereport(LOG,
942 (errmsg("crash recovery starts in timeline %u "
943 "and has target timeline %u",
947 }
949 ControlFile->checkPointCopy = checkPoint;
951 {
952 /* initialize minRecoveryPoint if not set yet */
953 if (ControlFile->minRecoveryPoint < checkPoint.redo)
954 {
955 ControlFile->minRecoveryPoint = checkPoint.redo;
957 }
958 }
959
960 /*
961 * Set backupStartPoint if we're starting recovery from a base backup.
962 *
963 * Also set backupEndPoint and use minRecoveryPoint as the backup end
964 * location if we're starting recovery from a base backup which was
965 * taken from a standby. In this case, the database system status in
966 * pg_control must indicate that the database was already in recovery.
967 * Usually that will be DB_IN_ARCHIVE_RECOVERY but also can be
968 * DB_SHUTDOWNED_IN_RECOVERY if recovery previously was interrupted
969 * before reaching this point; e.g. because restore_command or
970 * primary_conninfo were faulty.
971 *
972 * Any other state indicates that the backup somehow became corrupted
973 * and we can't sensibly continue with recovery.
974 */
975 if (haveBackupLabel)
976 {
977 ControlFile->backupStartPoint = checkPoint.redo;
979
980 if (backupFromStandby)
981 {
982 if (dbstate_at_startup != DB_IN_ARCHIVE_RECOVERY &&
983 dbstate_at_startup != DB_SHUTDOWNED_IN_RECOVERY)
985 (errmsg("backup_label contains data inconsistent with control file"),
986 errhint("This means that the backup is corrupted and you will "
987 "have to use another backup for recovery.")));
989 }
990 }
991 }
992
993 /* remember these, so that we know when we have reached consistency */
998 {
1001 }
1002 else
1003 {
1006 }
1007
1008 /*
1009 * Start recovery assuming that the final record isn't lost.
1010 */
1013
1014 *wasShutdown_ptr = wasShutdown;
1015 *haveBackupLabel_ptr = haveBackupLabel;
1016 *haveTblspcMap_ptr = haveTblspcMap;
1017}
TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)
Definition: timeline.c:544
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition: timeline.c:572
void remove_tablespace_symlink(const char *linkloc)
Definition: tablespace.c:883
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1843
#define UINT64_FORMAT
Definition: c.h:507
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode_for_file_access(void)
Definition: elog.c:876
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:781
char * DataDir
Definition: globals.c:70
void OwnLatch(Latch *latch)
Definition: latch.c:463
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
DBState
Definition: pg_control.h:90
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:96
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:93
@ DB_SHUTDOWNED
Definition: pg_control.h:92
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:95
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:68
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
#define PG_TBLSPC_DIR
Definition: relpath.h:41
Oid oldestMultiDB
Definition: pg_control.h:51
MultiXactId oldestMulti
Definition: pg_control.h:50
MultiXactOffset nextMultiOffset
Definition: pg_control.h:47
TransactionId newestCommitTsXid
Definition: pg_control.h:55
TransactionId oldestXid
Definition: pg_control.h:48
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:45
MultiXactId nextMulti
Definition: pg_control.h:46
FullTransactionId nextXid
Definition: pg_control.h:44
TransactionId oldestCommitTsXid
Definition: pg_control.h:53
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:49
XLogRecPtr backupStartPoint
Definition: pg_control.h:170
bool backupEndRequired
Definition: pg_control.h:172
CheckPoint checkPointCopy
Definition: pg_control.h:135
XLogRecPtr backupEndPoint
Definition: pg_control.h:171
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:168
XLogRecPtr checkPoint
Definition: pg_control.h:133
uint64 system_identifier
Definition: pg_control.h:110
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:169
Definition: pg_list.h:54
uint64 system_identifier
Definition: xlogreader.h:191
uint8 xl_info
Definition: xlogrecord.h:46
#define U64FromFullTransactionId(x)
Definition: transam.h:49
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define symlink(oldpath, newpath)
Definition: win32_port.h:225
int wal_decode_buffer_size
Definition: xlog.c:136
static ControlFileData * ControlFile
Definition: xlog.c:574
#define TABLESPACE_MAP_OLD
Definition: xlog.h:306
#define TABLESPACE_MAP
Definition: xlog.h:305
#define BACKUP_LABEL_FILE
Definition: xlog.h:302
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogPrefetcher * XLogPrefetcherAllocate(XLogReaderState *reader)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:106
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
Definition: xlogreader.c:90
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
static bool backupEndRequired
Definition: xlogrecovery.c:283
const char * recoveryTargetName
Definition: xlogrecovery.c:91
static XLogRecPtr minRecoveryPoint
Definition: xlogrecovery.c:278
static int XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *readBuf)
static XLogRecPtr backupEndPoint
Definition: xlogrecovery.c:282
static void validateRecoveryParameters(void)
static XLogRecord * ReadCheckpointRecord(XLogPrefetcher *xlogprefetcher, XLogRecPtr RecPtr, TimeLineID replayTLI)
static TimeLineID RedoStartTLI
Definition: xlogrecovery.c:170
static void readRecoverySignalFile(void)
XLogRecPtr recoveryTargetLSN
Definition: xlogrecovery.c:92
RecoveryTargetType recoveryTarget
Definition: xlogrecovery.c:85
static bool read_tablespace_map(List **tablespaces)
static bool read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI, bool *backupEndRequired, bool *backupFromStandby)
static List * expectedTLEs
Definition: xlogrecovery.c:123
static char * primary_image_masked
Definition: xlogrecovery.c:298
static TimeLineID minRecoveryPointTLI
Definition: xlogrecovery.c:279
TransactionId recoveryTargetXid
Definition: xlogrecovery.c:88
static char * replay_image_masked
Definition: xlogrecovery.c:297
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
static XLogRecPtr RedoStartLSN
Definition: xlogrecovery.c:169
static void EnableStandbyMode(void)
Definition: xlogrecovery.c:478
TimestampTz recoveryTargetTime
Definition: xlogrecovery.c:90
static bool StandbyModeRequested
Definition: xlogrecovery.c:146
static XLogRecPtr backupStartPoint
Definition: xlogrecovery.c:281
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:842

References abortedRecPtr, ArchiveRecoveryRequested, Assert, BACKUP_LABEL_FILE, backupEndPoint, ControlFileData::backupEndPoint, backupEndRequired, ControlFileData::backupEndRequired, backupStartPoint, ControlFileData::backupStartPoint, ControlFileData::checkPoint, ControlFileData::checkPointCopy, CheckPointLoc, CheckPointTLI, ControlFile, DataDir, DB_IN_ARCHIVE_RECOVERY, DB_IN_CRASH_RECOVERY, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DEBUG1, durable_rename(), EnableStandbyMode(), ereport, errcode(), errcode_for_file_access(), errdetail(), errhint(), errmsg(), errmsg_internal(), ERROR, expectedTLEs, FATAL, InArchiveRecovery, InRecovery, InvalidXLogRecPtr, lfirst, LOG, LSN_FORMAT_ARGS, minRecoveryPoint, ControlFileData::minRecoveryPoint, minRecoveryPointTLI, ControlFileData::minRecoveryPointTLI, missingContrecPtr, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, NIL, tablespaceinfo::oid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, OwnLatch(), palloc(), palloc0(), PANIC, tablespaceinfo::path, pfree(), PG_TBLSPC_DIR, primary_image_masked, psprintf(), read_backup_label(), read_tablespace_map(), ReadCheckpointRecord(), ReadRecord(), readRecoverySignalFile(), RECOVERY_TARGET_IMMEDIATE, RECOVERY_TARGET_LSN, RECOVERY_TARGET_NAME, RECOVERY_TARGET_TIME, RECOVERY_TARGET_XID, recoveryTarget, recoveryTargetLSN, recoveryTargetName, recoveryTargetTime, recoveryTargetTLI, recoveryTargetXid, XLogRecoveryCtlData::recoveryWakeupLatch, CheckPoint::redo, RedoStartLSN, RedoStartTLI, remove_tablespace_symlink(), replay_image_masked, StandbyModeRequested, stat, ControlFileData::state, symlink, XLogReaderState::system_identifier, ControlFileData::system_identifier, TABLESPACE_MAP, TABLESPACE_MAP_OLD, CheckPoint::ThisTimeLineID, timestamptz_to_str(), tliOfPointInHistory(), tliSwitchPoint(), TransactionIdIsNormal, U64FromFullTransactionId, UINT64_FORMAT, validateRecoveryParameters(), wal_decode_buffer_size, wal_segment_close(), wal_segment_size, XidFromFullTransactionId, XLogRecord::xl_info, XL_ROUTINE, XLOG_CHECKPOINT_SHUTDOWN, XLogPageRead(), xlogprefetcher, XLogPrefetcherAllocate(), XLogPrefetcherBeginRead(), xlogreader, XLogReaderAllocate(), XLogReaderSetDecodeBuffer(), XLogRecGetData, XLogRecoveryCtl, and XLogRecPtrIsInvalid.

Referenced by StartupXLOG().

◆ PerformWalRecovery()

void PerformWalRecovery ( void  )

Definition at line 1652 of file xlogrecovery.c.

1653{
1654 XLogRecord *record;
1655 bool reachedRecoveryTarget = false;
1656 TimeLineID replayTLI;
1657
1658 /*
1659 * Initialize shared variables for tracking progress of WAL replay, as if
1660 * we had just replayed the record before the REDO location (or the
1661 * checkpoint record itself, if it's a shutdown checkpoint).
1662 */
1665 {
1669 }
1670 else
1671 {
1675 }
1682
1683 /* Also ensure XLogReceiptTime has a sane value */
1685
1686 /*
1687 * Let postmaster know we've started redo now, so that it can launch the
1688 * archiver if necessary.
1689 */
1692
1693 /*
1694 * Allow read-only connections immediately if we're consistent already.
1695 */
1697
1698 /*
1699 * Find the first record that logically follows the checkpoint --- it
1700 * might physically precede it, though.
1701 */
1703 {
1704 /* back up to find the record */
1705 replayTLI = RedoStartTLI;
1707 record = ReadRecord(xlogprefetcher, PANIC, false, replayTLI);
1708
1709 /*
1710 * If a checkpoint record's redo pointer points back to an earlier
1711 * LSN, the record at that LSN should be an XLOG_CHECKPOINT_REDO
1712 * record.
1713 */
1714 if (record->xl_rmid != RM_XLOG_ID ||
1716 ereport(FATAL,
1717 (errmsg("unexpected record type found at redo point %X/%X",
1719 }
1720 else
1721 {
1722 /* just have to read next record after CheckPoint */
1724 replayTLI = CheckPointTLI;
1725 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1726 }
1727
1728 if (record != NULL)
1729 {
1730 TimestampTz xtime;
1731 PGRUsage ru0;
1732
1733 pg_rusage_init(&ru0);
1734
1735 InRedo = true;
1736
1737 RmgrStartup();
1738
1739 ereport(LOG,
1740 (errmsg("redo starts at %X/%X",
1742
1743 /* Prepare to report progress of the redo phase. */
1744 if (!StandbyMode)
1746
1747 /*
1748 * main redo apply loop
1749 */
1750 do
1751 {
1752 if (!StandbyMode)
1753 ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
1755
1756#ifdef WAL_DEBUG
1757 if (XLOG_DEBUG)
1758 {
1760
1762 appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
1765 xlog_outrec(&buf, xlogreader);
1766 appendStringInfoString(&buf, " - ");
1768 elog(LOG, "%s", buf.data);
1769 pfree(buf.data);
1770 }
1771#endif
1772
1773 /* Handle interrupt signals of startup process */
1775
1776 /*
1777 * Pause WAL replay, if requested by a hot-standby session via
1778 * SetRecoveryPause().
1779 *
1780 * Note that we intentionally don't take the info_lck spinlock
1781 * here. We might therefore read a slightly stale value of the
1782 * recoveryPause flag, but it can't be very stale (no worse than
1783 * the last spinlock we did acquire). Since a pause request is a
1784 * pretty asynchronous thing anyway, possibly responding to it one
1785 * WAL record later than we otherwise would is a minor issue, so
1786 * it doesn't seem worth adding another spinlock cycle to prevent
1787 * that.
1788 */
1789 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1791 recoveryPausesHere(false);
1792
1793 /*
1794 * Have we reached our recovery target?
1795 */
1797 {
1798 reachedRecoveryTarget = true;
1799 break;
1800 }
1801
1802 /*
1803 * If we've been asked to lag the primary, wait on latch until
1804 * enough time has passed.
1805 */
1807 {
1808 /*
1809 * We test for paused recovery again here. If user sets
1810 * delayed apply, it may be because they expect to pause
1811 * recovery in case of problems, so we must test again here
1812 * otherwise pausing during the delay-wait wouldn't work.
1813 */
1814 if (((volatile XLogRecoveryCtlData *) XLogRecoveryCtl)->recoveryPauseState !=
1816 recoveryPausesHere(false);
1817 }
1818
1819 /*
1820 * Apply the record
1821 */
1822 ApplyWalRecord(xlogreader, record, &replayTLI);
1823
1824 /* Exit loop if we reached inclusive recovery target */
1826 {
1827 reachedRecoveryTarget = true;
1828 break;
1829 }
1830
1831 /* Else, try to fetch the next WAL record */
1832 record = ReadRecord(xlogprefetcher, LOG, false, replayTLI);
1833 } while (record != NULL);
1834
1835 /*
1836 * end of main redo apply loop
1837 */
1838
1839 if (reachedRecoveryTarget)
1840 {
1841 if (!reachedConsistency)
1842 ereport(FATAL,
1843 (errmsg("requested recovery stop point is before consistent recovery point")));
1844
1845 /*
1846 * This is the last point where we can restart recovery with a new
1847 * recovery target, if we shutdown and begin again. After this,
1848 * Resource Managers may choose to do permanent corrective actions
1849 * at end of recovery.
1850 */
1851 switch (recoveryTargetAction)
1852 {
1854
1855 /*
1856 * exit with special return code to request shutdown of
1857 * postmaster. Log messages issued from postmaster.
1858 */
1859 proc_exit(3);
1860
1862 SetRecoveryPause(true);
1863 recoveryPausesHere(true);
1864
1865 /* drop into promote */
1866
1868 break;
1869 }
1870 }
1871
1872 RmgrCleanup();
1873
1874 ereport(LOG,
1875 (errmsg("redo done at %X/%X system usage: %s",
1877 pg_rusage_show(&ru0))));
1878 xtime = GetLatestXTime();
1879 if (xtime)
1880 ereport(LOG,
1881 (errmsg("last completed transaction was at log time %s",
1882 timestamptz_to_str(xtime))));
1883
1884 InRedo = false;
1885 }
1886 else
1887 {
1888 /* there are no WAL records following the checkpoint */
1889 ereport(LOG,
1890 (errmsg("redo is not required")));
1891 }
1892
1893 /*
1894 * This check is intentionally after the above log messages that indicate
1895 * how far recovery went.
1896 */
1899 !reachedRecoveryTarget)
1900 ereport(FATAL,
1901 (errcode(ERRCODE_CONFIG_FILE_ERROR),
1902 errmsg("recovery ended before configured recovery target was reached")));
1903}
void HandleStartupProcInterrupts(void)
Definition: startup.c:154
void begin_startup_progress_phase(void)
Definition: startup.c:343
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
#define elog(elevel,...)
Definition: elog.h:225
bool IsUnderPostmaster
Definition: globals.c:119
void proc_exit(int code)
Definition: ipc.c:104
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:82
const char * pg_rusage_show(const PGRUsage *ru0)
Definition: pg_rusage.c:40
void pg_rusage_init(PGRUsage *ru0)
Definition: pg_rusage.c:27
static char * buf
Definition: pg_test_fsync.c:72
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:165
@ PMSIGNAL_RECOVERY_STARTED
Definition: pmsignal.h:35
void RmgrStartup(void)
Definition: rmgr.c:58
void RmgrCleanup(void)
Definition: rmgr.c:74
#define ereport_startup_progress(msg,...)
Definition: startup.h:18
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
RmgrId xl_rmid
Definition: xlogrecord.h:47
@ RECOVERY_TARGET_ACTION_PAUSE
@ RECOVERY_TARGET_ACTION_PROMOTE
@ RECOVERY_TARGET_ACTION_SHUTDOWN
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool reachedConsistency
Definition: xlogrecovery.c:294
static bool recoveryStopsBefore(XLogReaderState *record)
int recoveryTargetAction
Definition: xlogrecovery.c:87
static bool recoveryApplyDelay(XLogReaderState *record)
static bool recoveryStopsAfter(XLogReaderState *record)
static void CheckRecoveryConsistency(void)
void SetRecoveryPause(bool recoveryPause)
void xlog_outdesc(StringInfo buf, XLogReaderState *record)
static bool InRedo
Definition: xlogrecovery.c:203
static void ApplyWalRecord(XLogReaderState *xlogreader, XLogRecord *record, TimeLineID *replayTLI)
static void recoveryPausesHere(bool endOfRecovery)
TimestampTz GetLatestXTime(void)

References appendStringInfo(), appendStringInfoString(), ApplyWalRecord(), ArchiveRecoveryRequested, Assert, begin_startup_progress_phase(), buf, CheckPointLoc, CheckPointTLI, CheckRecoveryConsistency(), XLogRecoveryCtlData::currentChunkStartTime, elog, XLogReaderState::EndRecPtr, ereport, ereport_startup_progress, errcode(), errmsg(), FATAL, GetCurrentTimestamp(), GetLatestXTime(), HandleStartupProcInterrupts(), XLogRecoveryCtlData::info_lck, initStringInfo(), InRedo, InvalidXLogRecPtr, IsUnderPostmaster, XLogRecoveryCtlData::lastReplayedEndRecPtr, XLogRecoveryCtlData::lastReplayedReadRecPtr, XLogRecoveryCtlData::lastReplayedTLI, LOG, LSN_FORMAT_ARGS, PANIC, pfree(), pg_rusage_init(), pg_rusage_show(), PMSIGNAL_RECOVERY_STARTED, proc_exit(), reachedConsistency, ReadRecord(), XLogReaderState::ReadRecPtr, RECOVERY_NOT_PAUSED, RECOVERY_TARGET_ACTION_PAUSE, RECOVERY_TARGET_ACTION_PROMOTE, RECOVERY_TARGET_ACTION_SHUTDOWN, RECOVERY_TARGET_UNSET, recoveryApplyDelay(), XLogRecoveryCtlData::recoveryLastXTime, recoveryPausesHere(), XLogRecoveryCtlData::recoveryPauseState, recoveryStopsAfter(), recoveryStopsBefore(), recoveryTarget, recoveryTargetAction, RedoStartLSN, RedoStartTLI, XLogRecoveryCtlData::replayEndRecPtr, XLogRecoveryCtlData::replayEndTLI, RmgrCleanup(), RmgrStartup(), SendPostmasterSignal(), SetRecoveryPause(), SpinLockAcquire, SpinLockRelease, StandbyMode, timestamptz_to_str(), XLogRecord::xl_info, XLogRecord::xl_rmid, XLOG_CHECKPOINT_REDO, xlog_outdesc(), xlogprefetcher, XLogPrefetcherBeginRead(), xlogreader, XLogReceiptTime, XLogRecoveryCtl, and XLR_INFO_MASK.

Referenced by StartupXLOG().

◆ PromoteIsTriggered()

bool PromoteIsTriggered ( void  )

Definition at line 4394 of file xlogrecovery.c.

4395{
4396 /*
4397 * We check shared state each time only until a standby promotion is
4398 * triggered. We can't trigger a promotion again, so there's no need to
4399 * keep checking after the shared variable has once been seen true.
4400 */
4402 return true;
4403
4407
4409}
static bool LocalPromoteIsTriggered
Definition: xlogrecovery.c:182

References XLogRecoveryCtlData::info_lck, LocalPromoteIsTriggered, XLogRecoveryCtlData::SharedPromoteIsTriggered, SpinLockAcquire, SpinLockRelease, and XLogRecoveryCtl.

Referenced by PerformRecoveryXLogAction(), pg_wal_replay_pause(), and pg_wal_replay_resume().

◆ RecoveryRequiresIntParameter()

void RecoveryRequiresIntParameter ( const char *  param_name,
int  currValue,
int  minValue 
)

Definition at line 4659 of file xlogrecovery.c.

4660{
4661 if (currValue < minValue)
4662 {
4664 {
4665 bool warned_for_promote = false;
4666
4668 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4669 errmsg("hot standby is not possible because of insufficient parameter settings"),
4670 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4671 param_name,
4672 currValue,
4673 minValue)));
4674
4675 SetRecoveryPause(true);
4676
4677 ereport(LOG,
4678 (errmsg("recovery has paused"),
4679 errdetail("If recovery is unpaused, the server will shut down."),
4680 errhint("You can then restart the server after making the necessary configuration changes.")));
4681
4683 {
4685
4687 {
4688 if (!warned_for_promote)
4690 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4691 errmsg("promotion is not possible because of insufficient parameter settings"),
4692
4693 /*
4694 * Repeat the detail from above so it's easy to find
4695 * in the log.
4696 */
4697 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4698 param_name,
4699 currValue,
4700 minValue),
4701 errhint("Restart the server after making the necessary configuration changes.")));
4702 warned_for_promote = true;
4703 }
4704
4705 /*
4706 * If recovery pause is requested then set it paused. While
4707 * we are in the loop, user might resume and pause again so
4708 * set this every time.
4709 */
4711
4712 /*
4713 * We wait on a condition variable that will wake us as soon
4714 * as the pause ends, but we use a timeout so we can check the
4715 * above conditions periodically too.
4716 */
4718 WAIT_EVENT_RECOVERY_PAUSE);
4719 }
4721 }
4722
4723 ereport(FATAL,
4724 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4725 errmsg("recovery aborted because of insufficient parameter settings"),
4726 /* Repeat the detail from above so it's easy to find in the log. */
4727 errdetail("%s = %d is a lower setting than on the primary server, where its value was %d.",
4728 param_name,
4729 currValue,
4730 minValue),
4731 errhint("You can restart the server after making the necessary configuration changes.")));
4732 }
4733}
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
#define WARNING
Definition: elog.h:36
ConditionVariable recoveryNotPausedCV
Definition: xlogrecovery.c:359
static bool CheckForStandbyTrigger(void)
static void ConfirmRecoveryPaused(void)
static bool HotStandbyActiveInReplay(void)
RecoveryPauseState GetRecoveryPauseState(void)

References CheckForStandbyTrigger(), ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), ConfirmRecoveryPaused(), ereport, errcode(), errdetail(), errhint(), errmsg(), FATAL, GetRecoveryPauseState(), HandleStartupProcInterrupts(), HotStandbyActiveInReplay(), LOG, RECOVERY_NOT_PAUSED, XLogRecoveryCtlData::recoveryNotPausedCV, SetRecoveryPause(), WARNING, and XLogRecoveryCtl.

Referenced by CheckRequiredParameterValues().

◆ RemovePromoteSignalFiles()

void RemovePromoteSignalFiles ( void  )

Definition at line 4454 of file xlogrecovery.c.

4455{
4456 unlink(PROMOTE_SIGNAL_FILE);
4457}

References PROMOTE_SIGNAL_FILE.

Referenced by CheckForStandbyTrigger(), and PostmasterMain().

◆ SetRecoveryPause()

◆ ShutdownWalRecovery()

void ShutdownWalRecovery ( void  )

Definition at line 1608 of file xlogrecovery.c.

1609{
1610 char recoveryPath[MAXPGPATH];
1611
1612 /* Final update of pg_stat_recovery_prefetch. */
1614
1615 /* Shut down xlogreader */
1616 if (readFile >= 0)
1617 {
1618 close(readFile);
1619 readFile = -1;
1620 }
1623
1625 {
1626 /*
1627 * Since there might be a partial WAL segment named RECOVERYXLOG, get
1628 * rid of it.
1629 */
1630 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYXLOG");
1631 unlink(recoveryPath); /* ignore any error */
1632
1633 /* Get rid of any remaining recovered timeline-history file, too */
1634 snprintf(recoveryPath, MAXPGPATH, XLOGDIR "/RECOVERYHISTORY");
1635 unlink(recoveryPath); /* ignore any error */
1636 }
1637
1638 /*
1639 * We don't need the latch anymore. It's not strictly necessary to disown
1640 * it, but let's do it for the sake of tidiness.
1641 */
1644}
void DisownLatch(Latch *latch)
Definition: latch.c:489
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define XLOGDIR
void XLogPrefetcherComputeStats(XLogPrefetcher *prefetcher)
void XLogPrefetcherFree(XLogPrefetcher *prefetcher)
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:161

References ArchiveRecoveryRequested, close, DisownLatch(), MAXPGPATH, readFile, XLogRecoveryCtlData::recoveryWakeupLatch, snprintf, XLOGDIR, xlogprefetcher, XLogPrefetcherComputeStats(), XLogPrefetcherFree(), xlogreader, XLogReaderFree(), and XLogRecoveryCtl.

Referenced by StartupXLOG().

◆ StartupRequestWalReceiverRestart()

void StartupRequestWalReceiverRestart ( void  )

Definition at line 4375 of file xlogrecovery.c.

4376{
4378 {
4379 ereport(LOG,
4380 (errmsg("WAL receiver process shutdown requested")));
4381
4382 pendingWalRcvRestart = true;
4383 }
4384}
bool WalRcvRunning(void)
static bool pendingWalRcvRestart
Definition: xlogrecovery.c:248
static XLogSource currentSource
Definition: xlogrecovery.c:246

References currentSource, ereport, errmsg(), LOG, pendingWalRcvRestart, WalRcvRunning(), and XLOG_FROM_STREAM.

Referenced by StartupRereadConfig().

◆ WakeupRecovery()

◆ xlog_outdesc()

void xlog_outdesc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 2299 of file xlogrecovery.c.

2300{
2301 RmgrData rmgr = GetRmgr(XLogRecGetRmid(record));
2302 uint8 info = XLogRecGetInfo(record);
2303 const char *id;
2304
2307
2308 id = rmgr.rm_identify(info);
2309 if (id == NULL)
2310 appendStringInfo(buf, "UNKNOWN (%X): ", info & ~XLR_INFO_MASK);
2311 else
2312 appendStringInfo(buf, "%s: ", id);
2313
2314 rmgr.rm_desc(buf, record);
2315}
uint8_t uint8
Definition: c.h:486
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
static RmgrData GetRmgr(RmgrId rmid)
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), buf, GetRmgr(), RmgrData::rm_desc, RmgrData::rm_identify, RmgrData::rm_name, XLogRecGetInfo, XLogRecGetRmid, and XLR_INFO_MASK.

Referenced by PerformWalRecovery(), rm_redo_error_callback(), and XLogInsertRecord().

◆ XLogRecoveryShmemInit()

void XLogRecoveryShmemInit ( void  )

Definition at line 458 of file xlogrecovery.c.

459{
460 bool found;
461
463 ShmemInitStruct("XLOG Recovery Ctl", XLogRecoveryShmemSize(), &found);
464 if (found)
465 return;
466 memset(XLogRecoveryCtl, 0, sizeof(XLogRecoveryCtlData));
467
471}
void ConditionVariableInit(ConditionVariable *cv)
void InitSharedLatch(Latch *latch)
Definition: latch.c:430
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:382
#define SpinLockInit(lock)
Definition: spin.h:57
Size XLogRecoveryShmemSize(void)
Definition: xlogrecovery.c:447

References ConditionVariableInit(), XLogRecoveryCtlData::info_lck, InitSharedLatch(), XLogRecoveryCtlData::recoveryNotPausedCV, XLogRecoveryCtlData::recoveryWakeupLatch, ShmemInitStruct(), SpinLockInit, XLogRecoveryCtl, and XLogRecoveryShmemSize().

Referenced by CreateOrAttachShmemStructs().

◆ XLogRecoveryShmemSize()

Size XLogRecoveryShmemSize ( void  )

Definition at line 447 of file xlogrecovery.c.

448{
449 Size size;
450
451 /* XLogRecoveryCtl */
452 size = sizeof(XLogRecoveryCtlData);
453
454 return size;
455}
size_t Size
Definition: c.h:562
static pg_noinline void Size size
Definition: slab.c:607
struct XLogRecoveryCtlData XLogRecoveryCtlData

References size.

Referenced by CalculateShmemSize(), and XLogRecoveryShmemInit().

◆ XLogRequestWalReceiverReply()

void XLogRequestWalReceiverReply ( void  )

Definition at line 4487 of file xlogrecovery.c.

4488{
4490}
static bool doRequestWalReceiverReply
Definition: xlogrecovery.c:185

References doRequestWalReceiverReply.

Referenced by xact_redo_commit().

Variable Documentation

◆ archiveCleanupCommand

PGDLLIMPORT char* archiveCleanupCommand
extern

Definition at line 84 of file xlogrecovery.c.

Referenced by CreateRestartPoint().

◆ PrimaryConnInfo

PGDLLIMPORT char* PrimaryConnInfo
extern

Definition at line 96 of file xlogrecovery.c.

◆ PrimarySlotName

PGDLLIMPORT char* PrimarySlotName
extern

Definition at line 97 of file xlogrecovery.c.

◆ reachedConsistency

◆ recovery_min_apply_delay

PGDLLIMPORT int recovery_min_apply_delay
extern

Definition at line 93 of file xlogrecovery.c.

Referenced by recoveryApplyDelay().

◆ recovery_target_time_string

PGDLLIMPORT char* recovery_target_time_string
extern

Definition at line 89 of file xlogrecovery.c.

Referenced by validateRecoveryParameters().

◆ recoveryEndCommand

PGDLLIMPORT char* recoveryEndCommand
extern

Definition at line 83 of file xlogrecovery.c.

Referenced by CleanupAfterArchiveRecovery().

◆ recoveryRestoreCommand

PGDLLIMPORT char* recoveryRestoreCommand
extern

Definition at line 82 of file xlogrecovery.c.

Referenced by RestoreArchivedFile(), and validateRecoveryParameters().

◆ recoveryTarget

◆ recoveryTargetAction

PGDLLIMPORT int recoveryTargetAction
extern

Definition at line 87 of file xlogrecovery.c.

Referenced by PerformWalRecovery(), and validateRecoveryParameters().

◆ recoveryTargetInclusive

PGDLLIMPORT bool recoveryTargetInclusive
extern

Definition at line 86 of file xlogrecovery.c.

Referenced by recoveryStopsAfter(), and recoveryStopsBefore().

◆ recoveryTargetLSN

PGDLLIMPORT XLogRecPtr recoveryTargetLSN
extern

◆ recoveryTargetName

PGDLLIMPORT const char* recoveryTargetName
extern

Definition at line 91 of file xlogrecovery.c.

Referenced by assign_recovery_target_name(), InitWalRecovery(), and recoveryStopsAfter().

◆ recoveryTargetTime

PGDLLIMPORT TimestampTz recoveryTargetTime
extern

Definition at line 90 of file xlogrecovery.c.

Referenced by InitWalRecovery(), recoveryStopsBefore(), and validateRecoveryParameters().

◆ recoveryTargetTimeLineGoal

◆ recoveryTargetTLI

◆ recoveryTargetTLIRequested

PGDLLIMPORT TimeLineID recoveryTargetTLIRequested
extern

Definition at line 121 of file xlogrecovery.c.

Referenced by assign_recovery_target_timeline(), and validateRecoveryParameters().

◆ recoveryTargetXid

PGDLLIMPORT TransactionId recoveryTargetXid
extern

◆ StandbyMode

◆ wal_receiver_create_temp_slot

PGDLLIMPORT bool wal_receiver_create_temp_slot
extern

Definition at line 98 of file xlogrecovery.c.

Referenced by StartupRereadConfig(), and WaitForWALToBecomeAvailable().