PostgreSQL Source Code  git master
xlog.h File Reference
#include "access/xlogbackup.h"
#include "access/xlogdefs.h"
#include "datatype/timestamp.h"
#include "lib/stringinfo.h"
#include "nodes/pg_list.h"
Include dependency graph for xlog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CheckpointStatsData
 

Macros

#define XLogArchivingActive()    (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode > ARCHIVE_MODE_OFF)
 
#define XLogArchivingAlways()    (AssertMacro(XLogArchiveMode == ARCHIVE_MODE_OFF || wal_level >= WAL_LEVEL_REPLICA), XLogArchiveMode == ARCHIVE_MODE_ALWAYS)
 
#define XLogIsNeeded()   (wal_level >= WAL_LEVEL_REPLICA)
 
#define XLogHintBitIsNeeded()   (DataChecksumsEnabled() || wal_log_hints)
 
#define XLogStandbyInfoActive()   (wal_level >= WAL_LEVEL_REPLICA)
 
#define XLogLogicalInfoActive()   (wal_level >= WAL_LEVEL_LOGICAL)
 
#define CHECKPOINT_IS_SHUTDOWN   0x0001 /* Checkpoint is for shutdown */
 
#define CHECKPOINT_END_OF_RECOVERY
 
#define CHECKPOINT_IMMEDIATE   0x0004 /* Do it without delays */
 
#define CHECKPOINT_FORCE   0x0008 /* Force even if no activity */
 
#define CHECKPOINT_FLUSH_ALL
 
#define CHECKPOINT_WAIT   0x0020 /* Wait for completion */
 
#define CHECKPOINT_REQUESTED   0x0040 /* Checkpoint request has been made */
 
#define CHECKPOINT_CAUSE_XLOG   0x0080 /* XLOG consumption */
 
#define CHECKPOINT_CAUSE_TIME   0x0100 /* Elapsed time */
 
#define XLOG_INCLUDE_ORIGIN   0x01 /* include the replication origin */
 
#define XLOG_MARK_UNIMPORTANT   0x02 /* record not important for durability */
 
#define RECOVERY_SIGNAL_FILE   "recovery.signal"
 
#define STANDBY_SIGNAL_FILE   "standby.signal"
 
#define BACKUP_LABEL_FILE   "backup_label"
 
#define BACKUP_LABEL_OLD   "backup_label.old"
 
#define TABLESPACE_MAP   "tablespace_map"
 
#define TABLESPACE_MAP_OLD   "tablespace_map.old"
 
#define PROMOTE_SIGNAL_FILE   "promote"
 

Typedefs

typedef enum WalSyncMethod WalSyncMethod
 
typedef enum ArchiveMode ArchiveMode
 
typedef enum WalLevel WalLevel
 
typedef enum WalCompression WalCompression
 
typedef enum RecoveryState RecoveryState
 
typedef struct CheckpointStatsData CheckpointStatsData
 
typedef enum WALAvailability WALAvailability
 
typedef enum SessionBackupState SessionBackupState
 

Enumerations

enum  WalSyncMethod {
  WAL_SYNC_METHOD_FSYNC = 0 , WAL_SYNC_METHOD_FDATASYNC , WAL_SYNC_METHOD_OPEN , WAL_SYNC_METHOD_FSYNC_WRITETHROUGH ,
  WAL_SYNC_METHOD_OPEN_DSYNC
}
 
enum  ArchiveMode { ARCHIVE_MODE_OFF = 0 , ARCHIVE_MODE_ON , ARCHIVE_MODE_ALWAYS }
 
enum  WalLevel { WAL_LEVEL_MINIMAL = 0 , WAL_LEVEL_REPLICA , WAL_LEVEL_LOGICAL }
 
enum  WalCompression { WAL_COMPRESSION_NONE = 0 , WAL_COMPRESSION_PGLZ , WAL_COMPRESSION_LZ4 , WAL_COMPRESSION_ZSTD }
 
enum  RecoveryState { RECOVERY_STATE_CRASH = 0 , RECOVERY_STATE_ARCHIVE , RECOVERY_STATE_DONE }
 
enum  WALAvailability {
  WALAVAIL_INVALID_LSN , WALAVAIL_RESERVED , WALAVAIL_EXTENDED , WALAVAIL_UNRESERVED ,
  WALAVAIL_REMOVED
}
 
enum  SessionBackupState { SESSION_BACKUP_NONE , SESSION_BACKUP_RUNNING }
 

Functions

XLogRecPtr XLogInsertRecord (struct XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
 
void XLogFlush (XLogRecPtr record)
 
bool XLogBackgroundFlush (void)
 
bool XLogNeedsFlush (XLogRecPtr record)
 
int XLogFileInit (XLogSegNo logsegno, TimeLineID logtli)
 
int XLogFileOpen (XLogSegNo segno, TimeLineID tli)
 
void CheckXLogRemoved (XLogSegNo segno, TimeLineID tli)
 
XLogSegNo XLogGetLastRemovedSegno (void)
 
void XLogSetAsyncXactLSN (XLogRecPtr asyncXactLSN)
 
void XLogSetReplicationSlotMinimumLSN (XLogRecPtr lsn)
 
void xlog_redo (struct XLogReaderState *record)
 
void xlog_desc (StringInfo buf, struct XLogReaderState *record)
 
const char * xlog_identify (uint8 info)
 
void issue_xlog_fsync (int fd, XLogSegNo segno, TimeLineID tli)
 
bool RecoveryInProgress (void)
 
RecoveryState GetRecoveryState (void)
 
bool XLogInsertAllowed (void)
 
XLogRecPtr GetXLogInsertRecPtr (void)
 
XLogRecPtr GetXLogWriteRecPtr (void)
 
uint64 GetSystemIdentifier (void)
 
char * GetMockAuthenticationNonce (void)
 
bool DataChecksumsEnabled (void)
 
XLogRecPtr GetFakeLSNForUnloggedRel (void)
 
Size XLOGShmemSize (void)
 
void XLOGShmemInit (void)
 
void BootStrapXLOG (void)
 
void InitializeWalConsistencyChecking (void)
 
void LocalProcessControlFile (bool reset)
 
WalLevel GetActiveWalLevelOnStandby (void)
 
void StartupXLOG (void)
 
void ShutdownXLOG (int code, Datum arg)
 
void CreateCheckPoint (int flags)
 
bool CreateRestartPoint (int flags)
 
WALAvailability GetWALAvailability (XLogRecPtr targetLSN)
 
void XLogPutNextOid (Oid nextOid)
 
XLogRecPtr XLogRestorePoint (const char *rpName)
 
void UpdateFullPageWrites (void)
 
void GetFullPageWriteInfo (XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
 
XLogRecPtr GetRedoRecPtr (void)
 
XLogRecPtr GetInsertRecPtr (void)
 
XLogRecPtr GetFlushRecPtr (TimeLineID *insertTLI)
 
TimeLineID GetWALInsertionTimeLine (void)
 
XLogRecPtr GetLastImportantRecPtr (void)
 
void SetWalWriterSleeping (bool sleeping)
 
void RemoveNonParentXlogFiles (XLogRecPtr switchpoint, TimeLineID newTLI)
 
bool XLogCheckpointNeeded (XLogSegNo new_segno)
 
void SwitchIntoArchiveRecovery (XLogRecPtr EndRecPtr, TimeLineID replayTLI)
 
void ReachedEndOfBackup (XLogRecPtr EndRecPtr, TimeLineID tli)
 
void SetInstallXLogFileSegmentActive (void)
 
bool IsInstallXLogFileSegmentActive (void)
 
void XLogShutdownWalRcv (void)
 
void do_pg_backup_start (const char *backupidstr, bool fast, List **tablespaces, BackupState *state, StringInfo tblspcmapfile)
 
void do_pg_backup_stop (BackupState *state, bool waitforarchive)
 
void do_pg_abort_backup (int code, Datum arg)
 
void register_persistent_abort_backup_handler (void)
 
SessionBackupState get_backup_status (void)
 

Variables

PGDLLIMPORT int wal_sync_method
 
PGDLLIMPORT XLogRecPtr ProcLastRecPtr
 
PGDLLIMPORT XLogRecPtr XactLastRecEnd
 
PGDLLIMPORT XLogRecPtr XactLastCommitEnd
 
PGDLLIMPORT int wal_segment_size
 
PGDLLIMPORT int min_wal_size_mb
 
PGDLLIMPORT int max_wal_size_mb
 
PGDLLIMPORT int wal_keep_size_mb
 
PGDLLIMPORT int max_slot_wal_keep_size_mb
 
PGDLLIMPORT int XLOGbuffers
 
PGDLLIMPORT int XLogArchiveTimeout
 
PGDLLIMPORT int wal_retrieve_retry_interval
 
PGDLLIMPORT char * XLogArchiveCommand
 
PGDLLIMPORT bool EnableHotStandby
 
PGDLLIMPORT bool fullPageWrites
 
PGDLLIMPORT bool wal_log_hints
 
PGDLLIMPORT int wal_compression
 
PGDLLIMPORT bool wal_init_zero
 
PGDLLIMPORT bool wal_recycle
 
PGDLLIMPORT boolwal_consistency_checking
 
PGDLLIMPORT char * wal_consistency_checking_string
 
PGDLLIMPORT bool log_checkpoints
 
PGDLLIMPORT bool track_wal_io_timing
 
PGDLLIMPORT int wal_decode_buffer_size
 
PGDLLIMPORT int CheckPointSegments
 
PGDLLIMPORT int XLogArchiveMode
 
PGDLLIMPORT int wal_level
 
PGDLLIMPORT CheckpointStatsData CheckpointStats
 

Macro Definition Documentation

◆ BACKUP_LABEL_FILE

#define BACKUP_LABEL_FILE   "backup_label"

Definition at line 294 of file xlog.h.

◆ BACKUP_LABEL_OLD

#define BACKUP_LABEL_OLD   "backup_label.old"

Definition at line 295 of file xlog.h.

◆ CHECKPOINT_CAUSE_TIME

#define CHECKPOINT_CAUSE_TIME   0x0100 /* Elapsed time */

Definition at line 147 of file xlog.h.

◆ CHECKPOINT_CAUSE_XLOG

#define CHECKPOINT_CAUSE_XLOG   0x0080 /* XLOG consumption */

Definition at line 146 of file xlog.h.

◆ CHECKPOINT_END_OF_RECOVERY

#define CHECKPOINT_END_OF_RECOVERY
Value:
0x0002 /* Like shutdown checkpoint, but
* issued at end of WAL recovery */

Definition at line 138 of file xlog.h.

◆ CHECKPOINT_FLUSH_ALL

#define CHECKPOINT_FLUSH_ALL
Value:
0x0010 /* Flush all pages, including those
* belonging to unlogged tables */

Definition at line 141 of file xlog.h.

◆ CHECKPOINT_FORCE

#define CHECKPOINT_FORCE   0x0008 /* Force even if no activity */

Definition at line 140 of file xlog.h.

◆ CHECKPOINT_IMMEDIATE

#define CHECKPOINT_IMMEDIATE   0x0004 /* Do it without delays */

Definition at line 139 of file xlog.h.

◆ CHECKPOINT_IS_SHUTDOWN

#define CHECKPOINT_IS_SHUTDOWN   0x0001 /* Checkpoint is for shutdown */

Definition at line 137 of file xlog.h.

◆ CHECKPOINT_REQUESTED

#define CHECKPOINT_REQUESTED   0x0040 /* Checkpoint request has been made */

Definition at line 144 of file xlog.h.

◆ CHECKPOINT_WAIT

#define CHECKPOINT_WAIT   0x0020 /* Wait for completion */

Definition at line 143 of file xlog.h.

◆ PROMOTE_SIGNAL_FILE

#define PROMOTE_SIGNAL_FILE   "promote"

Definition at line 301 of file xlog.h.

◆ RECOVERY_SIGNAL_FILE

#define RECOVERY_SIGNAL_FILE   "recovery.signal"

Definition at line 292 of file xlog.h.

◆ STANDBY_SIGNAL_FILE

#define STANDBY_SIGNAL_FILE   "standby.signal"

Definition at line 293 of file xlog.h.

◆ TABLESPACE_MAP

#define TABLESPACE_MAP   "tablespace_map"

Definition at line 297 of file xlog.h.

◆ TABLESPACE_MAP_OLD

#define TABLESPACE_MAP_OLD   "tablespace_map.old"

Definition at line 298 of file xlog.h.

◆ XLOG_INCLUDE_ORIGIN

#define XLOG_INCLUDE_ORIGIN   0x01 /* include the replication origin */

Definition at line 152 of file xlog.h.

◆ XLOG_MARK_UNIMPORTANT

#define XLOG_MARK_UNIMPORTANT   0x02 /* record not important for durability */

Definition at line 153 of file xlog.h.

◆ XLogArchivingActive

Definition at line 97 of file xlog.h.

◆ XLogArchivingAlways

Definition at line 100 of file xlog.h.

◆ XLogHintBitIsNeeded

#define XLogHintBitIsNeeded ( )    (DataChecksumsEnabled() || wal_log_hints)

Definition at line 118 of file xlog.h.

◆ XLogIsNeeded

#define XLogIsNeeded ( )    (wal_level >= WAL_LEVEL_REPLICA)

Definition at line 107 of file xlog.h.

◆ XLogLogicalInfoActive

#define XLogLogicalInfoActive ( )    (wal_level >= WAL_LEVEL_LOGICAL)

Definition at line 124 of file xlog.h.

◆ XLogStandbyInfoActive

#define XLogStandbyInfoActive ( )    (wal_level >= WAL_LEVEL_REPLICA)

Definition at line 121 of file xlog.h.

Typedef Documentation

◆ ArchiveMode

typedef enum ArchiveMode ArchiveMode

◆ CheckpointStatsData

◆ RecoveryState

◆ SessionBackupState

◆ WALAvailability

◆ WalCompression

◆ WalLevel

typedef enum WalLevel WalLevel

◆ WalSyncMethod

Enumeration Type Documentation

◆ ArchiveMode

Enumerator
ARCHIVE_MODE_OFF 
ARCHIVE_MODE_ON 
ARCHIVE_MODE_ALWAYS 

Definition at line 61 of file xlog.h.

62 {
63  ARCHIVE_MODE_OFF = 0, /* disabled */
64  ARCHIVE_MODE_ON, /* enabled while server is running normally */
65  ARCHIVE_MODE_ALWAYS, /* enabled always (even during recovery) */
66 } ArchiveMode;
ArchiveMode
Definition: xlog.h:62
@ ARCHIVE_MODE_ALWAYS
Definition: xlog.h:65
@ ARCHIVE_MODE_OFF
Definition: xlog.h:63
@ ARCHIVE_MODE_ON
Definition: xlog.h:64

◆ RecoveryState

Enumerator
RECOVERY_STATE_CRASH 
RECOVERY_STATE_ARCHIVE 
RECOVERY_STATE_DONE 

Definition at line 87 of file xlog.h.

88 {
89  RECOVERY_STATE_CRASH = 0, /* crash recovery */
90  RECOVERY_STATE_ARCHIVE, /* archive recovery */
91  RECOVERY_STATE_DONE, /* currently in production */
RecoveryState
Definition: xlog.h:88
@ RECOVERY_STATE_CRASH
Definition: xlog.h:89
@ RECOVERY_STATE_DONE
Definition: xlog.h:91
@ RECOVERY_STATE_ARCHIVE
Definition: xlog.h:90

◆ SessionBackupState

Enumerator
SESSION_BACKUP_NONE 
SESSION_BACKUP_RUNNING 

Definition at line 277 of file xlog.h.

280 {
@ SESSION_BACKUP_NONE
Definition: xlog.h:279

◆ WALAvailability

Enumerator
WALAVAIL_INVALID_LSN 
WALAVAIL_RESERVED 
WALAVAIL_EXTENDED 
WALAVAIL_UNRESERVED 
WALAVAIL_REMOVED 

Definition at line 184 of file xlog.h.

187 {
188  WALAVAIL_INVALID_LSN, /* parameter error */
189  WALAVAIL_RESERVED, /* WAL segment is within max_wal_size */
190  WALAVAIL_EXTENDED, /* WAL segment is reserved by a slot or
191  * wal_keep_size */
192  WALAVAIL_UNRESERVED, /* no longer reserved, but not removed yet */
@ WALAVAIL_RESERVED
Definition: xlog.h:187
@ WALAVAIL_UNRESERVED
Definition: xlog.h:190
@ WALAVAIL_EXTENDED
Definition: xlog.h:188
@ WALAVAIL_INVALID_LSN
Definition: xlog.h:186

◆ WalCompression

Enumerator
WAL_COMPRESSION_NONE 
WAL_COMPRESSION_PGLZ 
WAL_COMPRESSION_LZ4 
WAL_COMPRESSION_ZSTD 

Definition at line 78 of file xlog.h.

79 {
WalCompression
Definition: xlog.h:79
@ WAL_COMPRESSION_NONE
Definition: xlog.h:80
@ WAL_COMPRESSION_LZ4
Definition: xlog.h:82
@ WAL_COMPRESSION_PGLZ
Definition: xlog.h:81
@ WAL_COMPRESSION_ZSTD
Definition: xlog.h:83

◆ WalLevel

enum WalLevel
Enumerator
WAL_LEVEL_MINIMAL 
WAL_LEVEL_REPLICA 
WAL_LEVEL_LOGICAL 

Definition at line 70 of file xlog.h.

71 {
75 } WalLevel;
WalLevel
Definition: xlog.h:71
@ WAL_LEVEL_REPLICA
Definition: xlog.h:73
@ WAL_LEVEL_LOGICAL
Definition: xlog.h:74
@ WAL_LEVEL_MINIMAL
Definition: xlog.h:72

◆ WalSyncMethod

Enumerator
WAL_SYNC_METHOD_FSYNC 
WAL_SYNC_METHOD_FDATASYNC 
WAL_SYNC_METHOD_OPEN 
WAL_SYNC_METHOD_FSYNC_WRITETHROUGH 
WAL_SYNC_METHOD_OPEN_DSYNC 

Definition at line 22 of file xlog.h.

23 {
26  WAL_SYNC_METHOD_OPEN, /* for O_SYNC */
28  WAL_SYNC_METHOD_OPEN_DSYNC /* for O_DSYNC */
WalSyncMethod
Definition: xlog.h:23
@ WAL_SYNC_METHOD_OPEN
Definition: xlog.h:26
@ WAL_SYNC_METHOD_FDATASYNC
Definition: xlog.h:25
@ WAL_SYNC_METHOD_FSYNC_WRITETHROUGH
Definition: xlog.h:27
@ WAL_SYNC_METHOD_OPEN_DSYNC
Definition: xlog.h:28
@ WAL_SYNC_METHOD_FSYNC
Definition: xlog.h:24

Function Documentation

◆ BootStrapXLOG()

void BootStrapXLOG ( void  )

Definition at line 4760 of file xlog.c.

4761 {
4762  CheckPoint checkPoint;
4763  char *buffer;
4764  XLogPageHeader page;
4765  XLogLongPageHeader longpage;
4766  XLogRecord *record;
4767  char *recptr;
4768  uint64 sysidentifier;
4769  struct timeval tv;
4770  pg_crc32c crc;
4771 
4772  /* allow ordinary WAL segment creation, like StartupXLOG() would */
4774 
4775  /*
4776  * Select a hopefully-unique system identifier code for this installation.
4777  * We use the result of gettimeofday(), including the fractional seconds
4778  * field, as being about as unique as we can easily get. (Think not to
4779  * use random(), since it hasn't been seeded and there's no portable way
4780  * to seed it other than the system clock value...) The upper half of the
4781  * uint64 value is just the tv_sec part, while the lower half contains the
4782  * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
4783  * PID for a little extra uniqueness. A person knowing this encoding can
4784  * determine the initialization time of the installation, which could
4785  * perhaps be useful sometimes.
4786  */
4787  gettimeofday(&tv, NULL);
4788  sysidentifier = ((uint64) tv.tv_sec) << 32;
4789  sysidentifier |= ((uint64) tv.tv_usec) << 12;
4790  sysidentifier |= getpid() & 0xFFF;
4791 
4792  /* page buffer must be aligned suitably for O_DIRECT */
4793  buffer = (char *) palloc(XLOG_BLCKSZ + XLOG_BLCKSZ);
4794  page = (XLogPageHeader) TYPEALIGN(XLOG_BLCKSZ, buffer);
4795  memset(page, 0, XLOG_BLCKSZ);
4796 
4797  /*
4798  * Set up information for the initial checkpoint record
4799  *
4800  * The initial checkpoint record is written to the beginning of the WAL
4801  * segment with logid=0 logseg=1. The very first WAL segment, 0/0, is not
4802  * used, so that we can use 0/0 to mean "before any valid WAL segment".
4803  */
4804  checkPoint.redo = wal_segment_size + SizeOfXLogLongPHD;
4805  checkPoint.ThisTimeLineID = BootstrapTimeLineID;
4806  checkPoint.PrevTimeLineID = BootstrapTimeLineID;
4807  checkPoint.fullPageWrites = fullPageWrites;
4808  checkPoint.nextXid =
4810  checkPoint.nextOid = FirstGenbkiObjectId;
4811  checkPoint.nextMulti = FirstMultiXactId;
4812  checkPoint.nextMultiOffset = 0;
4813  checkPoint.oldestXid = FirstNormalTransactionId;
4814  checkPoint.oldestXidDB = Template1DbOid;
4815  checkPoint.oldestMulti = FirstMultiXactId;
4816  checkPoint.oldestMultiDB = Template1DbOid;
4819  checkPoint.time = (pg_time_t) time(NULL);
4821 
4822  TransamVariables->nextXid = checkPoint.nextXid;
4823  TransamVariables->nextOid = checkPoint.nextOid;
4825  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
4826  AdvanceOldestClogXid(checkPoint.oldestXid);
4827  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
4828  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
4830 
4831  /* Set up the XLOG page header */
4832  page->xlp_magic = XLOG_PAGE_MAGIC;
4833  page->xlp_info = XLP_LONG_HEADER;
4834  page->xlp_tli = BootstrapTimeLineID;
4836  longpage = (XLogLongPageHeader) page;
4837  longpage->xlp_sysid = sysidentifier;
4838  longpage->xlp_seg_size = wal_segment_size;
4839  longpage->xlp_xlog_blcksz = XLOG_BLCKSZ;
4840 
4841  /* Insert the initial checkpoint record */
4842  recptr = ((char *) page + SizeOfXLogLongPHD);
4843  record = (XLogRecord *) recptr;
4844  record->xl_prev = 0;
4845  record->xl_xid = InvalidTransactionId;
4846  record->xl_tot_len = SizeOfXLogRecord + SizeOfXLogRecordDataHeaderShort + sizeof(checkPoint);
4848  record->xl_rmid = RM_XLOG_ID;
4849  recptr += SizeOfXLogRecord;
4850  /* fill the XLogRecordDataHeaderShort struct */
4851  *(recptr++) = (char) XLR_BLOCK_ID_DATA_SHORT;
4852  *(recptr++) = sizeof(checkPoint);
4853  memcpy(recptr, &checkPoint, sizeof(checkPoint));
4854  recptr += sizeof(checkPoint);
4855  Assert(recptr - (char *) record == record->xl_tot_len);
4856 
4857  INIT_CRC32C(crc);
4858  COMP_CRC32C(crc, ((char *) record) + SizeOfXLogRecord, record->xl_tot_len - SizeOfXLogRecord);
4859  COMP_CRC32C(crc, (char *) record, offsetof(XLogRecord, xl_crc));
4860  FIN_CRC32C(crc);
4861  record->xl_crc = crc;
4862 
4863  /* Create first XLOG segment file */
4866 
4867  /*
4868  * We needn't bother with Reserve/ReleaseExternalFD here, since we'll
4869  * close the file again in a moment.
4870  */
4871 
4872  /* Write the first page with the initial record */
4873  errno = 0;
4874  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_WRITE);
4875  if (write(openLogFile, page, XLOG_BLCKSZ) != XLOG_BLCKSZ)
4876  {
4877  /* if write didn't set errno, assume problem is no disk space */
4878  if (errno == 0)
4879  errno = ENOSPC;
4880  ereport(PANIC,
4882  errmsg("could not write bootstrap write-ahead log file: %m")));
4883  }
4885 
4886  pgstat_report_wait_start(WAIT_EVENT_WAL_BOOTSTRAP_SYNC);
4887  if (pg_fsync(openLogFile) != 0)
4888  ereport(PANIC,
4890  errmsg("could not fsync bootstrap write-ahead log file: %m")));
4892 
4893  if (close(openLogFile) != 0)
4894  ereport(PANIC,
4896  errmsg("could not close bootstrap write-ahead log file: %m")));
4897 
4898  openLogFile = -1;
4899 
4900  /* Now create pg_control */
4901  InitControlFile(sysidentifier);
4902  ControlFile->time = checkPoint.time;
4903  ControlFile->checkPoint = checkPoint.redo;
4904  ControlFile->checkPointCopy = checkPoint;
4905 
4906  /* some additional ControlFile fields are set in WriteControlFile() */
4907  WriteControlFile();
4908 
4909  /* Bootstrap the commit log, too */
4910  BootStrapCLOG();
4914 
4915  pfree(buffer);
4916 
4917  /*
4918  * Force control file to be read - in contrast to normal processing we'd
4919  * otherwise never run the checks and GUC related initializations therein.
4920  */
4921  ReadControlFile();
4922 }
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:793
void BootStrapCLOG(void)
Definition: clog.c:721
void BootStrapCommitTs(void)
Definition: commit_ts.c:563
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition: commit_ts.c:870
int errcode_for_file_access(void)
Definition: elog.c:881
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define PANIC
Definition: elog.h:42
#define ereport(elevel,...)
Definition: elog.h:149
int pg_fsync(int fd)
Definition: fd.c:386
#define close(a)
Definition: win32.h:12
#define write(a, b, c)
Definition: win32.h:14
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
void MultiXactSetNextMXact(MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
Definition: multixact.c:2181
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2215
void BootStrapMultiXact(void)
Definition: multixact.c:1896
#define FirstMultiXactId
Definition: multixact.h:25
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:67
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:98
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
#define FIN_CRC32C(crc)
Definition: pg_crc32c.h:103
return crc
int64 pg_time_t
Definition: pgtime.h:23
Oid oldestMultiDB
Definition: pg_control.h:50
MultiXactId oldestMulti
Definition: pg_control.h:49
MultiXactOffset nextMultiOffset
Definition: pg_control.h:46
TransactionId newestCommitTsXid
Definition: pg_control.h:54
TransactionId oldestXid
Definition: pg_control.h:47
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:44
TransactionId oldestActiveXid
Definition: pg_control.h:63
bool fullPageWrites
Definition: pg_control.h:42
MultiXactId nextMulti
Definition: pg_control.h:45
FullTransactionId nextXid
Definition: pg_control.h:43
TransactionId oldestCommitTsXid
Definition: pg_control.h:52
pg_time_t time
Definition: pg_control.h:51
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:48
CheckPoint checkPointCopy
Definition: pg_control.h:134
pg_time_t time
Definition: pg_control.h:131
XLogRecPtr checkPoint
Definition: pg_control.h:132
FullTransactionId nextXid
Definition: transam.h:220
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
uint8 xl_info
Definition: xlogrecord.h:46
uint32 xl_tot_len
Definition: xlogrecord.h:43
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
void BootStrapSUBTRANS(void)
Definition: subtrans.c:221
#define InvalidTransactionId
Definition: transam.h:31
#define FirstGenbkiObjectId
Definition: transam.h:195
#define FirstNormalTransactionId
Definition: transam.h:34
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, Oid oldest_datoid)
Definition: varsup.c:372
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:355
TransamVariablesData * TransamVariables
Definition: varsup.c:34
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:88
static void pgstat_report_wait_end(void)
Definition: wait_event.h:104
int gettimeofday(struct timeval *tp, void *tzp)
int XLogFileInit(XLogSegNo logsegno, TimeLineID logtli)
Definition: xlog.c:3203
bool fullPageWrites
Definition: xlog.c:125
static void InitControlFile(uint64 sysidentifier)
Definition: xlog.c:3967
void SetInstallXLogFileSegmentActive(void)
Definition: xlog.c:9118
static int openLogFile
Definition: xlog.c:628
static void WriteControlFile(void)
Definition: xlog.c:4002
int wal_segment_size
Definition: xlog.c:146
static TimeLineID openLogTLI
Definition: xlog.c:630
static ControlFileData * ControlFile
Definition: xlog.c:580
#define BootstrapTimeLineID
Definition: xlog.c:114
static void ReadControlFile(void)
Definition: xlog.c:4084
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define SizeOfXLogRecordDataHeaderShort
Definition: xlogrecord.h:217
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:241
#define SizeOfXLogRecord
Definition: xlogrecord.h:55

References AdvanceOldestClogXid(), Assert(), BootStrapCLOG(), BootStrapCommitTs(), BootStrapMultiXact(), BootStrapSUBTRANS(), BootstrapTimeLineID, ControlFileData::checkPoint, ControlFileData::checkPointCopy, close, COMP_CRC32C, ControlFile, crc, ereport, errcode_for_file_access(), errmsg(), FIN_CRC32C, FirstGenbkiObjectId, FirstMultiXactId, FirstNormalTransactionId, fullPageWrites, CheckPoint::fullPageWrites, FullTransactionIdFromEpochAndXid(), gettimeofday(), INIT_CRC32C, InitControlFile(), InvalidTransactionId, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, TransamVariablesData::nextOid, CheckPoint::nextOid, TransamVariablesData::nextXid, CheckPoint::nextXid, TransamVariablesData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, openLogFile, openLogTLI, palloc(), PANIC, pfree(), pg_fsync(), pgstat_report_wait_end(), pgstat_report_wait_start(), CheckPoint::PrevTimeLineID, ReadControlFile(), CheckPoint::redo, SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetTransactionIdLimit(), SizeOfXLogLongPHD, SizeOfXLogRecord, SizeOfXLogRecordDataHeaderShort, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, TransamVariables, TYPEALIGN, wal_segment_size, write, WriteControlFile(), XLogRecord::xl_crc, XLogRecord::xl_info, XLogRecord::xl_prev, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLogRecord::xl_xid, XLOG_CHECKPOINT_SHUTDOWN, XLOG_PAGE_MAGIC, XLogFileInit(), XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, XLogLongPageHeaderData::xlp_xlog_blcksz, and XLR_BLOCK_ID_DATA_SHORT.

Referenced by BootstrapModeMain().

◆ CheckXLogRemoved()

void CheckXLogRemoved ( XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 3550 of file xlog.c.

3551 {
3552  int save_errno = errno;
3553  XLogSegNo lastRemovedSegNo;
3554 
3556  lastRemovedSegNo = XLogCtl->lastRemovedSegNo;
3558 
3559  if (segno <= lastRemovedSegNo)
3560  {
3561  char filename[MAXFNAMELEN];
3562 
3563  XLogFileName(filename, tli, segno, wal_segment_size);
3564  errno = save_errno;
3565  ereport(ERROR,
3567  errmsg("requested WAL segment %s has already been removed",
3568  filename)));
3569  }
3570  errno = save_errno;
3571 }
#define ERROR
Definition: elog.h:39
static char * filename
Definition: pg_dumpall.c:121
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
slock_t info_lck
Definition: xlog.c:559
XLogSegNo lastRemovedSegNo
Definition: xlog.c:470
static XLogCtlData * XLogCtl
Definition: xlog.c:572
#define MAXFNAMELEN
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
uint64 XLogSegNo
Definition: xlogdefs.h:48

References ereport, errcode_for_file_access(), errmsg(), ERROR, filename, XLogCtlData::info_lck, XLogCtlData::lastRemovedSegNo, MAXFNAMELEN, SpinLockAcquire, SpinLockRelease, wal_segment_size, XLogCtl, and XLogFileName().

Referenced by logical_read_xlog_page(), perform_base_backup(), and XLogSendPhysical().

◆ CreateCheckPoint()

void CreateCheckPoint ( int  flags)

Definition at line 6572 of file xlog.c.

6573 {
6574  bool shutdown;
6575  CheckPoint checkPoint;
6576  XLogRecPtr recptr;
6577  XLogSegNo _logSegNo;
6579  uint32 freespace;
6580  XLogRecPtr PriorRedoPtr;
6581  XLogRecPtr last_important_lsn;
6582  VirtualTransactionId *vxids;
6583  int nvxids;
6584  int oldXLogAllowed = 0;
6585 
6586  /*
6587  * An end-of-recovery checkpoint is really a shutdown checkpoint, just
6588  * issued at a different time.
6589  */
6591  shutdown = true;
6592  else
6593  shutdown = false;
6594 
6595  /* sanity check */
6596  if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
6597  elog(ERROR, "can't create a checkpoint during recovery");
6598 
6599  /*
6600  * Prepare to accumulate statistics.
6601  *
6602  * Note: because it is possible for log_checkpoints to change while a
6603  * checkpoint proceeds, we always accumulate stats, even if
6604  * log_checkpoints is currently off.
6605  */
6606  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
6608 
6609  /*
6610  * Let smgr prepare for checkpoint; this has to happen outside the
6611  * critical section and before we determine the REDO pointer. Note that
6612  * smgr must not do anything that'd have to be undone if we decide no
6613  * checkpoint is needed.
6614  */
6616 
6617  /*
6618  * Use a critical section to force system panic if we have trouble.
6619  */
6621 
6622  if (shutdown)
6623  {
6624  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6627  LWLockRelease(ControlFileLock);
6628  }
6629 
6630  /* Begin filling in the checkpoint WAL record */
6631  MemSet(&checkPoint, 0, sizeof(checkPoint));
6632  checkPoint.time = (pg_time_t) time(NULL);
6633 
6634  /*
6635  * For Hot Standby, derive the oldestActiveXid before we fix the redo
6636  * pointer. This allows us to begin accumulating changes to assemble our
6637  * starting snapshot of locks and transactions.
6638  */
6639  if (!shutdown && XLogStandbyInfoActive())
6641  else
6643 
6644  /*
6645  * Get location of last important record before acquiring insert locks (as
6646  * GetLastImportantRecPtr() also locks WAL locks).
6647  */
6648  last_important_lsn = GetLastImportantRecPtr();
6649 
6650  /*
6651  * If this isn't a shutdown or forced checkpoint, and if there has been no
6652  * WAL activity requiring a checkpoint, skip it. The idea here is to
6653  * avoid inserting duplicate checkpoints when the system is idle.
6654  */
6656  CHECKPOINT_FORCE)) == 0)
6657  {
6658  if (last_important_lsn == ControlFile->checkPoint)
6659  {
6660  END_CRIT_SECTION();
6661  ereport(DEBUG1,
6662  (errmsg_internal("checkpoint skipped because system is idle")));
6663  return;
6664  }
6665  }
6666 
6667  /*
6668  * An end-of-recovery checkpoint is created before anyone is allowed to
6669  * write WAL. To allow us to write the checkpoint record, temporarily
6670  * enable XLogInsertAllowed.
6671  */
6672  if (flags & CHECKPOINT_END_OF_RECOVERY)
6673  oldXLogAllowed = LocalSetXLogInsertAllowed();
6674 
6675  checkPoint.ThisTimeLineID = XLogCtl->InsertTimeLineID;
6676  if (flags & CHECKPOINT_END_OF_RECOVERY)
6677  checkPoint.PrevTimeLineID = XLogCtl->PrevTimeLineID;
6678  else
6679  checkPoint.PrevTimeLineID = checkPoint.ThisTimeLineID;
6680 
6681  /*
6682  * We must block concurrent insertions while examining insert state.
6683  */
6685 
6686  checkPoint.fullPageWrites = Insert->fullPageWrites;
6687 
6688  if (shutdown)
6689  {
6690  XLogRecPtr curInsert = XLogBytePosToRecPtr(Insert->CurrBytePos);
6691 
6692  /*
6693  * Compute new REDO record ptr = location of next XLOG record.
6694  *
6695  * Since this is a shutdown checkpoint, there can't be any concurrent
6696  * WAL insertion.
6697  */
6698  freespace = INSERT_FREESPACE(curInsert);
6699  if (freespace == 0)
6700  {
6701  if (XLogSegmentOffset(curInsert, wal_segment_size) == 0)
6702  curInsert += SizeOfXLogLongPHD;
6703  else
6704  curInsert += SizeOfXLogShortPHD;
6705  }
6706  checkPoint.redo = curInsert;
6707 
6708  /*
6709  * Here we update the shared RedoRecPtr for future XLogInsert calls;
6710  * this must be done while holding all the insertion locks.
6711  *
6712  * Note: if we fail to complete the checkpoint, RedoRecPtr will be
6713  * left pointing past where it really needs to point. This is okay;
6714  * the only consequence is that XLogInsert might back up whole buffers
6715  * that it didn't really need to. We can't postpone advancing
6716  * RedoRecPtr because XLogInserts that happen while we are dumping
6717  * buffers must assume that their buffer changes are not included in
6718  * the checkpoint.
6719  */
6720  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = checkPoint.redo;
6721  }
6722 
6723  /*
6724  * Now we can release the WAL insertion locks, allowing other xacts to
6725  * proceed while we are flushing disk buffers.
6726  */
6728 
6729  /*
6730  * If this is an online checkpoint, we have not yet determined the redo
6731  * point. We do so now by inserting the special XLOG_CHECKPOINT_REDO
6732  * record; the LSN at which it starts becomes the new redo pointer. We
6733  * don't do this for a shutdown checkpoint, because in that case no WAL
6734  * can be written between the redo point and the insertion of the
6735  * checkpoint record itself, so the checkpoint record itself serves to
6736  * mark the redo point.
6737  */
6738  if (!shutdown)
6739  {
6740  int dummy = 0;
6741 
6742  /* Record must have payload to avoid assertion failure. */
6743  XLogBeginInsert();
6744  XLogRegisterData((char *) &dummy, sizeof(dummy));
6745  (void) XLogInsert(RM_XLOG_ID, XLOG_CHECKPOINT_REDO);
6746 
6747  /*
6748  * XLogInsertRecord will have updated XLogCtl->Insert.RedoRecPtr in
6749  * shared memory and RedoRecPtr in backend-local memory, but we need
6750  * to copy that into the record that will be inserted when the
6751  * checkpoint is complete.
6752  */
6753  checkPoint.redo = RedoRecPtr;
6754  }
6755 
6756  /* Update the info_lck-protected copy of RedoRecPtr as well */
6758  XLogCtl->RedoRecPtr = checkPoint.redo;
6760 
6761  /*
6762  * If enabled, log checkpoint start. We postpone this until now so as not
6763  * to log anything if we decided to skip the checkpoint.
6764  */
6765  if (log_checkpoints)
6766  LogCheckpointStart(flags, false);
6767 
6768  /* Update the process title */
6769  update_checkpoint_display(flags, false, false);
6770 
6771  TRACE_POSTGRESQL_CHECKPOINT_START(flags);
6772 
6773  /*
6774  * Get the other info we need for the checkpoint record.
6775  *
6776  * We don't need to save oldestClogXid in the checkpoint, it only matters
6777  * for the short period in which clog is being truncated, and if we crash
6778  * during that we'll redo the clog truncation and fix up oldestClogXid
6779  * there.
6780  */
6781  LWLockAcquire(XidGenLock, LW_SHARED);
6782  checkPoint.nextXid = TransamVariables->nextXid;
6783  checkPoint.oldestXid = TransamVariables->oldestXid;
6785  LWLockRelease(XidGenLock);
6786 
6787  LWLockAcquire(CommitTsLock, LW_SHARED);
6790  LWLockRelease(CommitTsLock);
6791 
6792  LWLockAcquire(OidGenLock, LW_SHARED);
6793  checkPoint.nextOid = TransamVariables->nextOid;
6794  if (!shutdown)
6795  checkPoint.nextOid += TransamVariables->oidCount;
6796  LWLockRelease(OidGenLock);
6797 
6798  MultiXactGetCheckptMulti(shutdown,
6799  &checkPoint.nextMulti,
6800  &checkPoint.nextMultiOffset,
6801  &checkPoint.oldestMulti,
6802  &checkPoint.oldestMultiDB);
6803 
6804  /*
6805  * Having constructed the checkpoint record, ensure all shmem disk buffers
6806  * and commit-log buffers are flushed to disk.
6807  *
6808  * This I/O could fail for various reasons. If so, we will fail to
6809  * complete the checkpoint, but there is no reason to force a system
6810  * panic. Accordingly, exit critical section while doing it.
6811  */
6812  END_CRIT_SECTION();
6813 
6814  /*
6815  * In some cases there are groups of actions that must all occur on one
6816  * side or the other of a checkpoint record. Before flushing the
6817  * checkpoint record we must explicitly wait for any backend currently
6818  * performing those groups of actions.
6819  *
6820  * One example is end of transaction, so we must wait for any transactions
6821  * that are currently in commit critical sections. If an xact inserted
6822  * its commit record into XLOG just before the REDO point, then a crash
6823  * restart from the REDO point would not replay that record, which means
6824  * that our flushing had better include the xact's update of pg_xact. So
6825  * we wait till he's out of his commit critical section before proceeding.
6826  * See notes in RecordTransactionCommit().
6827  *
6828  * Because we've already released the insertion locks, this test is a bit
6829  * fuzzy: it is possible that we will wait for xacts we didn't really need
6830  * to wait for. But the delay should be short and it seems better to make
6831  * checkpoint take a bit longer than to hold off insertions longer than
6832  * necessary. (In fact, the whole reason we have this issue is that xact.c
6833  * does commit record XLOG insertion and clog update as two separate steps
6834  * protected by different locks, but again that seems best on grounds of
6835  * minimizing lock contention.)
6836  *
6837  * A transaction that has not yet set delayChkptFlags when we look cannot
6838  * be at risk, since it has not inserted its commit record yet; and one
6839  * that's already cleared it is not at risk either, since it's done fixing
6840  * clog and we will correctly flush the update below. So we cannot miss
6841  * any xacts we need to wait for.
6842  */
6844  if (nvxids > 0)
6845  {
6846  do
6847  {
6848  pgstat_report_wait_start(WAIT_EVENT_CHECKPOINT_DELAY_START);
6849  pg_usleep(10000L); /* wait for 10 msec */
6851  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6853  }
6854  pfree(vxids);
6855 
6856  CheckPointGuts(checkPoint.redo, flags);
6857 
6859  if (nvxids > 0)
6860  {
6861  do
6862  {
6863  pgstat_report_wait_start(WAIT_EVENT_CHECKPOINT_DELAY_COMPLETE);
6864  pg_usleep(10000L); /* wait for 10 msec */
6866  } while (HaveVirtualXIDsDelayingChkpt(vxids, nvxids,
6868  }
6869  pfree(vxids);
6870 
6871  /*
6872  * Take a snapshot of running transactions and write this to WAL. This
6873  * allows us to reconstruct the state of running transactions during
6874  * archive recovery, if required. Skip, if this info disabled.
6875  *
6876  * If we are shutting down, or Startup process is completing crash
6877  * recovery we don't need to write running xact data.
6878  */
6879  if (!shutdown && XLogStandbyInfoActive())
6881 
6883 
6884  /*
6885  * Now insert the checkpoint record into XLOG.
6886  */
6887  XLogBeginInsert();
6888  XLogRegisterData((char *) (&checkPoint), sizeof(checkPoint));
6889  recptr = XLogInsert(RM_XLOG_ID,
6890  shutdown ? XLOG_CHECKPOINT_SHUTDOWN :
6892 
6893  XLogFlush(recptr);
6894 
6895  /*
6896  * We mustn't write any new WAL after a shutdown checkpoint, or it will be
6897  * overwritten at next startup. No-one should even try, this just allows
6898  * sanity-checking. In the case of an end-of-recovery checkpoint, we want
6899  * to just temporarily disable writing until the system has exited
6900  * recovery.
6901  */
6902  if (shutdown)
6903  {
6904  if (flags & CHECKPOINT_END_OF_RECOVERY)
6905  LocalXLogInsertAllowed = oldXLogAllowed;
6906  else
6907  LocalXLogInsertAllowed = 0; /* never again write WAL */
6908  }
6909 
6910  /*
6911  * We now have ProcLastRecPtr = start of actual checkpoint record, recptr
6912  * = end of actual checkpoint record.
6913  */
6914  if (shutdown && checkPoint.redo != ProcLastRecPtr)
6915  ereport(PANIC,
6916  (errmsg("concurrent write-ahead log activity while database system is shutting down")));
6917 
6918  /*
6919  * Remember the prior checkpoint's redo ptr for
6920  * UpdateCheckPointDistanceEstimate()
6921  */
6922  PriorRedoPtr = ControlFile->checkPointCopy.redo;
6923 
6924  /*
6925  * Update the control file.
6926  */
6927  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
6928  if (shutdown)
6931  ControlFile->checkPointCopy = checkPoint;
6932  /* crash recovery should always recover to the end of WAL */
6935 
6936  /*
6937  * Persist unloggedLSN value. It's reset on crash recovery, so this goes
6938  * unused on non-shutdown checkpoints, but seems useful to store it always
6939  * for debugging purposes.
6940  */
6944 
6946  LWLockRelease(ControlFileLock);
6947 
6948  /* Update shared-memory copy of checkpoint XID/epoch */
6950  XLogCtl->ckptFullXid = checkPoint.nextXid;
6952 
6953  /*
6954  * We are now done with critical updates; no need for system panic if we
6955  * have trouble while fooling with old log segments.
6956  */
6957  END_CRIT_SECTION();
6958 
6959  /*
6960  * Let smgr do post-checkpoint cleanup (eg, deleting old files).
6961  */
6963 
6964  /*
6965  * Update the average distance between checkpoints if the prior checkpoint
6966  * exists.
6967  */
6968  if (PriorRedoPtr != InvalidXLogRecPtr)
6970 
6971  /*
6972  * Delete old log files, those no longer needed for last checkpoint to
6973  * prevent the disk holding the xlog from growing full.
6974  */
6976  KeepLogSeg(recptr, &_logSegNo);
6978  _logSegNo, InvalidOid,
6980  {
6981  /*
6982  * Some slots have been invalidated; recalculate the old-segment
6983  * horizon, starting again from RedoRecPtr.
6984  */
6986  KeepLogSeg(recptr, &_logSegNo);
6987  }
6988  _logSegNo--;
6989  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, recptr,
6990  checkPoint.ThisTimeLineID);
6991 
6992  /*
6993  * Make more log segments if needed. (Do this after recycling old log
6994  * segments, since that may supply some of the needed files.)
6995  */
6996  if (!shutdown)
6997  PreallocXlogFiles(recptr, checkPoint.ThisTimeLineID);
6998 
6999  /*
7000  * Truncate pg_subtrans if possible. We can throw away all data before
7001  * the oldest XMIN of any running transaction. No future transaction will
7002  * attempt to reference any pg_subtrans entry older than that (see Asserts
7003  * in subtrans.c). During recovery, though, we mustn't do this because
7004  * StartupSUBTRANS hasn't been called yet.
7005  */
7006  if (!RecoveryInProgress())
7008 
7009  /* Real work is done; log and update stats. */
7010  LogCheckpointEnd(false);
7011 
7012  /* Reset the process title */
7013  update_checkpoint_display(flags, false, true);
7014 
7015  TRACE_POSTGRESQL_CHECKPOINT_DONE(CheckpointStats.ckpt_bufs_written,
7016  NBuffers,
7020 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1649
unsigned int uint32
Definition: c.h:495
#define MemSet(start, val, len)
Definition: c.h:1009
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
#define DEBUG1
Definition: elog.h:30
static void Insert(File file)
Definition: fd.c:1290
int NBuffers
Definition: globals.c:138
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_SHARED
Definition: lwlock.h:117
@ LW_EXCLUSIVE
Definition: lwlock.h:116
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
void MultiXactGetCheckptMulti(bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
Definition: multixact.c:2135
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:81
@ DB_SHUTDOWNING
Definition: pg_control.h:93
@ DB_SHUTDOWNED
Definition: pg_control.h:91
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:68
#define InvalidOid
Definition: postgres_ext.h:36
#define DELAY_CHKPT_START
Definition: proc.h:119
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:120
VirtualTransactionId * GetVirtualXIDsDelayingChkpt(int *nvxids, int type)
Definition: procarray.c:3007
TransactionId GetOldestActiveTransactionId(void)
Definition: procarray.c:2844
TransactionId GetOldestTransactionIdConsideredRunning(void)
Definition: procarray.c:2015
bool HaveVirtualXIDsDelayingChkpt(VirtualTransactionId *vxids, int nvxids, int type)
Definition: procarray.c:3053
void pg_usleep(long microsec)
Definition: signal.c:53
bool InvalidateObsoleteReplicationSlots(ReplicationSlotInvalidationCause cause, XLogSegNo oldestSegno, Oid dboid, TransactionId snapshotConflictHorizon)
Definition: slot.c:1564
@ RS_INVAL_WAL_REMOVED
Definition: slot.h:48
XLogRecPtr LogStandbySnapshot(void)
Definition: standby.c:1287
TimestampTz ckpt_start_t
Definition: xlog.h:159
int ckpt_segs_removed
Definition: xlog.h:168
int ckpt_segs_added
Definition: xlog.h:167
int ckpt_bufs_written
Definition: xlog.h:165
int ckpt_segs_recycled
Definition: xlog.h:169
XLogRecPtr minRecoveryPoint
Definition: pg_control.h:167
XLogRecPtr unloggedLSN
Definition: pg_control.h:136
TimeLineID minRecoveryPointTLI
Definition: pg_control.h:168
TransactionId oldestCommitTsXid
Definition: transam.h:232
TransactionId newestCommitTsXid
Definition: transam.h:233
TransactionId oldestXid
Definition: transam.h:222
FullTransactionId ckptFullXid
Definition: xlog.c:466
TimeLineID InsertTimeLineID
Definition: xlog.c:515
slock_t ulsn_lck
Definition: xlog.c:474
XLogRecPtr RedoRecPtr
Definition: xlog.c:465
XLogRecPtr unloggedLSN
Definition: xlog.c:473
XLogCtlInsert Insert
Definition: xlog.c:461
TimeLineID PrevTimeLineID
Definition: xlog.c:516
XLogRecPtr RedoRecPtr
Definition: xlog.c:439
void TruncateSUBTRANS(TransactionId oldestXact)
Definition: subtrans.c:348
void SyncPreCheckpoint(void)
Definition: sync.c:182
void SyncPostCheckpoint(void)
Definition: sync.c:207
XLogRecPtr ProcLastRecPtr
Definition: xlog.c:256
bool RecoveryInProgress(void)
Definition: xlog.c:6039
static void WALInsertLockRelease(void)
Definition: xlog.c:1437
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos)
Definition: xlog.c:1717
static void WALInsertLockAcquireExclusive(void)
Definition: xlog.c:1408
static void UpdateControlFile(void)
Definition: xlog.c:4285
static void RemoveOldXlogFiles(XLogSegNo segno, XLogRecPtr lastredoptr, XLogRecPtr endptr, TimeLineID insertTLI)
Definition: xlog.c:3651
static void LogCheckpointStart(int flags, bool restartpoint)
Definition: xlog.c:6337
static XLogRecPtr RedoRecPtr
Definition: xlog.c:276
static void LogCheckpointEnd(bool restartpoint)
Definition: xlog.c:6369
static void PreallocXlogFiles(XLogRecPtr endptr, TimeLineID tli)
Definition: xlog.c:3513
bool log_checkpoints
Definition: xlog.c:132
static void KeepLogSeg(XLogRecPtr recptr, XLogSegNo *logSegNo)
Definition: xlog.c:7602
static int LocalSetXLogInsertAllowed(void)
Definition: xlog.c:6127
XLogRecPtr GetLastImportantRecPtr(void)
Definition: xlog.c:6244
static void UpdateCheckPointDistanceEstimate(uint64 nbytes)
Definition: xlog.c:6472
#define INSERT_FREESPACE(endptr)
Definition: xlog.c:586
static int LocalXLogInsertAllowed
Definition: xlog.c:239
CheckpointStatsData CheckpointStats
Definition: xlog.c:212
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2621
static void CheckPointGuts(XLogRecPtr checkPointRedo, int flags)
Definition: xlog.c:7165
static void update_checkpoint_display(int flags, bool restartpoint, bool reset)
Definition: xlog.c:6510
#define CHECKPOINT_END_OF_RECOVERY
Definition: xlog.h:138
#define CHECKPOINT_FORCE
Definition: xlog.h:140
#define CHECKPOINT_IS_SHUTDOWN
Definition: xlog.h:137
#define XLogStandbyInfoActive()
Definition: xlog.h:121
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:365
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:475
void XLogBeginInsert(void)
Definition: xloginsert.c:150

References ControlFileData::checkPoint, CHECKPOINT_END_OF_RECOVERY, CHECKPOINT_FORCE, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_bufs_written, CheckpointStatsData::ckpt_segs_added, CheckpointStatsData::ckpt_segs_recycled, CheckpointStatsData::ckpt_segs_removed, CheckpointStatsData::ckpt_start_t, XLogCtlData::ckptFullXid, ControlFile, DB_SHUTDOWNED, DB_SHUTDOWNING, DEBUG1, DELAY_CHKPT_COMPLETE, DELAY_CHKPT_START, elog(), END_CRIT_SECTION, ereport, errmsg(), errmsg_internal(), ERROR, CheckPoint::fullPageWrites, GetCurrentTimestamp(), GetLastImportantRecPtr(), GetOldestActiveTransactionId(), GetOldestTransactionIdConsideredRunning(), GetVirtualXIDsDelayingChkpt(), HaveVirtualXIDsDelayingChkpt(), XLogCtlData::info_lck, XLogCtlData::Insert, Insert(), INSERT_FREESPACE, XLogCtlData::InsertTimeLineID, InvalidateObsoleteReplicationSlots(), InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, KeepLogSeg(), LocalSetXLogInsertAllowed(), LocalXLogInsertAllowed, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LogStandbySnapshot(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MultiXactGetCheckptMulti(), NBuffers, TransamVariablesData::newestCommitTsXid, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, TransamVariablesData::nextOid, CheckPoint::nextOid, TransamVariablesData::nextXid, CheckPoint::nextXid, TransamVariablesData::oidCount, CheckPoint::oldestActiveXid, TransamVariablesData::oldestCommitTsXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, TransamVariablesData::oldestXid, CheckPoint::oldestXid, TransamVariablesData::oldestXidDB, CheckPoint::oldestXidDB, PANIC, pfree(), pg_usleep(), pgstat_report_wait_end(), pgstat_report_wait_start(), PreallocXlogFiles(), XLogCtlData::PrevTimeLineID, CheckPoint::PrevTimeLineID, ProcLastRecPtr, RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), RS_INVAL_WAL_REMOVED, SizeOfXLogLongPHD, SizeOfXLogShortPHD, SpinLockAcquire, SpinLockRelease, START_CRIT_SECTION, ControlFileData::state, SyncPostCheckpoint(), SyncPreCheckpoint(), CheckPoint::ThisTimeLineID, CheckPoint::time, TransamVariables, TruncateSUBTRANS(), XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, ControlFileData::unloggedLSN, update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_REDO, XLOG_CHECKPOINT_SHUTDOWN, XLogBeginInsert(), XLogBytePosToRecPtr(), XLogCtl, XLogFlush(), XLogInsert(), XLogRegisterData(), XLogSegmentOffset, and XLogStandbyInfoActive.

Referenced by CheckpointerMain(), RequestCheckpoint(), and ShutdownXLOG().

◆ CreateRestartPoint()

bool CreateRestartPoint ( int  flags)

Definition at line 7246 of file xlog.c.

7247 {
7248  XLogRecPtr lastCheckPointRecPtr;
7249  XLogRecPtr lastCheckPointEndPtr;
7250  CheckPoint lastCheckPoint;
7251  XLogRecPtr PriorRedoPtr;
7252  XLogRecPtr receivePtr;
7253  XLogRecPtr replayPtr;
7254  TimeLineID replayTLI;
7255  XLogRecPtr endptr;
7256  XLogSegNo _logSegNo;
7257  TimestampTz xtime;
7258 
7259  /* Concurrent checkpoint/restartpoint cannot happen */
7261 
7262  /* Get a local copy of the last safe checkpoint record. */
7264  lastCheckPointRecPtr = XLogCtl->lastCheckPointRecPtr;
7265  lastCheckPointEndPtr = XLogCtl->lastCheckPointEndPtr;
7266  lastCheckPoint = XLogCtl->lastCheckPoint;
7268 
7269  /*
7270  * Check that we're still in recovery mode. It's ok if we exit recovery
7271  * mode after this check, the restart point is valid anyway.
7272  */
7273  if (!RecoveryInProgress())
7274  {
7275  ereport(DEBUG2,
7276  (errmsg_internal("skipping restartpoint, recovery has already ended")));
7277  return false;
7278  }
7279 
7280  /*
7281  * If the last checkpoint record we've replayed is already our last
7282  * restartpoint, we can't perform a new restart point. We still update
7283  * minRecoveryPoint in that case, so that if this is a shutdown restart
7284  * point, we won't start up earlier than before. That's not strictly
7285  * necessary, but when hot standby is enabled, it would be rather weird if
7286  * the database opened up for read-only connections at a point-in-time
7287  * before the last shutdown. Such time travel is still possible in case of
7288  * immediate shutdown, though.
7289  *
7290  * We don't explicitly advance minRecoveryPoint when we do create a
7291  * restartpoint. It's assumed that flushing the buffers will do that as a
7292  * side-effect.
7293  */
7294  if (XLogRecPtrIsInvalid(lastCheckPointRecPtr) ||
7295  lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
7296  {
7297  ereport(DEBUG2,
7298  (errmsg_internal("skipping restartpoint, already performed at %X/%X",
7299  LSN_FORMAT_ARGS(lastCheckPoint.redo))));
7300 
7302  if (flags & CHECKPOINT_IS_SHUTDOWN)
7303  {
7304  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7307  LWLockRelease(ControlFileLock);
7308  }
7309  return false;
7310  }
7311 
7312  /*
7313  * Update the shared RedoRecPtr so that the startup process can calculate
7314  * the number of segments replayed since last restartpoint, and request a
7315  * restartpoint if it exceeds CheckPointSegments.
7316  *
7317  * Like in CreateCheckPoint(), hold off insertions to update it, although
7318  * during recovery this is just pro forma, because no WAL insertions are
7319  * happening.
7320  */
7322  RedoRecPtr = XLogCtl->Insert.RedoRecPtr = lastCheckPoint.redo;
7324 
7325  /* Also update the info_lck-protected copy */
7327  XLogCtl->RedoRecPtr = lastCheckPoint.redo;
7329 
7330  /*
7331  * Prepare to accumulate statistics.
7332  *
7333  * Note: because it is possible for log_checkpoints to change while a
7334  * checkpoint proceeds, we always accumulate stats, even if
7335  * log_checkpoints is currently off.
7336  */
7337  MemSet(&CheckpointStats, 0, sizeof(CheckpointStats));
7339 
7340  if (log_checkpoints)
7341  LogCheckpointStart(flags, true);
7342 
7343  /* Update the process title */
7344  update_checkpoint_display(flags, true, false);
7345 
7346  CheckPointGuts(lastCheckPoint.redo, flags);
7347 
7348  /*
7349  * Remember the prior checkpoint's redo ptr for
7350  * UpdateCheckPointDistanceEstimate()
7351  */
7352  PriorRedoPtr = ControlFile->checkPointCopy.redo;
7353 
7354  /*
7355  * Update pg_control, using current time. Check that it still shows an
7356  * older checkpoint, else do nothing; this is a quick hack to make sure
7357  * nothing really bad happens if somehow we get here after the
7358  * end-of-recovery checkpoint.
7359  */
7360  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7361  if (ControlFile->checkPointCopy.redo < lastCheckPoint.redo)
7362  {
7363  /*
7364  * Update the checkpoint information. We do this even if the cluster
7365  * does not show DB_IN_ARCHIVE_RECOVERY to match with the set of WAL
7366  * segments recycled below.
7367  */
7368  ControlFile->checkPoint = lastCheckPointRecPtr;
7369  ControlFile->checkPointCopy = lastCheckPoint;
7370 
7371  /*
7372  * Ensure minRecoveryPoint is past the checkpoint record and update it
7373  * if the control file still shows DB_IN_ARCHIVE_RECOVERY. Normally,
7374  * this will have happened already while writing out dirty buffers,
7375  * but not necessarily - e.g. because no buffers were dirtied. We do
7376  * this because a backup performed in recovery uses minRecoveryPoint
7377  * to determine which WAL files must be included in the backup, and
7378  * the file (or files) containing the checkpoint record must be
7379  * included, at a minimum. Note that for an ordinary restart of
7380  * recovery there's no value in having the minimum recovery point any
7381  * earlier than this anyway, because redo will begin just after the
7382  * checkpoint record.
7383  */
7385  {
7386  if (ControlFile->minRecoveryPoint < lastCheckPointEndPtr)
7387  {
7388  ControlFile->minRecoveryPoint = lastCheckPointEndPtr;
7390 
7391  /* update local copy */
7394  }
7395  if (flags & CHECKPOINT_IS_SHUTDOWN)
7397  }
7399  }
7400  LWLockRelease(ControlFileLock);
7401 
7402  /*
7403  * Update the average distance between checkpoints/restartpoints if the
7404  * prior checkpoint exists.
7405  */
7406  if (PriorRedoPtr != InvalidXLogRecPtr)
7408 
7409  /*
7410  * Delete old log files, those no longer needed for last restartpoint to
7411  * prevent the disk holding the xlog from growing full.
7412  */
7414 
7415  /*
7416  * Retreat _logSegNo using the current end of xlog replayed or received,
7417  * whichever is later.
7418  */
7419  receivePtr = GetWalRcvFlushRecPtr(NULL, NULL);
7420  replayPtr = GetXLogReplayRecPtr(&replayTLI);
7421  endptr = (receivePtr < replayPtr) ? replayPtr : receivePtr;
7422  KeepLogSeg(endptr, &_logSegNo);
7424  _logSegNo, InvalidOid,
7426  {
7427  /*
7428  * Some slots have been invalidated; recalculate the old-segment
7429  * horizon, starting again from RedoRecPtr.
7430  */
7432  KeepLogSeg(endptr, &_logSegNo);
7433  }
7434  _logSegNo--;
7435 
7436  /*
7437  * Try to recycle segments on a useful timeline. If we've been promoted
7438  * since the beginning of this restartpoint, use the new timeline chosen
7439  * at end of recovery. If we're still in recovery, use the timeline we're
7440  * currently replaying.
7441  *
7442  * There is no guarantee that the WAL segments will be useful on the
7443  * current timeline; if recovery proceeds to a new timeline right after
7444  * this, the pre-allocated WAL segments on this timeline will not be used,
7445  * and will go wasted until recycled on the next restartpoint. We'll live
7446  * with that.
7447  */
7448  if (!RecoveryInProgress())
7449  replayTLI = XLogCtl->InsertTimeLineID;
7450 
7451  RemoveOldXlogFiles(_logSegNo, RedoRecPtr, endptr, replayTLI);
7452 
7453  /*
7454  * Make more log segments if needed. (Do this after recycling old log
7455  * segments, since that may supply some of the needed files.)
7456  */
7457  PreallocXlogFiles(endptr, replayTLI);
7458 
7459  /*
7460  * Truncate pg_subtrans if possible. We can throw away all data before
7461  * the oldest XMIN of any running transaction. No future transaction will
7462  * attempt to reference any pg_subtrans entry older than that (see Asserts
7463  * in subtrans.c). When hot standby is disabled, though, we mustn't do
7464  * this because StartupSUBTRANS hasn't been called yet.
7465  */
7466  if (EnableHotStandby)
7468 
7469  /* Real work is done; log and update stats. */
7470  LogCheckpointEnd(true);
7471 
7472  /* Reset the process title */
7473  update_checkpoint_display(flags, true, true);
7474 
7475  xtime = GetLatestXTime();
7477  (errmsg("recovery restart point at %X/%X",
7478  LSN_FORMAT_ARGS(lastCheckPoint.redo)),
7479  xtime ? errdetail("Last completed transaction was at log time %s.",
7480  timestamptz_to_str(xtime)) : 0));
7481 
7482  /*
7483  * Finally, execute archive_cleanup_command, if any.
7484  */
7485  if (archiveCleanupCommand && strcmp(archiveCleanupCommand, "") != 0)
7487  "archive_cleanup_command",
7488  false,
7489  WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND);
7490 
7491  return true;
7492 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1848
int64 TimestampTz
Definition: timestamp.h:39
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define LOG
Definition: elog.h:31
#define DEBUG2
Definition: elog.h:29
bool IsUnderPostmaster
Definition: globals.c:115
@ B_CHECKPOINTER
Definition: miscadmin.h:337
BackendType MyBackendType
Definition: miscinit.c:63
@ DB_IN_ARCHIVE_RECOVERY
Definition: pg_control.h:95
@ DB_SHUTDOWNED_IN_RECOVERY
Definition: pg_control.h:92
CheckPoint lastCheckPoint
Definition: xlog.c:551
XLogRecPtr lastCheckPointRecPtr
Definition: xlog.c:549
XLogRecPtr lastCheckPointEndPtr
Definition: xlog.c:550
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
bool EnableHotStandby
Definition: xlog.c:124
static void UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
Definition: xlog.c:2541
static XLogRecPtr LocalMinRecoveryPoint
Definition: xlog.c:639
static TimeLineID LocalMinRecoveryPointTLI
Definition: xlog.c:640
void ExecuteRecoveryCommand(const char *command, const char *commandName, bool failOnSignal, uint32 wait_event_info)
Definition: xlogarchive.c:296
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint32 TimeLineID
Definition: xlogdefs.h:59
char * archiveCleanupCommand
Definition: xlogrecovery.c:84
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
TimestampTz GetLatestXTime(void)

References archiveCleanupCommand, Assert(), B_CHECKPOINTER, ControlFileData::checkPoint, CHECKPOINT_IS_SHUTDOWN, ControlFileData::checkPointCopy, CheckPointGuts(), CheckpointStats, CheckpointStatsData::ckpt_start_t, ControlFile, DB_IN_ARCHIVE_RECOVERY, DB_SHUTDOWNED_IN_RECOVERY, DEBUG2, EnableHotStandby, ereport, errdetail(), errmsg(), errmsg_internal(), ExecuteRecoveryCommand(), GetCurrentTimestamp(), GetLatestXTime(), GetOldestTransactionIdConsideredRunning(), GetWalRcvFlushRecPtr(), GetXLogReplayRecPtr(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, InvalidateObsoleteReplicationSlots(), InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsUnderPostmaster, KeepLogSeg(), XLogCtlData::lastCheckPoint, XLogCtlData::lastCheckPointEndPtr, XLogCtlData::lastCheckPointRecPtr, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LOG, log_checkpoints, LogCheckpointEnd(), LogCheckpointStart(), LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyBackendType, PreallocXlogFiles(), RecoveryInProgress(), CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RemoveOldXlogFiles(), RS_INVAL_WAL_REMOVED, SpinLockAcquire, SpinLockRelease, ControlFileData::state, CheckPoint::ThisTimeLineID, timestamptz_to_str(), TruncateSUBTRANS(), update_checkpoint_display(), UpdateCheckPointDistanceEstimate(), UpdateControlFile(), UpdateMinRecoveryPoint(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLByteToSeg, XLogCtl, and XLogRecPtrIsInvalid.

Referenced by CheckpointerMain(), and ShutdownXLOG().

◆ DataChecksumsEnabled()

◆ do_pg_abort_backup()

void do_pg_abort_backup ( int  code,
Datum  arg 
)

Definition at line 9026 of file xlog.c.

9027 {
9028  bool during_backup_start = DatumGetBool(arg);
9029 
9030  /* If called during backup start, there shouldn't be one already running */
9031  Assert(!during_backup_start || sessionBackupState == SESSION_BACKUP_NONE);
9032 
9033  if (during_backup_start || sessionBackupState != SESSION_BACKUP_NONE)
9034  {
9038 
9041 
9042  if (!during_backup_start)
9043  ereport(WARNING,
9044  errmsg("aborting backup due to backend exiting before pg_backup_stop was called"));
9045  }
9046 }
#define WARNING
Definition: elog.h:36
void * arg
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
int runningBackups
Definition: xlog.c:447
static SessionBackupState sessionBackupState
Definition: xlog.c:400

References arg, Assert(), DatumGetBool(), ereport, errmsg(), XLogCtlData::Insert, XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, and XLogCtl.

Referenced by do_pg_backup_start(), perform_base_backup(), and register_persistent_abort_backup_handler().

◆ do_pg_backup_start()

void do_pg_backup_start ( const char *  backupidstr,
bool  fast,
List **  tablespaces,
BackupState state,
StringInfo  tblspcmapfile 
)

Definition at line 8424 of file xlog.c.

8426 {
8428 
8429  Assert(state != NULL);
8431 
8432  /*
8433  * During recovery, we don't need to check WAL level. Because, if WAL
8434  * level is not sufficient, it's impossible to get here during recovery.
8435  */
8437  ereport(ERROR,
8438  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8439  errmsg("WAL level not sufficient for making an online backup"),
8440  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8441 
8442  if (strlen(backupidstr) > MAXPGPATH)
8443  ereport(ERROR,
8444  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8445  errmsg("backup label too long (max %d bytes)",
8446  MAXPGPATH)));
8447 
8448  memcpy(state->name, backupidstr, strlen(backupidstr));
8449 
8450  /*
8451  * Mark backup active in shared memory. We must do full-page WAL writes
8452  * during an on-line backup even if not doing so at other times, because
8453  * it's quite possible for the backup dump to obtain a "torn" (partially
8454  * written) copy of a database page if it reads the page concurrently with
8455  * our write to the same page. This can be fixed as long as the first
8456  * write to the page in the WAL sequence is a full-page write. Hence, we
8457  * increment runningBackups then force a CHECKPOINT, to ensure there are
8458  * no dirty pages in shared memory that might get dumped while the backup
8459  * is in progress without having a corresponding WAL record. (Once the
8460  * backup is complete, we need not force full-page writes anymore, since
8461  * we expect that any pages not modified during the backup interval must
8462  * have been correctly captured by the backup.)
8463  *
8464  * Note that forcing full-page writes has no effect during an online
8465  * backup from the standby.
8466  *
8467  * We must hold all the insertion locks to change the value of
8468  * runningBackups, to ensure adequate interlocking against
8469  * XLogInsertRecord().
8470  */
8474 
8475  /*
8476  * Ensure we decrement runningBackups if we fail below. NB -- for this to
8477  * work correctly, it is critical that sessionBackupState is only updated
8478  * after this block is over.
8479  */
8481  {
8482  bool gotUniqueStartpoint = false;
8483  DIR *tblspcdir;
8484  struct dirent *de;
8485  tablespaceinfo *ti;
8486  int datadirpathlen;
8487 
8488  /*
8489  * Force an XLOG file switch before the checkpoint, to ensure that the
8490  * WAL segment the checkpoint is written to doesn't contain pages with
8491  * old timeline IDs. That would otherwise happen if you called
8492  * pg_backup_start() right after restoring from a PITR archive: the
8493  * first WAL segment containing the startup checkpoint has pages in
8494  * the beginning with the old timeline ID. That can cause trouble at
8495  * recovery: we won't have a history file covering the old timeline if
8496  * pg_wal directory was not included in the base backup and the WAL
8497  * archive was cleared too before starting the backup.
8498  *
8499  * This also ensures that we have emitted a WAL page header that has
8500  * XLP_BKP_REMOVABLE off before we emit the checkpoint record.
8501  * Therefore, if a WAL archiver (such as pglesslog) is trying to
8502  * compress out removable backup blocks, it won't remove any that
8503  * occur after this point.
8504  *
8505  * During recovery, we skip forcing XLOG file switch, which means that
8506  * the backup taken during recovery is not available for the special
8507  * recovery case described above.
8508  */
8510  RequestXLogSwitch(false);
8511 
8512  do
8513  {
8514  bool checkpointfpw;
8515 
8516  /*
8517  * Force a CHECKPOINT. Aside from being necessary to prevent torn
8518  * page problems, this guarantees that two successive backup runs
8519  * will have different checkpoint positions and hence different
8520  * history file names, even if nothing happened in between.
8521  *
8522  * During recovery, establish a restartpoint if possible. We use
8523  * the last restartpoint as the backup starting checkpoint. This
8524  * means that two successive backup runs can have same checkpoint
8525  * positions.
8526  *
8527  * Since the fact that we are executing do_pg_backup_start()
8528  * during recovery means that checkpointer is running, we can use
8529  * RequestCheckpoint() to establish a restartpoint.
8530  *
8531  * We use CHECKPOINT_IMMEDIATE only if requested by user (via
8532  * passing fast = true). Otherwise this can take awhile.
8533  */
8535  (fast ? CHECKPOINT_IMMEDIATE : 0));
8536 
8537  /*
8538  * Now we need to fetch the checkpoint record location, and also
8539  * its REDO pointer. The oldest point in WAL that would be needed
8540  * to restore starting from the checkpoint is precisely the REDO
8541  * pointer.
8542  */
8543  LWLockAcquire(ControlFileLock, LW_SHARED);
8544  state->checkpointloc = ControlFile->checkPoint;
8545  state->startpoint = ControlFile->checkPointCopy.redo;
8547  checkpointfpw = ControlFile->checkPointCopy.fullPageWrites;
8548  LWLockRelease(ControlFileLock);
8549 
8551  {
8552  XLogRecPtr recptr;
8553 
8554  /*
8555  * Check to see if all WAL replayed during online backup
8556  * (i.e., since last restartpoint used as backup starting
8557  * checkpoint) contain full-page writes.
8558  */
8560  recptr = XLogCtl->lastFpwDisableRecPtr;
8562 
8563  if (!checkpointfpw || state->startpoint <= recptr)
8564  ereport(ERROR,
8565  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8566  errmsg("WAL generated with full_page_writes=off was replayed "
8567  "since last restartpoint"),
8568  errhint("This means that the backup being taken on the standby "
8569  "is corrupt and should not be used. "
8570  "Enable full_page_writes and run CHECKPOINT on the primary, "
8571  "and then try an online backup again.")));
8572 
8573  /*
8574  * During recovery, since we don't use the end-of-backup WAL
8575  * record and don't write the backup history file, the
8576  * starting WAL location doesn't need to be unique. This means
8577  * that two base backups started at the same time might use
8578  * the same checkpoint as starting locations.
8579  */
8580  gotUniqueStartpoint = true;
8581  }
8582 
8583  /*
8584  * If two base backups are started at the same time (in WAL sender
8585  * processes), we need to make sure that they use different
8586  * checkpoints as starting locations, because we use the starting
8587  * WAL location as a unique identifier for the base backup in the
8588  * end-of-backup WAL record and when we write the backup history
8589  * file. Perhaps it would be better generate a separate unique ID
8590  * for each backup instead of forcing another checkpoint, but
8591  * taking a checkpoint right after another is not that expensive
8592  * either because only few buffers have been dirtied yet.
8593  */
8595  if (XLogCtl->Insert.lastBackupStart < state->startpoint)
8596  {
8597  XLogCtl->Insert.lastBackupStart = state->startpoint;
8598  gotUniqueStartpoint = true;
8599  }
8601  } while (!gotUniqueStartpoint);
8602 
8603  /*
8604  * Construct tablespace_map file.
8605  */
8606  datadirpathlen = strlen(DataDir);
8607 
8608  /* Collect information about all tablespaces */
8609  tblspcdir = AllocateDir("pg_tblspc");
8610  while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL)
8611  {
8612  char fullpath[MAXPGPATH + 10];
8613  char linkpath[MAXPGPATH];
8614  char *relpath = NULL;
8615  char *s;
8616  PGFileType de_type;
8617  char *badp;
8618  Oid tsoid;
8619 
8620  /*
8621  * Try to parse the directory name as an unsigned integer.
8622  *
8623  * Tablespace directories should be positive integers that can be
8624  * represented in 32 bits, with no leading zeroes or trailing
8625  * garbage. If we come across a name that doesn't meet those
8626  * criteria, skip it.
8627  */
8628  if (de->d_name[0] < '1' || de->d_name[1] > '9')
8629  continue;
8630  errno = 0;
8631  tsoid = strtoul(de->d_name, &badp, 10);
8632  if (*badp != '\0' || errno == EINVAL || errno == ERANGE)
8633  continue;
8634 
8635  snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name);
8636 
8637  de_type = get_dirent_type(fullpath, de, false, ERROR);
8638 
8639  if (de_type == PGFILETYPE_LNK)
8640  {
8641  StringInfoData escapedpath;
8642  int rllen;
8643 
8644  rllen = readlink(fullpath, linkpath, sizeof(linkpath));
8645  if (rllen < 0)
8646  {
8647  ereport(WARNING,
8648  (errmsg("could not read symbolic link \"%s\": %m",
8649  fullpath)));
8650  continue;
8651  }
8652  else if (rllen >= sizeof(linkpath))
8653  {
8654  ereport(WARNING,
8655  (errmsg("symbolic link \"%s\" target is too long",
8656  fullpath)));
8657  continue;
8658  }
8659  linkpath[rllen] = '\0';
8660 
8661  /*
8662  * Relpath holds the relative path of the tablespace directory
8663  * when it's located within PGDATA, or NULL if it's located
8664  * elsewhere.
8665  */
8666  if (rllen > datadirpathlen &&
8667  strncmp(linkpath, DataDir, datadirpathlen) == 0 &&
8668  IS_DIR_SEP(linkpath[datadirpathlen]))
8669  relpath = pstrdup(linkpath + datadirpathlen + 1);
8670 
8671  /*
8672  * Add a backslash-escaped version of the link path to the
8673  * tablespace map file.
8674  */
8675  initStringInfo(&escapedpath);
8676  for (s = linkpath; *s; s++)
8677  {
8678  if (*s == '\n' || *s == '\r' || *s == '\\')
8679  appendStringInfoChar(&escapedpath, '\\');
8680  appendStringInfoChar(&escapedpath, *s);
8681  }
8682  appendStringInfo(tblspcmapfile, "%s %s\n",
8683  de->d_name, escapedpath.data);
8684  pfree(escapedpath.data);
8685  }
8686  else if (de_type == PGFILETYPE_DIR)
8687  {
8688  /*
8689  * It's possible to use allow_in_place_tablespaces to create
8690  * directories directly under pg_tblspc, for testing purposes
8691  * only.
8692  *
8693  * In this case, we store a relative path rather than an
8694  * absolute path into the tablespaceinfo.
8695  */
8696  snprintf(linkpath, sizeof(linkpath), "pg_tblspc/%s",
8697  de->d_name);
8698  relpath = pstrdup(linkpath);
8699  }
8700  else
8701  {
8702  /* Skip any other file type that appears here. */
8703  continue;
8704  }
8705 
8706  ti = palloc(sizeof(tablespaceinfo));
8707  ti->oid = tsoid;
8708  ti->path = pstrdup(linkpath);
8709  ti->rpath = relpath;
8710  ti->size = -1;
8711 
8712  if (tablespaces)
8713  *tablespaces = lappend(*tablespaces, ti);
8714  }
8715  FreeDir(tblspcdir);
8716 
8717  state->starttime = (pg_time_t) time(NULL);
8718  }
8720 
8721  state->started_in_recovery = backup_started_in_recovery;
8722 
8723  /*
8724  * Mark that the start phase has correctly finished for the backup.
8725  */
8727 }
static bool backup_started_in_recovery
Definition: basebackup.c:112
void RequestCheckpoint(int flags)
Definition: checkpointer.c:921
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2879
int FreeDir(DIR *dir)
Definition: fd.c:2931
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2813
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:525
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_LNK
Definition: file_utils.h:24
@ PGFILETYPE_DIR
Definition: file_utils.h:23
char * DataDir
Definition: globals.c:66
#define PG_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:47
#define PG_END_ENSURE_ERROR_CLEANUP(cleanup_function, arg)
Definition: ipc.h:52
List * lappend(List *list, void *datum)
Definition: list.c:338
char * pstrdup(const char *in)
Definition: mcxt.c:1644
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define IS_DIR_SEP(ch)
Definition: port.h:102
unsigned int Oid
Definition: postgres_ext.h:31
#define relpath(rlocator, forknum)
Definition: relpath.h:94
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Definition: dirent.c:26
XLogRecPtr lastFpwDisableRecPtr
Definition: xlog.c:557
XLogRecPtr lastBackupStart
Definition: xlog.c:448
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
Definition: regguts.h:323
char * rpath
Definition: basebackup.h:32
#define readlink(path, buf, size)
Definition: win32_port.h:236
XLogRecPtr RequestXLogSwitch(bool mark_unimportant)
Definition: xlog.c:7695
void do_pg_abort_backup(int code, Datum arg)
Definition: xlog.c:9026
@ SESSION_BACKUP_RUNNING
Definition: xlog.h:280
#define CHECKPOINT_WAIT
Definition: xlog.h:143
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:139
#define XLogIsNeeded()
Definition: xlog.h:107

References AllocateDir(), appendStringInfo(), appendStringInfoChar(), Assert(), backup_started_in_recovery, ControlFileData::checkPoint, CHECKPOINT_FORCE, CHECKPOINT_IMMEDIATE, CHECKPOINT_WAIT, ControlFileData::checkPointCopy, ControlFile, dirent::d_name, StringInfoData::data, DataDir, DatumGetBool(), do_pg_abort_backup(), ereport, errcode(), errhint(), errmsg(), ERROR, FreeDir(), CheckPoint::fullPageWrites, get_dirent_type(), XLogCtlData::info_lck, initStringInfo(), XLogCtlData::Insert, IS_DIR_SEP, lappend(), XLogCtlInsert::lastBackupStart, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXPGPATH, tablespaceinfo::oid, palloc(), tablespaceinfo::path, pfree(), PG_END_ENSURE_ERROR_CLEANUP, PG_ENSURE_ERROR_CLEANUP, PGFILETYPE_DIR, PGFILETYPE_LNK, pstrdup(), ReadDir(), readlink, RecoveryInProgress(), CheckPoint::redo, relpath, RequestCheckpoint(), RequestXLogSwitch(), tablespaceinfo::rpath, XLogCtlInsert::runningBackups, SESSION_BACKUP_RUNNING, sessionBackupState, tablespaceinfo::size, snprintf, SpinLockAcquire, SpinLockRelease, CheckPoint::ThisTimeLineID, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, XLogCtl, and XLogIsNeeded.

Referenced by perform_base_backup(), and pg_backup_start().

◆ do_pg_backup_stop()

void do_pg_backup_stop ( BackupState state,
bool  waitforarchive 
)

Definition at line 8752 of file xlog.c.

8753 {
8754  bool backup_stopped_in_recovery = false;
8755  char histfilepath[MAXPGPATH];
8756  char lastxlogfilename[MAXFNAMELEN];
8757  char histfilename[MAXFNAMELEN];
8758  XLogSegNo _logSegNo;
8759  FILE *fp;
8760  int seconds_before_warning;
8761  int waits = 0;
8762  bool reported_waiting = false;
8763 
8764  Assert(state != NULL);
8765 
8766  backup_stopped_in_recovery = RecoveryInProgress();
8767 
8768  /*
8769  * During recovery, we don't need to check WAL level. Because, if WAL
8770  * level is not sufficient, it's impossible to get here during recovery.
8771  */
8772  if (!backup_stopped_in_recovery && !XLogIsNeeded())
8773  ereport(ERROR,
8774  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8775  errmsg("WAL level not sufficient for making an online backup"),
8776  errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
8777 
8778  /*
8779  * OK to update backup counter and session-level lock.
8780  *
8781  * Note that CHECK_FOR_INTERRUPTS() must not occur while updating them,
8782  * otherwise they can be updated inconsistently, which might cause
8783  * do_pg_abort_backup() to fail.
8784  */
8786 
8787  /*
8788  * It is expected that each do_pg_backup_start() call is matched by
8789  * exactly one do_pg_backup_stop() call.
8790  */
8793 
8794  /*
8795  * Clean up session-level lock.
8796  *
8797  * You might think that WALInsertLockRelease() can be called before
8798  * cleaning up session-level lock because session-level lock doesn't need
8799  * to be protected with WAL insertion lock. But since
8800  * CHECK_FOR_INTERRUPTS() can occur in it, session-level lock must be
8801  * cleaned up before it.
8802  */
8804 
8806 
8807  /*
8808  * If we are taking an online backup from the standby, we confirm that the
8809  * standby has not been promoted during the backup.
8810  */
8811  if (state->started_in_recovery && !backup_stopped_in_recovery)
8812  ereport(ERROR,
8813  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8814  errmsg("the standby was promoted during online backup"),
8815  errhint("This means that the backup being taken is corrupt "
8816  "and should not be used. "
8817  "Try taking another online backup.")));
8818 
8819  /*
8820  * During recovery, we don't write an end-of-backup record. We assume that
8821  * pg_control was backed up last and its minimum recovery point can be
8822  * available as the backup end location. Since we don't have an
8823  * end-of-backup record, we use the pg_control value to check whether
8824  * we've reached the end of backup when starting recovery from this
8825  * backup. We have no way of checking if pg_control wasn't backed up last
8826  * however.
8827  *
8828  * We don't force a switch to new WAL file but it is still possible to
8829  * wait for all the required files to be archived if waitforarchive is
8830  * true. This is okay if we use the backup to start a standby and fetch
8831  * the missing WAL using streaming replication. But in the case of an
8832  * archive recovery, a user should set waitforarchive to true and wait for
8833  * them to be archived to ensure that all the required files are
8834  * available.
8835  *
8836  * We return the current minimum recovery point as the backup end
8837  * location. Note that it can be greater than the exact backup end
8838  * location if the minimum recovery point is updated after the backup of
8839  * pg_control. This is harmless for current uses.
8840  *
8841  * XXX currently a backup history file is for informational and debug
8842  * purposes only. It's not essential for an online backup. Furthermore,
8843  * even if it's created, it will not be archived during recovery because
8844  * an archiver is not invoked. So it doesn't seem worthwhile to write a
8845  * backup history file during recovery.
8846  */
8847  if (backup_stopped_in_recovery)
8848  {
8849  XLogRecPtr recptr;
8850 
8851  /*
8852  * Check to see if all WAL replayed during online backup contain
8853  * full-page writes.
8854  */
8856  recptr = XLogCtl->lastFpwDisableRecPtr;
8858 
8859  if (state->startpoint <= recptr)
8860  ereport(ERROR,
8861  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
8862  errmsg("WAL generated with full_page_writes=off was replayed "
8863  "during online backup"),
8864  errhint("This means that the backup being taken on the standby "
8865  "is corrupt and should not be used. "
8866  "Enable full_page_writes and run CHECKPOINT on the primary, "
8867  "and then try an online backup again.")));
8868 
8869 
8870  LWLockAcquire(ControlFileLock, LW_SHARED);
8871  state->stoppoint = ControlFile->minRecoveryPoint;
8873  LWLockRelease(ControlFileLock);
8874  }
8875  else
8876  {
8877  char *history_file;
8878 
8879  /*
8880  * Write the backup-end xlog record
8881  */
8882  XLogBeginInsert();
8883  XLogRegisterData((char *) (&state->startpoint),
8884  sizeof(state->startpoint));
8885  state->stoppoint = XLogInsert(RM_XLOG_ID, XLOG_BACKUP_END);
8886 
8887  /*
8888  * Given that we're not in recovery, InsertTimeLineID is set and can't
8889  * change, so we can read it without a lock.
8890  */
8891  state->stoptli = XLogCtl->InsertTimeLineID;
8892 
8893  /*
8894  * Force a switch to a new xlog segment file, so that the backup is
8895  * valid as soon as archiver moves out the current segment file.
8896  */
8897  RequestXLogSwitch(false);
8898 
8899  state->stoptime = (pg_time_t) time(NULL);
8900 
8901  /*
8902  * Write the backup history file
8903  */
8904  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8905  BackupHistoryFilePath(histfilepath, state->stoptli, _logSegNo,
8906  state->startpoint, wal_segment_size);
8907  fp = AllocateFile(histfilepath, "w");
8908  if (!fp)
8909  ereport(ERROR,
8911  errmsg("could not create file \"%s\": %m",
8912  histfilepath)));
8913 
8914  /* Build and save the contents of the backup history file */
8915  history_file = build_backup_content(state, true);
8916  fprintf(fp, "%s", history_file);
8917  pfree(history_file);
8918 
8919  if (fflush(fp) || ferror(fp) || FreeFile(fp))
8920  ereport(ERROR,
8922  errmsg("could not write file \"%s\": %m",
8923  histfilepath)));
8924 
8925  /*
8926  * Clean out any no-longer-needed history files. As a side effect,
8927  * this will post a .ready file for the newly created history file,
8928  * notifying the archiver that history file may be archived
8929  * immediately.
8930  */
8932  }
8933 
8934  /*
8935  * If archiving is enabled, wait for all the required WAL files to be
8936  * archived before returning. If archiving isn't enabled, the required WAL
8937  * needs to be transported via streaming replication (hopefully with
8938  * wal_keep_size set high enough), or some more exotic mechanism like
8939  * polling and copying files from pg_wal with script. We have no knowledge
8940  * of those mechanisms, so it's up to the user to ensure that he gets all
8941  * the required WAL.
8942  *
8943  * We wait until both the last WAL file filled during backup and the
8944  * history file have been archived, and assume that the alphabetic sorting
8945  * property of the WAL files ensures any earlier WAL files are safely
8946  * archived as well.
8947  *
8948  * We wait forever, since archive_command is supposed to work and we
8949  * assume the admin wanted his backup to work completely. If you don't
8950  * wish to wait, then either waitforarchive should be passed in as false,
8951  * or you can set statement_timeout. Also, some notices are issued to
8952  * clue in anyone who might be doing this interactively.
8953  */
8954 
8955  if (waitforarchive &&
8956  ((!backup_stopped_in_recovery && XLogArchivingActive()) ||
8957  (backup_stopped_in_recovery && XLogArchivingAlways())))
8958  {
8959  XLByteToPrevSeg(state->stoppoint, _logSegNo, wal_segment_size);
8960  XLogFileName(lastxlogfilename, state->stoptli, _logSegNo,
8962 
8963  XLByteToSeg(state->startpoint, _logSegNo, wal_segment_size);
8964  BackupHistoryFileName(histfilename, state->stoptli, _logSegNo,
8965  state->startpoint, wal_segment_size);
8966 
8967  seconds_before_warning = 60;
8968  waits = 0;
8969 
8970  while (XLogArchiveIsBusy(lastxlogfilename) ||
8971  XLogArchiveIsBusy(histfilename))
8972  {
8974 
8975  if (!reported_waiting && waits > 5)
8976  {
8977  ereport(NOTICE,
8978  (errmsg("base backup done, waiting for required WAL segments to be archived")));
8979  reported_waiting = true;
8980  }
8981 
8982  (void) WaitLatch(MyLatch,
8984  1000L,
8985  WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE);
8987 
8988  if (++waits >= seconds_before_warning)
8989  {
8990  seconds_before_warning *= 2; /* This wraps in >10 years... */
8991  ereport(WARNING,
8992  (errmsg("still waiting for all required WAL segments to be archived (%d seconds elapsed)",
8993  waits),
8994  errhint("Check that your archive_command is executing properly. "
8995  "You can safely cancel this backup, "
8996  "but the database backup will not be usable without all the WAL segments.")));
8997  }
8998  }
8999 
9000  ereport(NOTICE,
9001  (errmsg("all required WAL segments have been archived")));
9002  }
9003  else if (waitforarchive)
9004  ereport(NOTICE,
9005  (errmsg("WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to complete the backup")));
9006 }
#define NOTICE
Definition: elog.h:35
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2553
int FreeFile(FILE *file)
Definition: fd.c:2751
struct Latch * MyLatch
Definition: globals.c:58
void ResetLatch(Latch *latch)
Definition: latch.c:725
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:518
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
static void const char fflush(stdout)
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define XLOG_BACKUP_END
Definition: pg_control.h:72
#define fprintf
Definition: port.h:242
static void CleanupBackupHistory(void)
Definition: xlog.c:3924
#define XLogArchivingActive()
Definition: xlog.h:97
#define XLogArchivingAlways()
Definition: xlog.h:100
#define XLByteToPrevSeg(xlrp, logSegNo, wal_segsz_bytes)
static void BackupHistoryFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
static void BackupHistoryFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, XLogRecPtr startpoint, int wal_segsz_bytes)
bool XLogArchiveIsBusy(const char *xlog)
Definition: xlogarchive.c:620
char * build_backup_content(BackupState *state, bool ishistoryfile)
Definition: xlogbackup.c:29

References AllocateFile(), Assert(), BackupHistoryFileName(), BackupHistoryFilePath(), build_backup_content(), CHECK_FOR_INTERRUPTS, CleanupBackupHistory(), ControlFile, ereport, errcode(), errcode_for_file_access(), errhint(), errmsg(), ERROR, fflush(), fprintf, FreeFile(), XLogCtlData::info_lck, XLogCtlData::Insert, XLogCtlData::InsertTimeLineID, XLogCtlData::lastFpwDisableRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), MAXFNAMELEN, MAXPGPATH, ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, MyLatch, NOTICE, pfree(), RecoveryInProgress(), RequestXLogSwitch(), ResetLatch(), XLogCtlInsert::runningBackups, SESSION_BACKUP_NONE, sessionBackupState, SpinLockAcquire, SpinLockRelease, WaitLatch(), wal_segment_size, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), WARNING, WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, WL_TIMEOUT, XLByteToPrevSeg, XLByteToSeg, XLOG_BACKUP_END, XLogArchiveIsBusy(), XLogArchivingActive, XLogArchivingAlways, XLogBeginInsert(), XLogCtl, XLogFileName(), XLogInsert(), XLogIsNeeded, and XLogRegisterData().

Referenced by perform_base_backup(), and pg_backup_stop().

◆ get_backup_status()

SessionBackupState get_backup_status ( void  )

Definition at line 8733 of file xlog.c.

8734 {
8735  return sessionBackupState;
8736 }

References sessionBackupState.

Referenced by pg_backup_start(), pg_backup_stop(), and SendBaseBackup().

◆ GetActiveWalLevelOnStandby()

WalLevel GetActiveWalLevelOnStandby ( void  )

Definition at line 4592 of file xlog.c.

4593 {
4594  return ControlFile->wal_level;
4595 }

References ControlFile, and ControlFileData::wal_level.

Referenced by CheckLogicalDecodingRequirements().

◆ GetFakeLSNForUnloggedRel()

XLogRecPtr GetFakeLSNForUnloggedRel ( void  )

Definition at line 4330 of file xlog.c.

4331 {
4332  XLogRecPtr nextUnloggedLSN;
4333 
4334  /* increment the unloggedLSN counter, need SpinLock */
4336  nextUnloggedLSN = XLogCtl->unloggedLSN++;
4338 
4339  return nextUnloggedLSN;
4340 }

References SpinLockAcquire, SpinLockRelease, XLogCtlData::ulsn_lck, XLogCtlData::unloggedLSN, and XLogCtl.

Referenced by gistGetFakeLSN().

◆ GetFlushRecPtr()

XLogRecPtr GetFlushRecPtr ( TimeLineID insertTLI)

Definition at line 6204 of file xlog.c.

6205 {
6207 
6211 
6212  /*
6213  * If we're writing and flushing WAL, the time line can't be changing, so
6214  * no lock is required.
6215  */
6216  if (insertTLI)
6217  *insertTLI = XLogCtl->InsertTimeLineID;
6218 
6219  return LogwrtResult.Flush;
6220 }
RecoveryState SharedRecoveryState
Definition: xlog.c:522
XLogwrtResult LogwrtResult
Definition: xlog.c:484
XLogRecPtr Flush
Definition: xlog.c:337
static XLogwrtResult LogwrtResult
Definition: xlog.c:618

References Assert(), XLogwrtResult::Flush, XLogCtlData::info_lck, XLogCtlData::InsertTimeLineID, XLogCtlData::LogwrtResult, LogwrtResult, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by binary_upgrade_logical_slot_has_caught_up(), get_flush_position(), GetCurrentLSN(), IdentifySystem(), pg_current_wal_flush_lsn(), pg_logical_slot_get_changes_guts(), pg_replication_slot_advance(), read_local_xlog_page_guts(), StartReplication(), WalSndWaitForWal(), XLogSendLogical(), and XLogSendPhysical().

◆ GetFullPageWriteInfo()

void GetFullPageWriteInfo ( XLogRecPtr RedoRecPtr_p,
bool doPageWrites_p 
)

Definition at line 6172 of file xlog.c.

6173 {
6174  *RedoRecPtr_p = RedoRecPtr;
6175  *doPageWrites_p = doPageWrites;
6176 }
static bool doPageWrites
Definition: xlog.c:289

References doPageWrites, and RedoRecPtr.

Referenced by XLogCheckBufferNeedsBackup(), and XLogInsert().

◆ GetInsertRecPtr()

XLogRecPtr GetInsertRecPtr ( void  )

Definition at line 6187 of file xlog.c.

6188 {
6189  XLogRecPtr recptr;
6190 
6192  recptr = XLogCtl->LogwrtRqst.Write;
6194 
6195  return recptr;
6196 }
XLogwrtRqst LogwrtRqst
Definition: xlog.c:464
XLogRecPtr Write
Definition: xlog.c:330

References XLogCtlData::info_lck, XLogCtlData::LogwrtRqst, SpinLockAcquire, SpinLockRelease, XLogwrtRqst::Write, and XLogCtl.

Referenced by CheckpointerMain(), gistvacuumscan(), and IsCheckpointOnSchedule().

◆ GetLastImportantRecPtr()

XLogRecPtr GetLastImportantRecPtr ( void  )

Definition at line 6244 of file xlog.c.

6245 {
6247  int i;
6248 
6249  for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
6250  {
6251  XLogRecPtr last_important;
6252 
6253  /*
6254  * Need to take a lock to prevent torn reads of the LSN, which are
6255  * possible on some of the supported platforms. WAL insert locks only
6256  * support exclusive mode, so we have to use that.
6257  */
6259  last_important = WALInsertLocks[i].l.lastImportantAt;
6260  LWLockRelease(&WALInsertLocks[i].l.lock);
6261 
6262  if (res < last_important)
6263  res = last_important;
6264  }
6265 
6266  return res;
6267 }
int i
Definition: isn.c:73
XLogRecPtr lastImportantAt
Definition: xlog.c:380
WALInsertLock l
Definition: xlog.c:392
static WALInsertLockPadded * WALInsertLocks
Definition: xlog.c:575
#define NUM_XLOGINSERT_LOCKS
Definition: xlog.c:153

References i, InvalidXLogRecPtr, WALInsertLockPadded::l, WALInsertLock::lastImportantAt, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), NUM_XLOGINSERT_LOCKS, res, and WALInsertLocks.

Referenced by BackgroundWriterMain(), CheckArchiveTimeout(), and CreateCheckPoint().

◆ GetMockAuthenticationNonce()

char* GetMockAuthenticationNonce ( void  )

Definition at line 4304 of file xlog.c.

4305 {
4306  Assert(ControlFile != NULL);
4308 }
char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN]
Definition: pg_control.h:228

References Assert(), ControlFile, and ControlFileData::mock_authentication_nonce.

Referenced by scram_mock_salt().

◆ GetRecoveryState()

RecoveryState GetRecoveryState ( void  )

Definition at line 6075 of file xlog.c.

6076 {
6077  RecoveryState retval;
6078 
6080  retval = XLogCtl->SharedRecoveryState;
6082 
6083  return retval;
6084 }

References XLogCtlData::info_lck, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by XLogArchiveCheckDone().

◆ GetRedoRecPtr()

XLogRecPtr GetRedoRecPtr ( void  )

Definition at line 6142 of file xlog.c.

6143 {
6144  XLogRecPtr ptr;
6145 
6146  /*
6147  * The possibly not up-to-date copy in XlogCtl is enough. Even if we
6148  * grabbed a WAL insertion lock to read the authoritative value in
6149  * Insert->RedoRecPtr, someone might update it just after we've released
6150  * the lock.
6151  */
6153  ptr = XLogCtl->RedoRecPtr;
6155 
6156  if (RedoRecPtr < ptr)
6157  RedoRecPtr = ptr;
6158 
6159  return RedoRecPtr;
6160 }

References XLogCtlData::info_lck, RedoRecPtr, XLogCtlData::RedoRecPtr, SpinLockAcquire, SpinLockRelease, and XLogCtl.

Referenced by CheckPointLogicalRewriteHeap(), CheckPointSnapBuild(), nextval_internal(), ReplicationSlotReserveWal(), XLogPageRead(), XLogSaveBufferForHint(), and XLogWrite().

◆ GetSystemIdentifier()

uint64 GetSystemIdentifier ( void  )

Definition at line 4294 of file xlog.c.

4295 {
4296  Assert(ControlFile != NULL);
4298 }
uint64 system_identifier
Definition: pg_control.h:109

References Assert(), ControlFile, and ControlFileData::system_identifier.

Referenced by IdentifySystem(), ReplicationSlotNameForTablesync(), and WalReceiverMain().

◆ GetWALAvailability()

WALAvailability GetWALAvailability ( XLogRecPtr  targetLSN)

Definition at line 7518 of file xlog.c.

7519 {
7520  XLogRecPtr currpos; /* current write LSN */
7521  XLogSegNo currSeg; /* segid of currpos */
7522  XLogSegNo targetSeg; /* segid of targetLSN */
7523  XLogSegNo oldestSeg; /* actual oldest segid */
7524  XLogSegNo oldestSegMaxWalSize; /* oldest segid kept by max_wal_size */
7525  XLogSegNo oldestSlotSeg; /* oldest segid kept by slot */
7526  uint64 keepSegs;
7527 
7528  /*
7529  * slot does not reserve WAL. Either deactivated, or has never been active
7530  */
7531  if (XLogRecPtrIsInvalid(targetLSN))
7532  return WALAVAIL_INVALID_LSN;
7533 
7534  /*
7535  * Calculate the oldest segment currently reserved by all slots,
7536  * considering wal_keep_size and max_slot_wal_keep_size. Initialize
7537  * oldestSlotSeg to the current segment.
7538  */
7539  currpos = GetXLogWriteRecPtr();
7540  XLByteToSeg(currpos, oldestSlotSeg, wal_segment_size);
7541  KeepLogSeg(currpos, &oldestSlotSeg);
7542 
7543  /*
7544  * Find the oldest extant segment file. We get 1 until checkpoint removes
7545  * the first WAL segment file since startup, which causes the status being
7546  * wrong under certain abnormal conditions but that doesn't actually harm.
7547  */
7548  oldestSeg = XLogGetLastRemovedSegno() + 1;
7549 
7550  /* calculate oldest segment by max_wal_size */
7551  XLByteToSeg(currpos, currSeg, wal_segment_size);
7553 
7554  if (currSeg > keepSegs)
7555  oldestSegMaxWalSize = currSeg - keepSegs;
7556  else
7557  oldestSegMaxWalSize = 1;
7558 
7559  /* the segment we care about */
7560  XLByteToSeg(targetLSN, targetSeg, wal_segment_size);
7561 
7562  /*
7563  * No point in returning reserved or extended status values if the
7564  * targetSeg is known to be lost.
7565  */
7566  if (targetSeg >= oldestSlotSeg)
7567  {
7568  /* show "reserved" when targetSeg is within max_wal_size */
7569  if (targetSeg >= oldestSegMaxWalSize)
7570  return WALAVAIL_RESERVED;
7571 
7572  /* being retained by slots exceeding max_wal_size */
7573  return WALAVAIL_EXTENDED;
7574  }
7575 
7576  /* WAL segments are no longer retained but haven't been removed yet */
7577  if (targetSeg >= oldestSeg)
7578  return WALAVAIL_UNRESERVED;
7579 
7580  /* Definitely lost */
7581  return WALAVAIL_REMOVED;
7582 }
XLogSegNo XLogGetLastRemovedSegno(void)
Definition: xlog.c:3581
int max_wal_size_mb
Definition: xlog.c:117
#define ConvertToXSegs(x, segsize)
Definition: xlog.c:609
XLogRecPtr GetXLogWriteRecPtr(void)
Definition: xlog.c:9083
@ WALAVAIL_REMOVED
Definition: xlog.h:191

References ConvertToXSegs, GetXLogWriteRecPtr(), KeepLogSeg(), max_wal_size_mb, wal_segment_size, WALAVAIL_EXTENDED, WALAVAIL_INVALID_LSN, WALAVAIL_REMOVED, WALAVAIL_RESERVED, WALAVAIL_UNRESERVED, XLByteToSeg, XLogGetLastRemovedSegno(), and XLogRecPtrIsInvalid.

Referenced by pg_get_replication_slots().

◆ GetWALInsertionTimeLine()

TimeLineID GetWALInsertionTimeLine ( void  )

Definition at line 6227 of file xlog.c.

6228 {
6230 
6231  /* Since the value can't be changing, no lock is required. */
6232  return XLogCtl->InsertTimeLineID;
6233 }

References Assert(), XLogCtlData::InsertTimeLineID, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by logical_read_xlog_page(), pg_walfile_name(), pg_walfile_name_offset(), ReadReplicationSlot(), and XLogSendPhysical().

◆ GetXLogInsertRecPtr()

XLogRecPtr GetXLogInsertRecPtr ( void  )

Definition at line 9067 of file xlog.c.

9068 {
9070  uint64 current_bytepos;
9071 
9072  SpinLockAcquire(&Insert->insertpos_lck);
9073  current_bytepos = Insert->CurrBytePos;
9074  SpinLockRelease(&Insert->insertpos_lck);
9075 
9076  return XLogBytePosToRecPtr(current_bytepos);
9077 }

References XLogCtlData::Insert, Insert(), SpinLockAcquire, SpinLockRelease, XLogBytePosToRecPtr(), and XLogCtl.

Referenced by CreateOverwriteContrecordRecord(), gistGetFakeLSN(), logical_begin_heap_rewrite(), pg_current_wal_insert_lsn(), and ReplicationSlotReserveWal().

◆ GetXLogWriteRecPtr()

◆ InitializeWalConsistencyChecking()

void InitializeWalConsistencyChecking ( void  )

Definition at line 4517 of file xlog.c.

4518 {
4520 
4522  {
4523  struct config_generic *guc;
4524 
4525  guc = find_option("wal_consistency_checking", false, false, ERROR);
4526 
4528 
4529  set_config_option_ext("wal_consistency_checking",
4531  guc->scontext, guc->source, guc->srole,
4532  GUC_ACTION_SET, true, ERROR, false);
4533 
4534  /* checking should not be deferred again */
4536  }
4537 }
struct config_generic * find_option(const char *name, bool create_placeholders, bool skip_errors, int elevel)
Definition: guc.c:1230
int set_config_option_ext(const char *name, const char *value, GucContext context, GucSource source, Oid srole, GucAction action, bool changeVal, int elevel, bool is_reload)
Definition: guc.c:3354
@ GUC_ACTION_SET
Definition: guc.h:199
bool process_shared_preload_libraries_done
Definition: miscinit.c:1772
GucContext scontext
Definition: guc_tables.h:166
GucSource source
Definition: guc_tables.h:164
char * wal_consistency_checking_string
Definition: xlog.c:128
static bool check_wal_consistency_checking_deferred
Definition: xlog.c:169

References Assert(), check_wal_consistency_checking_deferred, ERROR, find_option(), GUC_ACTION_SET, process_shared_preload_libraries_done, config_generic::scontext, set_config_option_ext(), config_generic::source, config_generic::srole, and wal_consistency_checking_string.

Referenced by PostgresSingleUserMain(), and PostmasterMain().

◆ IsInstallXLogFileSegmentActive()

bool IsInstallXLogFileSegmentActive ( void  )

Definition at line 9126 of file xlog.c.

9127 {
9128  bool result;
9129 
9130  LWLockAcquire(ControlFileLock, LW_SHARED);
9132  LWLockRelease(ControlFileLock);
9133 
9134  return result;
9135 }
bool InstallXLogFileSegmentActive
Definition: xlog.c:532

References XLogCtlData::InstallXLogFileSegmentActive, LW_SHARED, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by XLogFileRead().

◆ issue_xlog_fsync()

void issue_xlog_fsync ( int  fd,
XLogSegNo  segno,
TimeLineID  tli 
)

Definition at line 8317 of file xlog.c.

8318 {
8319  char *msg = NULL;
8320  instr_time start;
8321 
8322  Assert(tli != 0);
8323 
8324  /*
8325  * Quick exit if fsync is disabled or write() has already synced the WAL
8326  * file.
8327  */
8328  if (!enableFsync ||
8331  return;
8332 
8333  /* Measure I/O timing to sync the WAL file */
8334  if (track_wal_io_timing)
8335  INSTR_TIME_SET_CURRENT(start);
8336  else
8337  INSTR_TIME_SET_ZERO(start);
8338 
8339  pgstat_report_wait_start(WAIT_EVENT_WAL_SYNC);
8340  switch (wal_sync_method)
8341  {
8342  case WAL_SYNC_METHOD_FSYNC:
8343  if (pg_fsync_no_writethrough(fd) != 0)
8344  msg = _("could not fsync file \"%s\": %m");
8345  break;
8346 #ifdef HAVE_FSYNC_WRITETHROUGH
8348  if (pg_fsync_writethrough(fd) != 0)
8349  msg = _("could not fsync write-through file \"%s\": %m");
8350  break;
8351 #endif
8353  if (pg_fdatasync(fd) != 0)
8354  msg = _("could not fdatasync file \"%s\": %m");
8355  break;
8356  case WAL_SYNC_METHOD_OPEN:
8358  /* not reachable */
8359  Assert(false);
8360  break;
8361  default:
8362  elog(PANIC, "unrecognized wal_sync_method: %d", wal_sync_method);
8363  break;
8364  }
8365 
8366  /* PANIC if failed to fsync */
8367  if (msg)
8368  {
8369  char xlogfname[MAXFNAMELEN];
8370  int save_errno = errno;
8371 
8372  XLogFileName(xlogfname, tli, segno, wal_segment_size);
8373  errno = save_errno;
8374  ereport(PANIC,
8376  errmsg(msg, xlogfname)));
8377  }
8378 
8380 
8381  /*
8382  * Increment the I/O timing and the number of times WAL files were synced.
8383  */
8384  if (track_wal_io_timing)
8385  {
8386  instr_time end;
8387 
8390  }
8391 
8393 }
#define _(x)
Definition: elog.c:91
int pg_fsync_no_writethrough(int fd)
Definition: fd.c:441
int pg_fdatasync(int fd)
Definition: fd.c:480
int pg_fsync_writethrough(int fd)
Definition: fd.c:461
bool enableFsync
Definition: globals.c:125
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_SET_ZERO(t)
Definition: instr_time.h:172
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:184
PgStat_PendingWalStats PendingWalStats
Definition: pgstat_wal.c:24
static int fd(const char *x, int i)
Definition: preproc-init.c:105
instr_time wal_sync_time
Definition: pgstat.h:453
PgStat_Counter wal_sync
Definition: pgstat.h:451
int wal_sync_method
Definition: xlog.c:133
bool track_wal_io_timing
Definition: xlog.c:140

References _, Assert(), elog(), enableFsync, ereport, errcode_for_file_access(), errmsg(), fd(), INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, INSTR_TIME_SET_ZERO, MAXFNAMELEN, PANIC, PendingWalStats, pg_fdatasync(), pg_fsync_no_writethrough(), pg_fsync_writethrough(), pgstat_report_wait_end(), pgstat_report_wait_start(), track_wal_io_timing, wal_segment_size, PgStat_PendingWalStats::wal_sync, wal_sync_method, WAL_SYNC_METHOD_FDATASYNC, WAL_SYNC_METHOD_FSYNC, WAL_SYNC_METHOD_FSYNC_WRITETHROUGH, WAL_SYNC_METHOD_OPEN, WAL_SYNC_METHOD_OPEN_DSYNC, PgStat_PendingWalStats::wal_sync_time, and XLogFileName().

Referenced by XLogWalRcvFlush(), and XLogWrite().

◆ LocalProcessControlFile()

void LocalProcessControlFile ( bool  reset)

Definition at line 4579 of file xlog.c.

4580 {
4581  Assert(reset || ControlFile == NULL);
4582  ControlFile = palloc(sizeof(ControlFileData));
4583  ReadControlFile();
4584 }
void reset(void)
Definition: sql-declare.c:600

References Assert(), ControlFile, palloc(), ReadControlFile(), and reset().

Referenced by PostgresSingleUserMain(), PostmasterMain(), and PostmasterStateMachine().

◆ ReachedEndOfBackup()

void ReachedEndOfBackup ( XLogRecPtr  EndRecPtr,
TimeLineID  tli 
)

Definition at line 5952 of file xlog.c.

5953 {
5954  /*
5955  * We have reached the end of base backup, as indicated by pg_control. The
5956  * data on disk is now consistent (unless minRecoveryPoint is further
5957  * ahead, which can happen if we crashed during previous recovery). Reset
5958  * backupStartPoint and backupEndPoint, and update minRecoveryPoint to
5959  * make sure we don't allow starting up at an earlier point even if
5960  * recovery is stopped and restarted soon after this.
5961  */
5962  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5963 
5964  if (ControlFile->minRecoveryPoint < EndRecPtr)
5965  {
5966  ControlFile->minRecoveryPoint = EndRecPtr;
5968  }
5969 
5972  ControlFile->backupEndRequired = false;
5974 
5975  LWLockRelease(ControlFileLock);
5976 }
XLogRecPtr backupStartPoint
Definition: pg_control.h:169
bool backupEndRequired
Definition: pg_control.h:171
XLogRecPtr backupEndPoint
Definition: pg_control.h:170

References ControlFileData::backupEndPoint, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFile, InvalidXLogRecPtr, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, and UpdateControlFile().

Referenced by CheckRecoveryConsistency().

◆ RecoveryInProgress()

bool RecoveryInProgress ( void  )

Definition at line 6039 of file xlog.c.

6040 {
6041  /*
6042  * We check shared state each time only until we leave recovery mode. We
6043  * can't re-enter recovery, so there's no need to keep checking after the
6044  * shared variable has once been seen false.
6045  */
6047  return false;
6048  else
6049  {
6050  /*
6051  * use volatile pointer to make sure we make a fresh read of the
6052  * shared variable.
6053  */
6054  volatile XLogCtlData *xlogctl = XLogCtl;
6055 
6057 
6058  /*
6059  * Note: We don't need a memory barrier when we're still in recovery.
6060  * We might exit recovery immediately after return, so the caller
6061  * can't rely on 'true' meaning that we're still in recovery anyway.
6062  */
6063 
6064  return LocalRecoveryInProgress;
6065  }
6066 }
static bool LocalRecoveryInProgress
Definition: xlog.c:227

References LocalRecoveryInProgress, RECOVERY_STATE_DONE, XLogCtlData::SharedRecoveryState, and XLogCtl.

Referenced by BackgroundWriterMain(), BeginReportingGUCOptions(), brin_desummarize_range(), brin_summarize_range(), btree_index_mainfork_expected(), check_transaction_isolation(), check_transaction_read_only(), CheckArchiveTimeout(), CheckLogicalDecodingRequirements(), CheckpointerMain(), ComputeXidHorizons(), CreateCheckPoint(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), CreateRestartPoint(), do_pg_backup_start(), do_pg_backup_stop(), error_commit_ts_disabled(), get_relation_info(), GetCurrentLSN(), GetNewMultiXactId(), GetNewObjectId(), GetNewTransactionId(), GetOldestActiveTransactionId(), GetOldestSafeDecodingTransactionId(), GetRunningTransactionData(), GetSerializableTransactionSnapshot(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), gin_clean_pending_list(), GlobalVisHorizonKindForRel(), heap_force_common(), heap_page_prune_opt(), IdentifySystem(), InitTempTableNamespace(), IsCheckpointOnSchedule(), LockAcquireExtended(), logical_read_xlog_page(), MaintainLatestCompletedXid(), MarkBufferDirtyHint(), perform_base_backup(), pg_create_restore_point(), pg_current_wal_flush_lsn(), pg_current_wal_insert_lsn(), pg_current_wal_lsn(), pg_get_wal_replay_pause_state(), pg_is_in_recovery(), pg_is_wal_replay_paused(), pg_log_standby_snapshot(), pg_logical_slot_get_changes_guts(), pg_promote(), pg_replication_slot_advance(), pg_switch_wal(), pg_wal_replay_pause(), pg_wal_replay_resume(), pg_walfile_name(), pg_walfile_name_offset(), PrepareRedoAdd(), PrepareRedoRemove(), PreventCommandDuringRecovery(), ProcSleep(), read_local_xlog_page_guts(), ReadReplicationSlot(), recovery_create_dbdir(), ReplicationSlotReserveWal(), replorigin_check_prerequisites(), ReportChangedGUCOptions(), sendDir(), SerialSetActiveSerXmin(), show_in_hot_standby(), ShutdownXLOG(), SnapBuildWaitSnapshot(), standard_ProcessUtility(), StartLogicalReplication(), StartReplication(), StartTransaction(), TransactionIdIsInProgress(), TruncateMultiXact(), UpdateFullPageWrites(), verify_heapam(), WalReceiverMain(), WalSndWaitForWal(), xlog_decode(), XLogBackgroundFlush(), XLogFlush(), XLogInsertAllowed(), XLogNeedsFlush(), and XLogSendPhysical().

◆ register_persistent_abort_backup_handler()

void register_persistent_abort_backup_handler ( void  )

Definition at line 9053 of file xlog.c.

9054 {
9055  static bool already_done = false;
9056 
9057  if (already_done)
9058  return;
9060  already_done = true;
9061 }
void before_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:337

References before_shmem_exit(), DatumGetBool(), and do_pg_abort_backup().

Referenced by pg_backup_start().

◆ RemoveNonParentXlogFiles()

void RemoveNonParentXlogFiles ( XLogRecPtr  switchpoint,
TimeLineID  newTLI 
)

Definition at line 3726 of file xlog.c.

3727 {
3728  DIR *xldir;
3729  struct dirent *xlde;
3730  char switchseg[MAXFNAMELEN];
3731  XLogSegNo endLogSegNo;
3732  XLogSegNo switchLogSegNo;
3733  XLogSegNo recycleSegNo;
3734 
3735  /*
3736  * Initialize info about where to begin the work. This will recycle,
3737  * somewhat arbitrarily, 10 future segments.
3738  */
3739  XLByteToPrevSeg(switchpoint, switchLogSegNo, wal_segment_size);
3740  XLByteToSeg(switchpoint, endLogSegNo, wal_segment_size);
3741  recycleSegNo = endLogSegNo + 10;
3742 
3743  /*
3744  * Construct a filename of the last segment to be kept.
3745  */
3746  XLogFileName(switchseg, newTLI, switchLogSegNo, wal_segment_size);
3747 
3748  elog(DEBUG2, "attempting to remove WAL segments newer than log file %s",
3749  switchseg);
3750 
3751  xldir = AllocateDir(XLOGDIR);
3752 
3753  while ((xlde = ReadDir(xldir, XLOGDIR)) != NULL)
3754  {
3755  /* Ignore files that are not XLOG segments */
3756  if (!IsXLogFileName(xlde->d_name))
3757  continue;
3758 
3759  /*
3760  * Remove files that are on a timeline older than the new one we're
3761  * switching to, but with a segment number >= the first segment on the
3762  * new timeline.
3763  */
3764  if (strncmp(xlde->d_name, switchseg, 8) < 0 &&
3765  strcmp(xlde->d_name + 8, switchseg + 8) > 0)
3766  {
3767  /*
3768  * If the file has already been marked as .ready, however, don't
3769  * remove it yet. It should be OK to remove it - files that are
3770  * not part of our timeline history are not required for recovery
3771  * - but seems safer to let them be archived and removed later.
3772  */
3773  if (!XLogArchiveIsReady(xlde->d_name))
3774  RemoveXlogFile(xlde, recycleSegNo, &endLogSegNo, newTLI);
3775  }
3776  }
3777 
3778  FreeDir(xldir);
3779 }
static void RemoveXlogFile(const struct dirent *segment_de, XLogSegNo recycleSegNo, XLogSegNo *endlogSegNo, TimeLineID insertTLI)
Definition: xlog.c:3795
static bool IsXLogFileName(const char *fname)
#define XLOGDIR
bool XLogArchiveIsReady(const char *xlog)
Definition: xlogarchive.c:695

References AllocateDir(), dirent::d_name, DEBUG2, elog(), FreeDir(), IsXLogFileName(), MAXFNAMELEN, ReadDir(), RemoveXlogFile(), wal_segment_size, XLByteToPrevSeg, XLByteToSeg, XLogArchiveIsReady(), XLOGDIR, and XLogFileName().

Referenced by ApplyWalRecord(), and CleanupAfterArchiveRecovery().

◆ SetInstallXLogFileSegmentActive()

void SetInstallXLogFileSegmentActive ( void  )

Definition at line 9118 of file xlog.c.

9119 {
9120  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
9122  LWLockRelease(ControlFileLock);
9123 }

References XLogCtlData::InstallXLogFileSegmentActive, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and XLogCtl.

Referenced by BootStrapXLOG(), StartupXLOG(), and WaitForWALToBecomeAvailable().

◆ SetWalWriterSleeping()

void SetWalWriterSleeping ( bool  sleeping)

Definition at line 9141 of file xlog.c.

9142 {
9144  XLogCtl->WalWriterSleeping = sleeping;
9146 }
bool WalWriterSleeping
Definition: xlog.c:539

References XLogCtlData::info_lck, SpinLockAcquire, SpinLockRelease, XLogCtlData::WalWriterSleeping, and XLogCtl.

Referenced by WalWriterMain().

◆ ShutdownXLOG()

void ShutdownXLOG ( int  code,
Datum  arg 
)

Definition at line 6290 of file xlog.c.

6291 {
6292  /*
6293  * We should have an aux process resource owner to use, and we should not
6294  * be in a transaction that's installed some other resowner.
6295  */
6297  Assert(CurrentResourceOwner == NULL ||
6300 
6301  /* Don't be chatty in standalone mode */
6303  (errmsg("shutting down")));
6304 
6305  /*
6306  * Signal walsenders to move to stopping state.
6307  */
6309 
6310  /*
6311  * Wait for WAL senders to be in stopping state. This prevents commands
6312  * from writing new WAL.
6313  */
6315 
6316  if (RecoveryInProgress())
6318  else
6319  {
6320  /*
6321  * If archiving is enabled, rotate the last XLOG file so that all the
6322  * remaining records are archived (postmaster wakes up the archiver
6323  * process one more time at the end of shutdown). The checkpoint
6324  * record will go to the next XLOG file and won't be archived (yet).
6325  */
6326  if (XLogArchivingActive())
6327  RequestXLogSwitch(false);
6328 
6330  }
6331 }
bool IsPostmasterEnvironment
Definition: globals.c:114
ResourceOwner CurrentResourceOwner
Definition: resowner.c:164
ResourceOwner AuxProcessResourceOwner
Definition: resowner.c:167
void WalSndInitStopping(void)
Definition: walsender.c:3406
void WalSndWaitStopping(void)
Definition: walsender.c:3432
bool CreateRestartPoint(int flags)
Definition: xlog.c:7246
void CreateCheckPoint(int flags)
Definition: xlog.c:6572

References Assert(), AuxProcessResourceOwner, CHECKPOINT_IMMEDIATE, CHECKPOINT_IS_SHUTDOWN, CreateCheckPoint(), CreateRestartPoint(), CurrentResourceOwner, ereport, errmsg(), IsPostmasterEnvironment, LOG, NOTICE, RecoveryInProgress(), RequestXLogSwitch(), WalSndInitStopping(), WalSndWaitStopping(), and XLogArchivingActive.

Referenced by HandleCheckpointerInterrupts(), and InitPostgres().

◆ StartupXLOG()

void StartupXLOG ( void  )

Definition at line 5147 of file xlog.c.

5148 {
5150  CheckPoint checkPoint;
5151  bool wasShutdown;
5152  bool didCrash;
5153  bool haveTblspcMap;
5154  bool haveBackupLabel;
5155  XLogRecPtr EndOfLog;
5156  TimeLineID EndOfLogTLI;
5157  TimeLineID newTLI;
5158  bool performedWalRecovery;
5159  EndOfWalRecoveryInfo *endOfRecoveryInfo;
5162  TransactionId oldestActiveXID;
5163  bool promoted = false;
5164 
5165  /*
5166  * We should have an aux process resource owner to use, and we should not
5167  * be in a transaction that's installed some other resowner.
5168  */
5170  Assert(CurrentResourceOwner == NULL ||
5173 
5174  /*
5175  * Check that contents look valid.
5176  */
5178  ereport(FATAL,
5179  (errmsg("control file contains invalid checkpoint location")));
5180 
5181  switch (ControlFile->state)
5182  {
5183  case DB_SHUTDOWNED:
5184 
5185  /*
5186  * This is the expected case, so don't be chatty in standalone
5187  * mode
5188  */
5190  (errmsg("database system was shut down at %s",
5191  str_time(ControlFile->time))));
5192  break;
5193 
5195  ereport(LOG,
5196  (errmsg("database system was shut down in recovery at %s",
5197  str_time(ControlFile->time))));
5198  break;
5199 
5200  case DB_SHUTDOWNING:
5201  ereport(LOG,
5202  (errmsg("database system shutdown was interrupted; last known up at %s",
5203  str_time(ControlFile->time))));
5204  break;
5205 
5206  case DB_IN_CRASH_RECOVERY:
5207  ereport(LOG,
5208  (errmsg("database system was interrupted while in recovery at %s",
5210  errhint("This probably means that some data is corrupted and"
5211  " you will have to use the last backup for recovery.")));
5212  break;
5213 
5215  ereport(LOG,
5216  (errmsg("database system was interrupted while in recovery at log time %s",
5218  errhint("If this has occurred more than once some data might be corrupted"
5219  " and you might need to choose an earlier recovery target.")));
5220  break;
5221 
5222  case DB_IN_PRODUCTION:
5223  ereport(LOG,
5224  (errmsg("database system was interrupted; last known up at %s",
5225  str_time(ControlFile->time))));
5226  break;
5227 
5228  default:
5229  ereport(FATAL,
5230  (errmsg("control file contains invalid database cluster state")));
5231  }
5232 
5233  /* This is just to allow attaching to startup process with a debugger */
5234 #ifdef XLOG_REPLAY_DELAY
5236  pg_usleep(60000000L);
5237 #endif
5238 
5239  /*
5240  * Verify that pg_wal and pg_wal/archive_status exist. In cases where
5241  * someone has performed a copy for PITR, these directories may have been
5242  * excluded and need to be re-created.
5243  */
5245 
5246  /* Set up timeout handler needed to report startup progress. */
5250 
5251  /*----------
5252  * If we previously crashed, perform a couple of actions:
5253  *
5254  * - The pg_wal directory may still include some temporary WAL segments
5255  * used when creating a new segment, so perform some clean up to not
5256  * bloat this path. This is done first as there is no point to sync
5257  * this temporary data.
5258  *
5259  * - There might be data which we had written, intending to fsync it, but
5260  * which we had not actually fsync'd yet. Therefore, a power failure in
5261  * the near future might cause earlier unflushed writes to be lost, even
5262  * though more recent data written to disk from here on would be
5263  * persisted. To avoid that, fsync the entire data directory.
5264  */
5265  if (ControlFile->state != DB_SHUTDOWNED &&
5267  {
5270  didCrash = true;
5271  }
5272  else
5273  didCrash = false;
5274 
5275  /*
5276  * Prepare for WAL recovery if needed.
5277  *
5278  * InitWalRecovery analyzes the control file and the backup label file, if
5279  * any. It updates the in-memory ControlFile buffer according to the
5280  * starting checkpoint, and sets InRecovery and ArchiveRecoveryRequested.
5281  * It also applies the tablespace map file, if any.
5282  */
5283  InitWalRecovery(ControlFile, &wasShutdown,
5284  &haveBackupLabel, &haveTblspcMap);
5285  checkPoint = ControlFile->checkPointCopy;
5286 
5287  /* initialize shared memory variables from the checkpoint record */
5288  TransamVariables->nextXid = checkPoint.nextXid;
5289  TransamVariables->nextOid = checkPoint.nextOid;
5291  MultiXactSetNextMXact(checkPoint.nextMulti, checkPoint.nextMultiOffset);
5292  AdvanceOldestClogXid(checkPoint.oldestXid);
5293  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
5294  SetMultiXactIdLimit(checkPoint.oldestMulti, checkPoint.oldestMultiDB, true);
5296  checkPoint.newestCommitTsXid);
5297  XLogCtl->ckptFullXid = checkPoint.nextXid;
5298 
5299  /*
5300  * Clear out any old relcache cache files. This is *necessary* if we do
5301  * any WAL replay, since that would probably result in the cache files
5302  * being out of sync with database reality. In theory we could leave them
5303  * in place if the database had been cleanly shut down, but it seems
5304  * safest to just remove them always and let them be rebuilt during the
5305  * first backend startup. These files needs to be removed from all
5306  * directories including pg_tblspc, however the symlinks are created only
5307  * after reading tablespace_map file in case of archive recovery from
5308  * backup, so needs to clear old relcache files here after creating
5309  * symlinks.
5310  */
5312 
5313  /*
5314  * Initialize replication slots, before there's a chance to remove
5315  * required resources.
5316  */
5318 
5319  /*
5320  * Startup logical state, needs to be setup now so we have proper data
5321  * during crash recovery.
5322  */
5324 
5325  /*
5326  * Startup CLOG. This must be done after TransamVariables->nextXid has
5327  * been initialized and before we accept connections or begin WAL replay.
5328  */
5329  StartupCLOG();
5330 
5331  /*
5332  * Startup MultiXact. We need to do this early to be able to replay
5333  * truncations.
5334  */
5335  StartupMultiXact();
5336 
5337  /*
5338  * Ditto for commit timestamps. Activate the facility if the setting is
5339  * enabled in the control file, as there should be no tracking of commit
5340  * timestamps done when the setting was disabled. This facility can be
5341  * started or stopped when replaying a XLOG_PARAMETER_CHANGE record.
5342  */
5344  StartupCommitTs();
5345 
5346  /*
5347  * Recover knowledge about replay progress of known replication partners.
5348  */
5350 
5351  /*
5352  * Initialize unlogged LSN. On a clean shutdown, it's restored from the
5353  * control file. On recovery, all unlogged relations are blown away, so
5354  * the unlogged LSN counter can be reset too.
5355  */
5358  else
5360 
5361  /*
5362  * Copy any missing timeline history files between 'now' and the recovery
5363  * target timeline from archive to pg_wal. While we don't need those files
5364  * ourselves - the history file of the recovery target timeline covers all
5365  * the previous timelines in the history too - a cascading standby server
5366  * might be interested in them. Or, if you archive the WAL from this
5367  * server to a different archive than the primary, it'd be good for all
5368  * the history files to get archived there after failover, so that you can
5369  * use one of the old timelines as a PITR target. Timeline history files
5370  * are small, so it's better to copy them unnecessarily than not copy them
5371  * and regret later.
5372  */
5374 
5375  /*
5376  * Before running in recovery, scan pg_twophase and fill in its status to
5377  * be able to work on entries generated by redo. Doing a scan before
5378  * taking any recovery action has the merit to discard any 2PC files that
5379  * are newer than the first record to replay, saving from any conflicts at
5380  * replay. This avoids as well any subsequent scans when doing recovery
5381  * of the on-disk two-phase data.
5382  */
5384 
5385  /*
5386  * When starting with crash recovery, reset pgstat data - it might not be
5387  * valid. Otherwise restore pgstat data. It's safe to do this here,
5388  * because postmaster will not yet have started any other processes.
5389  *
5390  * NB: Restoring replication slot stats relies on slot state to have
5391  * already been restored from disk.
5392  *
5393  * TODO: With a bit of extra work we could just start with a pgstat file
5394  * associated with the checkpoint redo location we're starting from.
5395  */
5396  if (didCrash)
5398  else
5400 
5401  lastFullPageWrites = checkPoint.fullPageWrites;
5402 
5405 
5406  /* REDO */
5407  if (InRecovery)
5408  {
5409  /* Initialize state for RecoveryInProgress() */
5411  if (InArchiveRecovery)
5413  else
5416 
5417  /*
5418  * Update pg_control to show that we are recovering and to show the
5419  * selected checkpoint as the place we are starting from. We also mark
5420  * pg_control with any minimum recovery stop point obtained from a
5421  * backup history file.
5422  *
5423  * No need to hold ControlFileLock yet, we aren't up far enough.
5424  */
5426 
5427  /*
5428  * If there was a backup label file, it's done its job and the info
5429  * has now been propagated into pg_control. We must get rid of the
5430  * label file so that if we crash during recovery, we'll pick up at
5431  * the latest recovery restartpoint instead of going all the way back
5432  * to the backup start point. It seems prudent though to just rename
5433  * the file out of the way rather than delete it completely.
5434  */
5435  if (haveBackupLabel)
5436  {
5437  unlink(BACKUP_LABEL_OLD);
5439  }
5440 
5441  /*
5442  * If there was a tablespace_map file, it's done its job and the
5443  * symlinks have been created. We must get rid of the map file so
5444  * that if we crash during recovery, we don't create symlinks again.
5445  * It seems prudent though to just rename the file out of the way
5446  * rather than delete it completely.
5447  */
5448  if (haveTblspcMap)
5449  {
5450  unlink(TABLESPACE_MAP_OLD);
5452  }
5453 
5454  /*
5455  * Initialize our local copy of minRecoveryPoint. When doing crash
5456  * recovery we want to replay up to the end of WAL. Particularly, in
5457  * the case of a promoted standby minRecoveryPoint value in the
5458  * control file is only updated after the first checkpoint. However,
5459  * if the instance crashes before the first post-recovery checkpoint
5460  * is completed then recovery will use a stale location causing the
5461  * startup process to think that there are still invalid page
5462  * references when checking for data consistency.
5463  */
5464  if (InArchiveRecovery)
5465  {
5468  }
5469  else
5470  {
5473  }
5474 
5475  /* Check that the GUCs used to generate the WAL allow recovery */
5477 
5478  /*
5479  * We're in recovery, so unlogged relations may be trashed and must be
5480  * reset. This should be done BEFORE allowing Hot Standby
5481  * connections, so that read-only backends don't try to read whatever
5482  * garbage is left over from before.
5483  */
5485 
5486  /*
5487  * Likewise, delete any saved transaction snapshot files that got left
5488  * behind by crashed backends.
5489  */
5491 
5492  /*
5493  * Initialize for Hot Standby, if enabled. We won't let backends in
5494  * yet, not until we've reached the min recovery point specified in
5495  * control file and we've established a recovery snapshot from a
5496  * running-xacts WAL record.
5497  */
5499  {
5500  TransactionId *xids;
5501  int nxids;
5502 
5503  ereport(DEBUG1,
5504  (errmsg_internal("initializing for hot standby")));
5505 
5507 
5508  if (wasShutdown)
5509  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
5510  else
5511  oldestActiveXID = checkPoint.oldestActiveXid;
5512  Assert(TransactionIdIsValid(oldestActiveXID));
5513 
5514  /* Tell procarray about the range of xids it has to deal with */
5516 
5517  /*
5518  * Startup subtrans only. CLOG, MultiXact and commit timestamp
5519  * have already been started up and other SLRUs are not maintained
5520  * during recovery and need not be started yet.
5521  */
5522  StartupSUBTRANS(oldestActiveXID);
5523 
5524  /*
5525  * If we're beginning at a shutdown checkpoint, we know that
5526  * nothing was running on the primary at this point. So fake-up an
5527  * empty running-xacts record and use that here and now. Recover
5528  * additional standby state for prepared transactions.
5529  */
5530  if (wasShutdown)
5531  {
5532  RunningTransactionsData running;
5533  TransactionId latestCompletedXid;
5534 
5535  /*
5536  * Construct a RunningTransactions snapshot representing a
5537  * shut down server, with only prepared transactions still
5538  * alive. We're never overflowed at this point because all
5539  * subxids are listed with their parent prepared transactions.
5540  */
5541  running.xcnt = nxids;
5542  running.subxcnt = 0;
5543  running.subxid_overflow = false;
5544  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
5545  running.oldestRunningXid = oldestActiveXID;
5546  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
5547  TransactionIdRetreat(latestCompletedXid);
5548  Assert(TransactionIdIsNormal(latestCompletedXid));
5549  running.latestCompletedXid = latestCompletedXid;
5550  running.xids = xids;
5551 
5552  ProcArrayApplyRecoveryInfo(&running);
5553 
5555  }
5556  }
5557 
5558  /*
5559  * We're all set for replaying the WAL now. Do it.
5560  */
5562  performedWalRecovery = true;
5563  }
5564  else
5565  performedWalRecovery = false;
5566 
5567  /*
5568  * Finish WAL recovery.
5569  */
5570  endOfRecoveryInfo = FinishWalRecovery();
5571  EndOfLog = endOfRecoveryInfo->endOfLog;
5572  EndOfLogTLI = endOfRecoveryInfo->endOfLogTLI;
5573  abortedRecPtr = endOfRecoveryInfo->abortedRecPtr;
5574  missingContrecPtr = endOfRecoveryInfo->missingContrecPtr;
5575 
5576  /*
5577  * Reset ps status display, so as no information related to recovery shows
5578  * up.
5579  */
5580  set_ps_display("");
5581 
5582  /*
5583  * When recovering from a backup (we are in recovery, and archive recovery
5584  * was requested), complain if we did not roll forward far enough to reach
5585  * the point where the database is consistent. For regular online
5586  * backup-from-primary, that means reaching the end-of-backup WAL record
5587  * (at which point we reset backupStartPoint to be Invalid), for
5588  * backup-from-replica (which can't inject records into the WAL stream),
5589  * that point is when we reach the minRecoveryPoint in pg_control (which
5590  * we purposefully copy last when backing up from a replica). For
5591  * pg_rewind (which creates a backup_label with a method of "pg_rewind")
5592  * or snapshot-style backups (which don't), backupEndRequired will be set
5593  * to false.
5594  *
5595  * Note: it is indeed okay to look at the local variable
5596  * LocalMinRecoveryPoint here, even though ControlFile->minRecoveryPoint
5597  * might be further ahead --- ControlFile->minRecoveryPoint cannot have
5598  * been advanced beyond the WAL we processed.
5599  */
5600  if (InRecovery &&
5601  (EndOfLog < LocalMinRecoveryPoint ||
5603  {
5604  /*
5605  * Ran off end of WAL before reaching end-of-backup WAL record, or
5606  * minRecoveryPoint. That's a bad sign, indicating that you tried to
5607  * recover from an online backup but never called pg_backup_stop(), or
5608  * you didn't archive all the WAL needed.
5609  */
5611  {
5613  ereport(FATAL,
5614  (errmsg("WAL ends before end of online backup"),
5615  errhint("All WAL generated while online backup was taken must be available at recovery.")));
5616  else
5617  ereport(FATAL,
5618  (errmsg("WAL ends before consistent recovery point")));
5619  }
5620  }
5621 
5622  /*
5623  * Reset unlogged relations to the contents of their INIT fork. This is
5624  * done AFTER recovery is complete so as to include any unlogged relations
5625  * created during recovery, but BEFORE recovery is marked as having
5626  * completed successfully. Otherwise we'd not retry if any of the post
5627  * end-of-recovery steps fail.
5628  */
5629  if (InRecovery)
5631 
5632  /*
5633  * Pre-scan prepared transactions to find out the range of XIDs present.
5634  * This information is not quite needed yet, but it is positioned here so
5635  * as potential problems are detected before any on-disk change is done.
5636  */
5637  oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
5638 
5639  /*
5640  * Allow ordinary WAL segment creation before possibly switching to a new
5641  * timeline, which creates a new segment, and after the last ReadRecord().
5642  */
5644 
5645  /*
5646  * Consider whether we need to assign a new timeline ID.
5647  *
5648  * If we did archive recovery, we always assign a new ID. This handles a
5649  * couple of issues. If we stopped short of the end of WAL during
5650  * recovery, then we are clearly generating a new timeline and must assign
5651  * it a unique new ID. Even if we ran to the end, modifying the current
5652  * last segment is problematic because it may result in trying to
5653  * overwrite an already-archived copy of that segment, and we encourage
5654  * DBAs to make their archive_commands reject that. We can dodge the
5655  * problem by making the new active segment have a new timeline ID.
5656  *
5657  * In a normal crash recovery, we can just extend the timeline we were in.
5658  */
5659  newTLI = endOfRecoveryInfo->lastRecTLI;
5661  {
5662  newTLI = findNewestTimeLine(recoveryTargetTLI) + 1;
5663  ereport(LOG,
5664  (errmsg("selected new timeline ID: %u", newTLI)));
5665 
5666  /*
5667  * Make a writable copy of the last WAL segment. (Note that we also
5668  * have a copy of the last block of the old WAL in
5669  * endOfRecovery->lastPage; we will use that below.)
5670  */
5671  XLogInitNewTimeline(EndOfLogTLI, EndOfLog, newTLI);
5672 
5673  /*
5674  * Remove the signal files out of the way, so that we don't
5675  * accidentally re-enter archive recovery mode in a subsequent crash.
5676  */
5677  if (endOfRecoveryInfo->standby_signal_file_found)
5679 
5680  if (endOfRecoveryInfo->recovery_signal_file_found)
5682 
5683  /*
5684  * Write the timeline history file, and have it archived. After this
5685  * point (or rather, as soon as the file is archived), the timeline
5686  * will appear as "taken" in the WAL archive and to any standby
5687  * servers. If we crash before actually switching to the new
5688  * timeline, standby servers will nevertheless think that we switched
5689  * to the new timeline, and will try to connect to the new timeline.
5690  * To minimize the window for that, try to do as little as possible
5691  * between here and writing the end-of-recovery record.
5692  */
5694  EndOfLog, endOfRecoveryInfo->recoveryStopReason);
5695 
5696  ereport(LOG,
5697  (errmsg("archive recovery complete")));
5698  }
5699 
5700  /* Save the selected TimeLineID in shared memory, too */
5701  XLogCtl->InsertTimeLineID = newTLI;
5702  XLogCtl->PrevTimeLineID = endOfRecoveryInfo->lastRecTLI;
5703 
5704  /*
5705  * Actually, if WAL ended in an incomplete record, skip the parts that
5706  * made it through and start writing after the portion that persisted.
5707  * (It's critical to first write an OVERWRITE_CONTRECORD message, which
5708  * we'll do as soon as we're open for writing new WAL.)
5709  */
5711  {
5712  /*
5713  * We should only have a missingContrecPtr if we're not switching to a
5714  * new timeline. When a timeline switch occurs, WAL is copied from the
5715  * old timeline to the new only up to the end of the last complete
5716  * record, so there can't be an incomplete WAL record that we need to
5717  * disregard.
5718  */
5719  Assert(newTLI == endOfRecoveryInfo->lastRecTLI);
5721  EndOfLog = missingContrecPtr;
5722  }
5723 
5724  /*
5725  * Prepare to write WAL starting at EndOfLog location, and init xlog
5726  * buffer cache using the block containing the last record from the
5727  * previous incarnation.
5728  */
5729  Insert = &XLogCtl->Insert;
5730  Insert->PrevBytePos = XLogRecPtrToBytePos(endOfRecoveryInfo->lastRec);
5731  Insert->CurrBytePos = XLogRecPtrToBytePos(EndOfLog);
5732 
5733  /*
5734  * Tricky point here: lastPage contains the *last* block that the LastRec
5735  * record spans, not the one it starts in. The last block is indeed the
5736  * one we want to use.
5737  */
5738  if (EndOfLog % XLOG_BLCKSZ != 0)
5739  {
5740  char *page;
5741  int len;
5742  int firstIdx;
5743 
5744  firstIdx = XLogRecPtrToBufIdx(EndOfLog);
5745  len = EndOfLog - endOfRecoveryInfo->lastPageBeginPtr;
5746  Assert(len < XLOG_BLCKSZ);
5747 
5748  /* Copy the valid part of the last block, and zero the rest */
5749  page = &XLogCtl->pages[firstIdx * XLOG_BLCKSZ];
5750  memcpy(page, endOfRecoveryInfo->lastPage, len);
5751  memset(page + len, 0, XLOG_BLCKSZ - len);
5752 
5753  XLogCtl->xlblocks[firstIdx] = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5754  XLogCtl->InitializedUpTo = endOfRecoveryInfo->lastPageBeginPtr + XLOG_BLCKSZ;
5755  }
5756  else
5757  {
5758  /*
5759  * There is no partial block to copy. Just set InitializedUpTo, and
5760  * let the first attempt to insert a log record to initialize the next
5761  * buffer.
5762  */
5763  XLogCtl->InitializedUpTo = EndOfLog;
5764  }
5765 
5766  LogwrtResult.Write = LogwrtResult.Flush = EndOfLog;
5767 
5769 
5770  XLogCtl->LogwrtRqst.Write = EndOfLog;
5771  XLogCtl->LogwrtRqst.Flush = EndOfLog;
5772 
5773  /*
5774  * Preallocate additional log files, if wanted.
5775  */
5776  PreallocXlogFiles(EndOfLog, newTLI);
5777 
5778  /*
5779  * Okay, we're officially UP.
5780  */
5781  InRecovery = false;
5782 
5783  /* start the archive_timeout timer and LSN running */
5784  XLogCtl->lastSegSwitchTime = (pg_time_t) time(NULL);
5785  XLogCtl->lastSegSwitchLSN = EndOfLog;
5786 
5787  /* also initialize latestCompletedXid, to nextXid - 1 */
5788  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
5791  LWLockRelease(ProcArrayLock);
5792 
5793  /*
5794  * Start up subtrans, if not already done for hot standby. (commit
5795  * timestamps are started below, if necessary.)
5796  */
5798  StartupSUBTRANS(oldestActiveXID);
5799 
5800  /*
5801  * Perform end of recovery actions for any SLRUs that need it.
5802  */
5803  TrimCLOG();
5804  TrimMultiXact();
5805 
5806  /*
5807  * Reload shared-memory state for prepared transactions. This needs to
5808  * happen before renaming the last partial segment of the old timeline as
5809  * it may be possible that we have to recovery some transactions from it.
5810  */
5812 
5813  /* Shut down xlogreader */
5815 
5816  /* Enable WAL writes for this backend only. */
5818 
5819  /* If necessary, write overwrite-contrecord before doing anything else */
5821  {
5824  }
5825 
5826  /*
5827  * Update full_page_writes in shared memory and write an XLOG_FPW_CHANGE
5828  * record before resource manager writes cleanup WAL records or checkpoint
5829  * record is written.
5830  */
5831  Insert->fullPageWrites = lastFullPageWrites;
5833 
5834  /*
5835  * Emit checkpoint or end-of-recovery record in XLOG, if required.
5836  */
5837  if (performedWalRecovery)
5838  promoted = PerformRecoveryXLogAction();
5839 
5840  /*
5841  * If any of the critical GUCs have changed, log them before we allow
5842  * backends to write WAL.
5843  */
5845 
5846  /* If this is archive recovery, perform post-recovery cleanup actions. */
5848  CleanupAfterArchiveRecovery(EndOfLogTLI, EndOfLog, newTLI);
5849 
5850  /*
5851  * Local WAL inserts enabled, so it's time to finish initialization of
5852  * commit timestamp.
5853  */
5855 
5856  /*
5857  * All done with end-of-recovery actions.
5858  *
5859  * Now allow backends to write WAL and update the control file status in
5860  * consequence. SharedRecoveryState, that controls if backends can write
5861  * WAL, is updated while holding ControlFileLock to prevent other backends
5862  * to look at an inconsistent state of the control file in shared memory.
5863  * There is still a small window during which backends can write WAL and
5864  * the control file is still referring to a system not in DB_IN_PRODUCTION
5865  * state while looking at the on-disk control file.
5866  *
5867  * Also, we use info_lck to update SharedRecoveryState to ensure that
5868  * there are no race conditions concerning visibility of other recent
5869  * updates to shared memory.
5870  */
5871  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5873 
5877 
5879  LWLockRelease(ControlFileLock);
5880 
5881  /*
5882  * Shutdown the recovery environment. This must occur after
5883  * RecoverPreparedTransactions() (see notes in lock_twophase_recover())
5884  * and after switching SharedRecoveryState to RECOVERY_STATE_DONE so as
5885  * any session building a snapshot will not rely on KnownAssignedXids as
5886  * RecoveryInProgress() would return false at this stage. This is
5887  * particularly critical for prepared 2PC transactions, that would still
5888  * need to be included in snapshots once recovery has ended.
5889  */
5892 
5893  /*
5894  * If there were cascading standby servers connected to us, nudge any wal
5895  * sender processes to notice that we've been promoted.
5896  */
5897  WalSndWakeup(true, true);
5898 
5899  /*
5900  * If this was a promotion, request an (online) checkpoint now. This isn't
5901  * required for consistency, but the last restartpoint might be far back,
5902  * and in case of a crash, recovering from it might take a longer than is
5903  * appropriate now that we're not in standby mode anymore.
5904  */
5905  if (promoted)
5907 }
TimeLineID findNewestTimeLine(TimeLineID startTLI)
Definition: timeline.c:264
void restoreTimeLineHistoryFiles(TimeLineID begin, TimeLineID end)
Definition: timeline.c:50
void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, XLogRecPtr switchpoint, char *reason)
Definition: timeline.c:304
void startup_progress_timeout_handler(void)
Definition: startup.c:326
uint32 TransactionId
Definition: c.h:641
void StartupCLOG(void)
Definition: clog.c:764
void TrimCLOG(void)
Definition: clog.c:783
void StartupCommitTs(void)
Definition: commit_ts.c:599
void CompleteCommitTsInitialization(void)
Definition: commit_ts.c:609
#define FATAL
Definition: elog.h:41
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition: fd.c:759
int durable_unlink(const char *fname, int elevel)
Definition: fd.c:849
void SyncDataDirectory(void)
Definition: fd.c:3514
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:417
void TrimMultiXact(void)
Definition: multixact.c:2033
void StartupMultiXact(void)
Definition: multixact.c:2010
void StartupReplicationOrigin(void)
Definition: origin.c:699
@ DB_IN_PRODUCTION
Definition: pg_control.h:96
@ DB_IN_CRASH_RECOVERY
Definition: pg_control.h:94
const void size_t len
void pgstat_restore_stats(void)
Definition: pgstat.c:410
void pgstat_discard_stats(void)
Definition: pgstat.c:422
void ProcArrayApplyRecoveryInfo(RunningTransactions running)
Definition: procarray.c:1053
void ProcArrayInitRecovery(TransactionId initializedUptoXID)
Definition: procarray.c:1022
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void ResetUnloggedRelations(int op)
Definition: reinit.c:47
#define UNLOGGED_RELATION_INIT
Definition: reinit.h:28
#define UNLOGGED_RELATION_CLEANUP
Definition: reinit.h:27
void RelationCacheInitFileRemove(void)
Definition: relcache.c:6780
void StartupReorderBuffer(void)
void StartupReplicationSlots(void)
Definition: slot.c:1679
void DeleteAllExportedSnapshotFiles(void)
Definition: snapmgr.c:1573
void InitRecoveryTransactionEnvironment(void)
Definition: standby.c:96
void ShutdownRecoveryTransactionEnvironment(void)
Definition: standby.c:161
bool track_commit_timestamp
Definition: pg_control.h:184
XLogRecPtr lastPageBeginPtr
Definition: xlogrecovery.h:111
XLogRecPtr abortedRecPtr
Definition: xlogrecovery.h:120
XLogRecPtr missingContrecPtr
Definition: xlogrecovery.h:121
TimeLineID endOfLogTLI
Definition: xlogrecovery.h:109
TransactionId oldestRunningXid
Definition: standby.h:84
TransactionId nextXid
Definition: standby.h:83
TransactionId latestCompletedXid
Definition: standby.h:85
TransactionId * xids
Definition: standby.h:87
FullTransactionId latestCompletedXid
Definition: transam.h:238
XLogRecPtr InitializedUpTo
Definition: xlog.c:496
char * pages
Definition: xlog.c:503
pg_time_t lastSegSwitchTime
Definition: xlog.c:477
XLogRecPtr lastSegSwitchLSN
Definition: xlog.c:478
XLogRecPtr * xlblocks
Definition: xlog.c:504
XLogRecPtr Flush
Definition: xlog.c:331
void StartupSUBTRANS(TransactionId oldestActiveXID)
Definition: subtrans.c:259
TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler)
Definition: timeout.c:509
@ STARTUP_PROGRESS_TIMEOUT
Definition: timeout.h:37
#define TransactionIdRetreat(dest)
Definition: transam.h:141
static void FullTransactionIdRetreat(FullTransactionId *dest)
Definition: transam.h:103
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
void RecoverPreparedTransactions(void)
Definition: twophase.c:2100
void restoreTwoPhaseData(void)
Definition: twophase.c:1914
TransactionId PrescanPreparedTransactions(TransactionId **xids_p, int *nxids_p)
Definition: twophase.c:1978
void StandbyRecoverPreparedTransactions(void)
Definition: twophase.c:2059
void WalSndWakeup(bool physical, bool logical)
Definition: walsender.c:3333
void UpdateFullPageWrites(void)
Definition: xlog.c:7801
static char * str_time(pg_time_t tnow)
Definition: xlog.c:4925
static void ValidateXLOGDirectoryStructure(void)
Definition: xlog.c:3885
static XLogRecPtr CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr, TimeLineID newTLI)
Definition: xlog.c:7095
static void XLogReportParameters(void)
Definition: xlog.c:7738
static bool PerformRecoveryXLogAction(void)
Definition: xlog.c:5989
static void CleanupAfterArchiveRecovery(TimeLineID EndOfLogTLI, XLogRecPtr EndOfLog, TimeLineID newTLI)
Definition: xlog.c:5015
static bool lastFullPageWrites
Definition: xlog.c:220
static uint64 XLogRecPtrToBytePos(XLogRecPtr ptr)
Definition: xlog.c:1800
static void XLogInitNewTimeline(TimeLineID endTLI, XLogRecPtr endOfLog, TimeLineID newTLI)
Definition: xlog.c:4940
static void CheckRequiredParameterValues(void)
Definition: xlog.c:5104
#define XLogRecPtrToBufIdx(recptr)
Definition: xlog.c:597
static void RemoveTempXlogFiles(void)
Definition: xlog.c:3618
#define TABLESPACE_MAP_OLD
Definition: xlog.h:298
#define TABLESPACE_MAP
Definition: xlog.h:297
#define STANDBY_SIGNAL_FILE
Definition: xlog.h:293
#define BACKUP_LABEL_OLD
Definition: xlog.h:295
#define BACKUP_LABEL_FILE
Definition: xlog.h:294
#define RECOVERY_SIGNAL_FILE
Definition: xlog.h:292
#define XRecOffIsValid(xlrp)
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
void ShutdownWalRecovery(void)
bool ArchiveRecoveryRequested
Definition: xlogrecovery.c:137
bool InArchiveRecovery
Definition: xlogrecovery.c:138
void PerformWalRecovery(void)
EndOfWalRecoveryInfo * FinishWalRecovery(void)
static XLogRecPtr missingContrecPtr
Definition: xlogrecovery.c:373
static XLogRecPtr abortedRecPtr
Definition: xlogrecovery.c:372
void InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr, bool *haveBackupLabel_ptr, bool *haveTblspcMap_ptr)
Definition: xlogrecovery.c:512
TimeLineID recoveryTargetTLI
Definition: xlogrecovery.c:122
HotStandbyState standbyState
Definition: xlogutils.c:56
bool InRecovery
Definition: xlogutils.c:53
@ STANDBY_DISABLED
Definition: xlogutils.h:49

References abortedRecPtr, EndOfWalRecoveryInfo::abortedRecPtr, AdvanceOldestClogXid(), ArchiveRecoveryRequested, Assert(), AuxProcessResourceOwner, BACKUP_LABEL_FILE, BACKUP_LABEL_OLD, ControlFileData::backupEndRequired, ControlFileData::backupStartPoint, ControlFileData::checkPoint, CHECKPOINT_FORCE, ControlFileData::checkPointCopy, CheckRequiredParameterValues(), XLogCtlData::ckptFullXid, CleanupAfterArchiveRecovery(), CompleteCommitTsInitialization(), ControlFile, CreateOverwriteContrecordRecord(), CurrentResourceOwner, DB_IN_ARCHIVE_RECOVERY, DB_IN_CRASH_RECOVERY, DB_IN_PRODUCTION, DB_SHUTDOWNED, DB_SHUTDOWNED_IN_RECOVERY, DB_SHUTDOWNING, DEBUG1, DeleteAllExportedSnapshotFiles(), doPageWrites, durable_rename(), durable_unlink(), EnableHotStandby, EndOfWalRecoveryInfo::endOfLog, EndOfWalRecoveryInfo::endOfLogTLI, ereport, errhint(), errmsg(), errmsg_internal(), FATAL, findNewestTimeLine(), FinishWalRecovery(), FirstNormalUnloggedLSN, XLogwrtRqst::Flush, XLogwrtResult::Flush, CheckPoint::fullPageWrites, FullTransactionIdRetreat(), InArchiveRecovery, XLogCtlData::info_lck, XLogCtlData::InitializedUpTo, InitRecoveryTransactionEnvironment(), InitWalRecovery(), InRecovery, XLogCtlData::Insert, Insert(), XLogCtlData::InsertTimeLineID, InvalidXLogRecPtr, IsBootstrapProcessingMode, IsPostmasterEnvironment, lastFullPageWrites, EndOfWalRecoveryInfo::lastPage, EndOfWalRecoveryInfo::lastPageBeginPtr, EndOfWalRecoveryInfo::lastRec, EndOfWalRecoveryInfo::lastRecTLI, XLogCtlData::lastSegSwitchLSN, XLogCtlData::lastSegSwitchTime, TransamVariablesData::latestCompletedXid, RunningTransactionsData::latestCompletedXid, len, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LocalSetXLogInsertAllowed(), LOG, XLogCtlData::LogwrtResult, LogwrtResult, XLogCtlData::LogwrtRqst, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, missingContrecPtr, EndOfWalRecoveryInfo::missingContrecPtr, MultiXactSetNextMXact(), CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, TransamVariablesData::nextOid, CheckPoint::nextOid, TransamVariablesData::nextXid, CheckPoint::nextXid, RunningTransactionsData::nextXid, NOTICE, TransamVariablesData::oidCount, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, RunningTransactionsData::oldestRunningXid, CheckPoint::oldestXid, CheckPoint::oldestXidDB, XLogCtlData::pages, PerformRecoveryXLogAction(), PerformWalRecovery(), pg_usleep(), pgstat_discard_stats(), pgstat_restore_stats(), PreallocXlogFiles(), PrescanPreparedTransactions(), XLogCtlData::PrevTimeLineID, ProcArrayApplyRecoveryInfo(), ProcArrayInitRecovery(), RecoverPreparedTransactions(), RECOVERY_SIGNAL_FILE, EndOfWalRecoveryInfo::recovery_signal_file_found, RECOVERY_STATE_ARCHIVE, RECOVERY_STATE_CRASH, RECOVERY_STATE_DONE, EndOfWalRecoveryInfo::recoveryStopReason, recoveryTargetTLI, CheckPoint::redo, RedoRecPtr, XLogCtlInsert::RedoRecPtr, XLogCtlData::RedoRecPtr, RegisterTimeout(), RelationCacheInitFileRemove(), RemoveTempXlogFiles(), RequestCheckpoint(), ResetUnloggedRelations(), restoreTimeLineHistoryFiles(), restoreTwoPhaseData(), set_ps_display(), SetCommitTsLimit(), SetInstallXLogFileSegmentActive(), SetMultiXactIdLimit(), SetTransactionIdLimit(), XLogCtlData::SharedRecoveryState, ShutdownRecoveryTransactionEnvironment(), ShutdownWalRecovery(), SpinLockAcquire, SpinLockRelease, STANDBY_DISABLED, STANDBY_SIGNAL_FILE, EndOfWalRecoveryInfo::standby_signal_file_found, StandbyRecoverPreparedTransactions(), standbyState, STARTUP_PROGRESS_TIMEOUT, startup_progress_timeout_handler(), StartupCLOG(), StartupCommitTs(), StartupMultiXact(), StartupReorderBuffer(), StartupReplicationOrigin(), StartupReplicationSlots(), StartupSUBTRANS(), ControlFileData::state, str_time(), RunningTransactionsData::subxcnt, RunningTransactionsData::subxid_overflow, SyncDataDirectory(), TABLESPACE_MAP, TABLESPACE_MAP_OLD, CheckPoint::ThisTimeLineID, CheckPoint::time, ControlFileData::time, ControlFileData::track_commit_timestamp, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdRetreat, TransamVariables, TrimCLOG(), TrimMultiXact(), UNLOGGED_RELATION_CLEANUP, UNLOGGED_RELATION_INIT, XLogCtlData::unloggedLSN, ControlFileData::unloggedLSN, UpdateControlFile(), UpdateFullPageWrites(), ValidateXLOGDirectoryStructure(), WalSndWakeup(), XLogwrtRqst::Write, XLogwrtResult::Write, writeTimeLineHistory(), RunningTransactionsData::xcnt, XidFromFullTransactionId, RunningTransactionsData::xids, XLogCtlData::xlblocks, XLogCtl, XLogInitNewTimeline(), XLogRecPtrIsInvalid, XLogRecPtrToBufIdx, XLogRecPtrToBytePos(), XLogReportParameters(), and XRecOffIsValid.

Referenced by InitPostgres(), and StartupProcessMain().

◆ SwitchIntoArchiveRecovery()

void SwitchIntoArchiveRecovery ( XLogRecPtr  EndRecPtr,
TimeLineID  replayTLI 
)

Definition at line 5914 of file xlog.c.

5915 {
5916  /* initialize minRecoveryPoint to this record */
5917  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
5919  if (ControlFile->minRecoveryPoint < EndRecPtr)
5920  {
5921  ControlFile->minRecoveryPoint = EndRecPtr;
5922  ControlFile->minRecoveryPointTLI = replayTLI;
5923  }
5924  /* update local copy */
5927 
5928  /*
5929  * The startup process can update its local copy of minRecoveryPoint from
5930  * this point.
5931  */
5932  updateMinRecoveryPoint = true;
5933 
5935 
5936  /*
5937  * We update SharedRecoveryState while holding the lock on ControlFileLock
5938  * so both states are consistent in shared memory.
5939  */
5943 
5944  LWLockRelease(ControlFileLock);
5945 }
static bool updateMinRecoveryPoint
Definition: xlog.c:641

References ControlFile, DB_IN_ARCHIVE_RECOVERY, XLogCtlData::info_lck, LocalMinRecoveryPoint, LocalMinRecoveryPointTLI, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ControlFileData::minRecoveryPoint, ControlFileData::minRecoveryPointTLI, RECOVERY_STATE_ARCHIVE, XLogCtlData::SharedRecoveryState, SpinLockAcquire, SpinLockRelease, ControlFileData::state, UpdateControlFile(), updateMinRecoveryPoint, and XLogCtl.

Referenced by ReadRecord().

◆ UpdateFullPageWrites()

void UpdateFullPageWrites ( void  )

Definition at line 7801 of file xlog.c.

7802 {
7804  bool recoveryInProgress;
7805 
7806  /*
7807  * Do nothing if full_page_writes has not been changed.
7808  *
7809  * It's safe to check the shared full_page_writes without the lock,
7810  * because we assume that there is no concurrently running process which
7811  * can update it.
7812  */
7813  if (fullPageWrites == Insert->fullPageWrites)
7814  return;
7815 
7816  /*
7817  * Perform this outside critical section so that the WAL insert
7818  * initialization done by RecoveryInProgress() doesn't trigger an
7819  * assertion failure.
7820  */
7821  recoveryInProgress = RecoveryInProgress();
7822 
7824 
7825  /*
7826  * It's always safe to take full page images, even when not strictly
7827  * required, but not the other round. So if we're setting full_page_writes
7828  * to true, first set it true and then write the WAL record. If we're
7829  * setting it to false, first write the WAL record and then set the global
7830  * flag.
7831  */
7832  if (fullPageWrites)
7833  {
7835  Insert->fullPageWrites = true;
7837  }
7838 
7839  /*
7840  * Write an XLOG_FPW_CHANGE record. This allows us to keep track of
7841  * full_page_writes during archive recovery, if required.
7842  */
7843  if (XLogStandbyInfoActive() && !recoveryInProgress)
7844  {
7845  XLogBeginInsert();
7846  XLogRegisterData((char *) (&fullPageWrites), sizeof(bool));
7847 
7848  XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE);
7849  }
7850 
7851  if (!fullPageWrites)
7852  {
7854  Insert->fullPageWrites = false;
7856  }
7857  END_CRIT_SECTION();
7858 }
#define XLOG_FPW_CHANGE
Definition: pg_control.h:75

References END_CRIT_SECTION, fullPageWrites, XLogCtlData::Insert, Insert(), RecoveryInProgress(), START_CRIT_SECTION, WALInsertLockAcquireExclusive(), WALInsertLockRelease(), XLOG_FPW_CHANGE, XLogBeginInsert(), XLogCtl, XLogInsert(), XLogRegisterData(), and XLogStandbyInfoActive.

Referenced by StartupXLOG(), and UpdateSharedMemoryConfig().

◆ xlog_desc()

void xlog_desc ( StringInfo  buf,
struct XLogReaderState record 
)

Definition at line 37 of file xlogdesc.c.

38 {
39  char *rec = XLogRecGetData(record);
40  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
41 
42  if (info == XLOG_CHECKPOINT_SHUTDOWN ||
43  info == XLOG_CHECKPOINT_ONLINE)
44  {
45  CheckPoint *checkpoint = (CheckPoint *) rec;
46 
47  appendStringInfo(buf, "redo %X/%X; "
48  "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
49  "oldest xid %u in DB %u; oldest multi %u in DB %u; "
50  "oldest/newest commit timestamp xid: %u/%u; "
51  "oldest running xid %u; %s",
52  LSN_FORMAT_ARGS(checkpoint->redo),
53  checkpoint->ThisTimeLineID,
54  checkpoint->PrevTimeLineID,
55  checkpoint->fullPageWrites ? "true" : "false",
57  XidFromFullTransactionId(checkpoint->nextXid),
58  checkpoint->nextOid,
59  checkpoint->nextMulti,
60  checkpoint->nextMultiOffset,
61  checkpoint->oldestXid,
62  checkpoint->oldestXidDB,
63  checkpoint->oldestMulti,
64  checkpoint->oldestMultiDB,
65  checkpoint->oldestCommitTsXid,
66  checkpoint->newestCommitTsXid,
67  checkpoint->oldestActiveXid,
68  (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
69  }
70  else if (info == XLOG_NEXTOID)
71  {
72  Oid nextOid;
73 
74  memcpy(&nextOid, rec, sizeof(Oid));
75  appendStringInfo(buf, "%u", nextOid);
76  }
77  else if (info == XLOG_RESTORE_POINT)
78  {
79  xl_restore_point *xlrec = (xl_restore_point *) rec;
80 
82  }
83  else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
84  {
85  /* no further information to print */
86  }
87  else if (info == XLOG_BACKUP_END)
88  {
89  XLogRecPtr startpoint;
90 
91  memcpy(&startpoint, rec, sizeof(XLogRecPtr));
92  appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
93  }
94  else if (info == XLOG_PARAMETER_CHANGE)
95  {
96  xl_parameter_change xlrec;
97  const char *wal_level_str;
98  const struct config_enum_entry *entry;
99 
100  memcpy(&xlrec, rec, sizeof(xl_parameter_change));
101 
102  /* Find a string representation for wal_level */
103  wal_level_str = "?";
104  for (entry = wal_level_options; entry->name; entry++)
105  {
106  if (entry->val == xlrec.wal_level)
107  {
108  wal_level_str = entry->name;
109  break;
110  }
111  }
112 
113  appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
114  "max_wal_senders=%d max_prepared_xacts=%d "
115  "max_locks_per_xact=%d wal_level=%s "
116  "wal_log_hints=%s track_commit_timestamp=%s",
117  xlrec.MaxConnections,
118  xlrec.max_worker_processes,
119  xlrec.max_wal_senders,
120  xlrec.max_prepared_xacts,
121  xlrec.max_locks_per_xact,
123  xlrec.wal_log_hints ? "on" : "off",
124  xlrec.track_commit_timestamp ? "on" : "off");
125  }
126  else if (info == XLOG_FPW_CHANGE)
127  {
128  bool fpw;
129 
130  memcpy(&fpw, rec, sizeof(bool));
131  appendStringInfoString(buf, fpw ? "true" : "false");
132  }
133  else if (info == XLOG_END_OF_RECOVERY)
134  {
135  xl_end_of_recovery xlrec;
136 
137  memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
138  appendStringInfo(buf, "tli %u; prev tli %u; time %s",
139  xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
141  }
142  else if (info == XLOG_OVERWRITE_CONTRECORD)
143  {
145 
146  memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
147  appendStringInfo(buf, "lsn %X/%X; time %s",
150  }
151  else if (info == XLOG_CHECKPOINT_REDO)
152  {
153  /* No details to write out */
154  }
155 }
static const char * wal_level_str(WalLevel wal_level)
unsigned char uint8
Definition: c.h:493
#define XLOG_RESTORE_POINT
Definition: pg_control.h:74
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:80
#define XLOG_FPI
Definition: pg_control.h:78
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:77
#define XLOG_NEXTOID
Definition: pg_control.h:70
#define XLOG_PARAMETER_CHANGE
Definition: pg_control.h:73
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:76
static char * buf
Definition: pg_test_fsync.c:73
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
Definition: guc.h:170
const char * name
Definition: guc.h:171
int val
Definition: guc.h:172
TimeLineID PrevTimeLineID
TimestampTz end_time
TimeLineID ThisTimeLineID
char rp_name[MAXFNAMELEN]
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
const struct config_enum_entry wal_level_options[]
Definition: xlogdesc.c:27
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References appendStringInfo(), appendStringInfoString(), buf, xl_end_of_recovery::end_time, EpochFromFullTransactionId, CheckPoint::fullPageWrites, LSN_FORMAT_ARGS, xl_parameter_change::max_locks_per_xact, xl_parameter_change::max_prepared_xacts, xl_parameter_change::max_wal_senders, xl_parameter_change::max_worker_processes, xl_parameter_change::MaxConnections, config_enum_entry::name, CheckPoint::newestCommitTsXid, CheckPoint::nextMulti, CheckPoint::nextMultiOffset, CheckPoint::nextOid, CheckPoint::nextXid, CheckPoint::oldestActiveXid, CheckPoint::oldestCommitTsXid, CheckPoint::oldestMulti, CheckPoint::oldestMultiDB, CheckPoint::oldestXid, CheckPoint::oldestXidDB, xl_overwrite_contrecord::overwrite_time, xl_overwrite_contrecord::overwritten_lsn, xl_end_of_recovery::PrevTimeLineID, CheckPoint::PrevTimeLineID, CheckPoint::redo, xl_restore_point::rp_name, xl_end_of_recovery::ThisTimeLineID, CheckPoint::ThisTimeLineID, timestamptz_to_str(), xl_parameter_change::track_commit_timestamp, config_enum_entry::val, xl_parameter_change::wal_level, wal_level_options, wal_level_str(), xl_parameter_change::wal_log_hints, XidFromFullTransactionId, XLOG_BACKUP_END, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_REDO, XLOG_CHECKPOINT_SHUTDOWN, XLOG_END_OF_RECOVERY, XLOG_FPI, XLOG_FPI_FOR_HINT, XLOG_FPW_CHANGE, XLOG_NEXTOID, XLOG_OVERWRITE_CONTRECORD, XLOG_PARAMETER_CHANGE, XLOG_RESTORE_POINT, XLogRecGetData, XLogRecGetInfo, and XLR_INFO_MASK.

◆ xlog_identify()

const char* xlog_identify ( uint8  info)

Definition at line 158 of file xlogdesc.c.

159 {
160  const char *id = NULL;
161 
162  switch (info & ~XLR_INFO_MASK)
163  {
165  id = "CHECKPOINT_SHUTDOWN";
166  break;
168  id = "CHECKPOINT_ONLINE";
169  break;
170  case XLOG_NOOP:
171  id = "NOOP";
172  break;
173  case XLOG_NEXTOID:
174  id = "NEXTOID";
175  break;
176  case XLOG_SWITCH:
177  id = "SWITCH";
178  break;
179  case XLOG_BACKUP_END:
180  id = "BACKUP_END";
181  break;
183  id = "PARAMETER_CHANGE";
184  break;
185  case XLOG_RESTORE_POINT:
186  id = "RESTORE_POINT";
187  break;
188  case XLOG_FPW_CHANGE:
189  id = "FPW_CHANGE";
190  break;
192  id = "END_OF_RECOVERY";
193  break;
195  id = "OVERWRITE_CONTRECORD";
196  break;
197  case XLOG_FPI:
198  id = "FPI";
199  break;
200  case XLOG_FPI_FOR_HINT:
201  id = "FPI_FOR_HINT";
202  break;
204  id = "CHECKPOINT_REDO";
205  break;
206  }
207 
208  return id;
209 }
#define XLOG_NOOP
Definition: pg_control.h:69
#define XLOG_SWITCH
Definition: pg_control.h:71

References XLOG_BACKUP_END, XLOG_CHECKPOINT_ONLINE, XLOG_CHECKPOINT_REDO, XLOG_CHECKPOINT_SHUTDOWN, XLOG_END_OF_RECOVERY, XLOG_FPI, XLOG_FPI_FOR_HINT, XLOG_FPW_CHANGE, XLOG_NEXTOID, XLOG_NOOP, XLOG_OVERWRITE_CONTRECORD, XLOG_PARAMETER_CHANGE, XLOG_RESTORE_POINT, XLOG_SWITCH, and XLR_INFO_MASK.

◆ xlog_redo()

void xlog_redo ( struct XLogReaderState record)

Definition at line 7870 of file xlog.c.

7871 {
7872  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
7873  XLogRecPtr lsn = record->EndRecPtr;
7874 
7875  /*
7876  * In XLOG rmgr, backup blocks are only used by XLOG_FPI and
7877  * XLOG_FPI_FOR_HINT records.
7878  */
7879  Assert(info == XLOG_FPI || info == XLOG_FPI_FOR_HINT ||
7880  !XLogRecHasAnyBlockRefs(record));
7881 
7882  if (info == XLOG_NEXTOID)
7883  {
7884  Oid nextOid;
7885 
7886  /*
7887  * We used to try to take the maximum of TransamVariables->nextOid and
7888  * the recorded nextOid, but that fails if the OID counter wraps
7889  * around. Since no OID allocation should be happening during replay
7890  * anyway, better to just believe the record exactly. We still take
7891  * OidGenLock while setting the variable, just in case.
7892  */
7893  memcpy(&nextOid, XLogRecGetData(record), sizeof(Oid));
7894  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7895  TransamVariables->nextOid = nextOid;
7897  LWLockRelease(OidGenLock);
7898  }
7899  else if (info == XLOG_CHECKPOINT_SHUTDOWN)
7900  {
7901  CheckPoint checkPoint;
7902  TimeLineID replayTLI;
7903 
7904  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
7905  /* In a SHUTDOWN checkpoint, believe the counters exactly */
7906  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
7907  TransamVariables->nextXid = checkPoint.nextXid;
7908  LWLockRelease(XidGenLock);
7909  LWLockAcquire(OidGenLock, LW_EXCLUSIVE);
7910  TransamVariables->nextOid = checkPoint.nextOid;
7912  LWLockRelease(OidGenLock);
7913  MultiXactSetNextMXact(checkPoint.nextMulti,
7914  checkPoint.nextMultiOffset);
7915 
7917  checkPoint.oldestMultiDB);
7918 
7919  /*
7920  * No need to set oldestClogXid here as well; it'll be set when we
7921  * redo an xl_clog_truncate if it changed since initialization.
7922  */
7923  SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
7924 
7925  /*
7926  * If we see a shutdown checkpoint while waiting for an end-of-backup
7927  * record, the backup was canceled and the end-of-backup record will
7928  * never arrive.
7929  */
7933  ereport(PANIC,
7934  (errmsg("online backup was canceled, recovery cannot continue")));
7935 
7936  /*
7937  * If we see a shutdown checkpoint, we know that nothing was running
7938  * on the primary at this point. So fake-up an empty running-xacts
7939  * record and use that here and now. Recover additional standby state
7940  * for prepared transactions.
7941  */
7943  {
7944  TransactionId *xids;
7945  int nxids;
7946  TransactionId oldestActiveXID;
7947  TransactionId latestCompletedXid;
7948  RunningTransactionsData running;
7949 
7950  oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
7951 
7952  /*
7953  * Construct a RunningTransactions snapshot representing a shut
7954  * down server, with only prepared transactions still alive. We're
7955  * never overflowed at this point because all subxids are listed
7956  * with their parent prepared transactions.
7957  */
7958  running.xcnt = nxids;
7959  running.subxcnt = 0;
7960  running.subxid_overflow = false;
7961  running.nextXid = XidFromFullTransactionId(checkPoint.nextXid);
7962  running.oldestRunningXid = oldestActiveXID;
7963  latestCompletedXid = XidFromFullTransactionId(checkPoint.nextXid);
7964  TransactionIdRetreat(latestCompletedXid);
7965  Assert(TransactionIdIsNormal(latestCompletedXid));
7966  running.latestCompletedXid = latestCompletedXid;
7967  running.xids = xids;
7968 
7969  ProcArrayApplyRecoveryInfo(&running);
7970 
7972  }
7973 
7974  /* ControlFile->checkPointCopy always tracks the latest ckpt XID */
7975  LWLockAcquire(ControlFileLock, LW_EXCLUSIVE);
7976  ControlFile->checkPointCopy.nextXid = checkPoint.nextXid;
7977  LWLockRelease(ControlFileLock);
7978 
7979  /* Update shared-memory copy of checkpoint XID/epoch */
7981  XLogCtl->ckptFullXid = checkPoint.nextXid;
7983 
7984  /*
7985  * We should've already switched to the new TLI before replaying this
7986  * record.
7987  */
7988  (void) GetCurrentReplayRecPtr(&replayTLI);
7989  if (checkPoint.ThisTimeLineID != replayTLI)
7990  ereport(PANIC,
7991  (errmsg("unexpected timeline ID %u (should be %u) in shutdown checkpoint record",
7992  checkPoint.ThisTimeLineID, replayTLI)));
7993 
7994  RecoveryRestartPoint(&checkPoint, record);
7995  }
7996  else if (info == XLOG_CHECKPOINT_ONLINE)
7997  {
7998  CheckPoint checkPoint;
7999  TimeLineID replayTLI;
8000 
8001  memcpy(&checkPoint, XLogRecGetData(record), sizeof(CheckPoint));
8002  /* In an ONLINE checkpoint, treat the XID counter as a minimum */
8003  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
8005  checkPoint.nextXid))
8006  TransamVariables->nextXid = checkPoint.nextXid;
8007  LWLockRelease(XidGenLock);
8008 
8009  /*
8010  * We ignore the nextOid counter in an ONLINE checkpoint, preferring
8011  * to track OID assignment through XLOG_NEXTOID records. The nextOid
8012  * counter is from the start of the checkpoint and might well be stale
8013  * compared to later XLOG_NEXTOID records. We could try to take the
8014  * maximum of the nextOid counter and our latest value, but since
8015  * there's no particular guarantee about the speed with which the OID
8016  * counter wraps around, that's a risky thing to do. In any case,
8017  * users of the nextOid counter are required to avoid assignment of
8018  * duplicates, so that a somewhat out-of-date value should be safe.
8019  */
8020 
8021  /* Handle multixact */
8023  checkPoint.nextMultiOffset);
8024 
8025  /*
8026  * NB: This may perform multixact truncation when replaying WAL
8027  * generated by an older primary.
8028  */
8030  checkPoint.oldestMultiDB);
8032  checkPoint.oldestXid))
8033  SetTransactionIdLimit(checkPoint.oldestXid,
8034  checkPoint.oldestXidDB);
8035  /* ControlFile->c