diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index a73fd4d044..6f45f2e177 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -819,15 +819,8 @@ test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/0
sequence, and that the success of a step is verified before
proceeding to the next step.
-
- Low level base backups can be made in a non-exclusive or an exclusive
- way. The non-exclusive method is recommended and the exclusive one is
- deprecated and will eventually be removed.
-
-
- Making a non-exclusive low level backup
- A non-exclusive low level backup is one that allows other
+ A low level backup allows other
concurrent backups to be running (both those started using
the same backup API and those started using
).
@@ -845,7 +838,7 @@ test ! -f /mnt/server/archivedir/00000001000000A900000065 && cp pg_wal/0
rights to run pg_start_backup (superuser, or a user who has been granted
EXECUTE on the function) and issue the command:
-SELECT pg_start_backup('label', false, false);
+SELECT pg_start_backup('label', false);
where label is any string you want to use to uniquely
identify this backup operation. The connection
@@ -866,10 +859,6 @@ SELECT pg_start_backup('label', false, false);
issue an immediate checkpoint using as much I/O as available.
-
- The third parameter being false tells
- pg_start_backup to initiate a non-exclusive base backup.
-
@@ -887,7 +876,7 @@ SELECT pg_start_backup('label', false, false);
In the same connection as before, issue the command:
-SELECT * FROM pg_stop_backup(false, true);
+SELECT * FROM pg_stop_backup(true);
This terminates backup mode. On a primary, it also performs an automatic
switch to the next WAL segment. On a standby, it is not possible to
@@ -945,116 +934,6 @@ SELECT * FROM pg_stop_backup(false, true);
-
-
- Making an exclusive low level backup
-
- The process for an exclusive backup is mostly the same as for a
- non-exclusive one, but it differs in a few key steps. This type of backup
- can only be taken on a primary and does not allow concurrent backups.
- Prior to PostgreSQL 9.6, this
- was the only low-level method available, but it is now recommended that
- all users upgrade their scripts to use non-exclusive backups if possible.
-
-
-
-
-
- Ensure that WAL archiving is enabled and working.
-
-
-
-
- Connect to the server (it does not matter which database) as a user with
- rights to run pg_start_backup (superuser, or a user who has been granted
- EXECUTE on the function) and issue the command:
-
-SELECT pg_start_backup('label');
-
- where label is any string you want to use to uniquely
- identify this backup operation.
- pg_start_backup creates a backup label file,
- called backup_label, in the cluster directory with
- information about your backup, including the start time and label string.
- The function also creates a tablespace map file,
- called tablespace_map, in the cluster directory with
- information about tablespace symbolic links in pg_tblspc/ if
- one or more such link is present. Both files are critical to the
- integrity of the backup, should you need to restore from it.
-
-
-
- By default, pg_start_backup can take a long time to finish.
- This is because it performs a checkpoint, and the I/O
- required for the checkpoint will be spread out over a significant
- period of time, by default half your inter-checkpoint interval
- (see the configuration parameter
- ). This is
- usually what you want, because it minimizes the impact on query
- processing. If you want to start the backup as soon as
- possible, use:
-
-SELECT pg_start_backup('label', true);
-
- This forces the checkpoint to be done as quickly as possible.
-
-
-
-
- Perform the backup, using any convenient file-system-backup tool
- such as tar or cpio (not
- pg_dump or
- pg_dumpall). It is neither
- necessary nor desirable to stop normal operation of the database
- while you do this. See
- for things to
- consider during this backup.
-
-
- Note that if the server crashes during the backup it may not be
- possible to restart until the backup_label file has been
- manually deleted from the PGDATA directory.
-
-
-
-
- Again connect to the database as a user with rights to run
- pg_stop_backup (superuser, or a user who has been granted EXECUTE on
- the function), and issue the command:
-
-SELECT pg_stop_backup();
-
- This function terminates backup mode and
- performs an automatic switch to the next WAL segment. The reason for the
- switch is to arrange for the last WAL segment written during the backup
- interval to be ready to archive.
-
-
-
-
- Once the WAL segment files active during the backup are archived, you are
- done. The file identified by pg_stop_backup's result is
- the last segment that is required to form a complete set of backup files.
- If archive_mode is enabled,
- pg_stop_backup does not return until the last segment has
- been archived.
- Archiving of these files happens automatically since you have
- already configured archive_command. In most cases this
- happens quickly, but you are advised to monitor your archive
- system to ensure there are no delays.
- If the archive process has fallen behind
- because of failures of the archive command, it will keep retrying
- until the archive succeeds and the backup is complete.
- If you wish to place a time limit on the execution of
- pg_stop_backup, set an appropriate
- statement_timeout value, but make note that if
- pg_stop_backup terminates because of this your backup
- may not be valid.
-
-
-
-
-
Backing up the data directory
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index b3336ea9be..ae7722bb12 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -18945,38 +18945,17 @@ SELECT set_config('log_statement_stats', 'off', false);
- pg_start_backup(label text , fast boolean , exclusive boolean )
+ pg_start_backup(label text , fast boolean )
pg_lsn
Prepare for performing on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)
- pg_stop_backup()
-
- pg_lsn
- Finish performing exclusive on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)
-
-
-
- pg_stop_backup(exclusive boolean , wait_for_archive boolean )
+ pg_stop_backup( wait_for_archive boolean )
setof record
- Finish performing exclusive or non-exclusive on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)
-
-
-
- pg_is_in_backup()
-
- bool
- True if an on-line exclusive backup is still in progress.
-
-
-
- pg_backup_start_time()
-
- timestamp with time zone
- Get start time of an on-line exclusive backup in progress.
+ Finish performing on-line backup (restricted to superusers by default, but other users can be granted EXECUTE to run the function)
@@ -19013,16 +18992,9 @@ SELECT set_config('log_statement_stats', 'off', false);
pg_start_backup accepts an arbitrary user-defined label for
the backup. (Typically this would be the name under which the backup dump
- file will be stored.) When used in exclusive mode, the function writes a
- backup label file (backup_label) and, if there are any links
- in the pg_tblspc/ directory, a tablespace map file
- (tablespace_map) into the database cluster's data directory,
- performs a checkpoint, and then returns the backup's starting write-ahead
- log location as text. The user can ignore this result value, but it is
- provided in case it is useful. When used in non-exclusive mode, the
- contents of these files are instead returned by the
- pg_stop_backup function, and should be written to the backup
- by the caller.
+ file will be stored.) It returns the backup's starting write-ahead
+ log location as a pg_lsn which can be ignored by the user, but is
+ provided in case it is useful.
postgres=# select pg_start_backup('label_goes_here');
@@ -19038,12 +19010,10 @@ postgres=# select pg_start_backup('label_goes_here');
- In an exclusive backup, pg_stop_backup removes the label file
- and, if it exists, the tablespace_map file created by
- pg_start_backup. In a non-exclusive backup, the contents of
- the backup_label and tablespace_map are returned
- in the result of the function, and should be written to files in the
- backup (and not in the data directory). There is an optional second
+ The contents of the backup_label and
+ tablespace_map are returned in the result of
+ pg_stop_backup, and should be written to files in the
+ backup (and not in the data directory). There is an optional
parameter of type boolean. If false, the pg_stop_backup
will return immediately after the backup is completed without waiting for
WAL to be archived. This behavior is only useful for backup
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c80b14ed97..5807616289 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -493,29 +493,6 @@ typedef union WALInsertLockPadded
char pad[PG_CACHE_LINE_SIZE];
} WALInsertLockPadded;
-/*
- * State of an exclusive backup, necessary to control concurrent activities
- * across sessions when working on exclusive backups.
- *
- * EXCLUSIVE_BACKUP_NONE means that there is no exclusive backup actually
- * running, to be more precise pg_start_backup() is not being executed for
- * an exclusive backup and there is no exclusive backup in progress.
- * EXCLUSIVE_BACKUP_STARTING means that pg_start_backup() is starting an
- * exclusive backup.
- * EXCLUSIVE_BACKUP_IN_PROGRESS means that pg_start_backup() has finished
- * running and an exclusive backup is in progress. pg_stop_backup() is
- * needed to finish it.
- * EXCLUSIVE_BACKUP_STOPPING means that pg_stop_backup() is stopping an
- * exclusive backup.
- */
-typedef enum ExclusiveBackupState
-{
- EXCLUSIVE_BACKUP_NONE = 0,
- EXCLUSIVE_BACKUP_STARTING,
- EXCLUSIVE_BACKUP_IN_PROGRESS,
- EXCLUSIVE_BACKUP_STOPPING
-} ExclusiveBackupState;
-
/*
* Session status of running backup, used for sanity checks in SQL-callable
* functions to start and stop backups.
@@ -563,15 +540,12 @@ typedef struct XLogCtlInsert
bool fullPageWrites;
/*
- * exclusiveBackupState indicates the state of an exclusive backup (see
- * comments of ExclusiveBackupState for more details). nonExclusiveBackups
- * is a counter indicating the number of streaming base backups currently
- * in progress. forcePageWrites is set to true when either of these is
- * non-zero. lastBackupStart is the latest checkpoint redo location used
- * as a starting point for an online backup.
+ * runningBackups is a counter indicating the number of backups currently in
+ * progress. forcePageWrites is set to true when either of these is
+ * non-zero. lastBackupStart is the latest checkpoint redo location used as
+ * a starting point for an online backup.
*/
- ExclusiveBackupState exclusiveBackupState;
- int nonExclusiveBackups;
+ int runningBackups;
XLogRecPtr lastBackupStart;
/*
@@ -916,7 +890,6 @@ static void xlog_outrec(StringInfo buf, XLogReaderState *record);
#endif
static void xlog_outdesc(StringInfo buf, XLogReaderState *record);
static void pg_start_backup_callback(int code, Datum arg);
-static void pg_stop_backup_callback(int code, Datum arg);
static bool read_backup_label(XLogRecPtr *checkPointLoc,
bool *backupEndRequired, bool *backupFromStandby);
static bool read_tablespace_map(List **tablespaces);
@@ -9208,7 +9181,7 @@ CreateRestartPoint(int flags)
* Ensure minRecoveryPoint is past the checkpoint record. Normally,
* this will have happened already while writing out dirty buffers,
* but not necessarily - e.g. because no buffers were dirtied. We do
- * this because a non-exclusive base backup uses minRecoveryPoint to
+ * this because a backup performed in recovery uses minRecoveryPoint to
* determine which WAL files must be included in the backup, and the
* file (or files) containing the checkpoint record must be included,
* at a minimum. Note that for an ordinary restart of recovery there's
@@ -10165,36 +10138,25 @@ XLogFileNameP(TimeLineID tli, XLogSegNo segno)
/*
* do_pg_start_backup is the workhorse of the user-visible pg_start_backup()
* function. It creates the necessary starting checkpoint and constructs the
- * backup label file.
- *
- * There are two kind of backups: exclusive and non-exclusive. An exclusive
- * backup is started with pg_start_backup(), and there can be only one active
- * at a time. The backup and tablespace map files of an exclusive backup are
- * written to $PGDATA/backup_label and $PGDATA/tablespace_map, and they are
- * removed by pg_stop_backup().
- *
- * A non-exclusive backup is used for the streaming base backups (see
- * src/backend/replication/basebackup.c). The difference to exclusive backups
- * is that the backup label and tablespace map files are not written to disk.
- * Instead, their would-be contents are returned in *labelfile and *tblspcmapfile,
- * and the caller is responsible for including them in the backup archive as
- * 'backup_label' and 'tablespace_map'. There can be many non-exclusive backups
- * active at the same time, and they don't conflict with an exclusive backup
- * either.
+ * backup label and tablespace map.
+ *
+ * The backup label and tablespace map contents are returned in *labelfile and
+ * *tblspcmapfile, and the caller is responsible for including them in the
+ * backup archive as 'backup_label' and 'tablespace_map'. There can be many
+ * backups active at the same time.
*
* tblspcmapfile is required mainly for tar format in windows as native windows
* utilities are not able to create symlinks while extracting files from tar.
* However for consistency, the same is used for all platforms.
*
- * needtblspcmapfile is true for the cases (exclusive backup and for
- * non-exclusive backup only when tar format is used for taking backup)
- * when backup needs to generate tablespace_map file, it is used to
- * embed escape character before newline character in tablespace path.
+ * needtblspcmapfile is true for the cases (only when tar format is used for
+ * taking backup) when backup needs to generate tablespace_map file, it is used
+ * to embed escape character before newline character in tablespace path.
*
* Returns the minimum WAL location that must be present to restore from this
* backup, and the corresponding timeline ID in *starttli_p.
*
- * Every successfully started non-exclusive backup must be stopped by calling
+ * Every successfully started backup must be stopped by calling
* do_pg_stop_backup() or do_pg_abort_backup().
*
* It is the responsibility of the caller of this function to verify the
@@ -10206,7 +10168,6 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
StringInfo tblspcmapfile, bool infotbssize,
bool needtblspcmapfile)
{
- bool exclusive = (labelfile == NULL);
bool backup_started_in_recovery = false;
XLogRecPtr checkpointloc;
XLogRecPtr startpoint;
@@ -10215,20 +10176,9 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
char strfbuf[128];
char xlogfilename[MAXFNAMELEN];
XLogSegNo _logSegNo;
- struct stat stat_buf;
- FILE *fp;
backup_started_in_recovery = RecoveryInProgress();
- /*
- * Currently only non-exclusive backup can be taken during recovery.
- */
- if (backup_started_in_recovery && exclusive)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("recovery is in progress"),
- errhint("WAL control functions cannot be executed during recovery.")));
-
/*
* During recovery, we don't need to check WAL level. Because, if WAL
* level is not sufficient, it's impossible to get here during recovery.
@@ -10267,30 +10217,12 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
* XLogInsertRecord().
*/
WALInsertLockAcquireExclusive();
- if (exclusive)
- {
- /*
- * At first, mark that we're now starting an exclusive backup, to
- * ensure that there are no other sessions currently running
- * pg_start_backup() or pg_stop_backup().
- */
- if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_NONE)
- {
- WALInsertLockRelease();
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("a backup is already in progress"),
- errhint("Run pg_stop_backup() and try again.")));
- }
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STARTING;
- }
- else
- XLogCtl->Insert.nonExclusiveBackups++;
+ XLogCtl->Insert.runningBackups++;
XLogCtl->Insert.forcePageWrites = true;
WALInsertLockRelease();
/* Ensure we release forcePageWrites if fail below */
- PG_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) BoolGetDatum(exclusive));
+ PG_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) 0);
{
bool gotUniqueStartpoint = false;
DIR *tblspcdir;
@@ -10417,11 +10349,8 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
XLogFileName(xlogfilename, starttli, _logSegNo, wal_segment_size);
/*
- * Construct tablespace_map file
+ * Construct tablespace_map
*/
- if (exclusive)
- tblspcmapfile = makeStringInfo();
-
datadirpathlen = strlen(DataDir);
/* Collect information about all tablespaces */
@@ -10511,11 +10440,8 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
FreeDir(tblspcdir);
/*
- * Construct backup label file
+ * Construct backup_label
*/
- if (exclusive)
- labelfile = makeStringInfo();
-
/* Use the log timezone here, not the session timezone */
stamp_time = (pg_time_t) time(NULL);
pg_strftime(strfbuf, sizeof(strfbuf),
@@ -10525,122 +10451,19 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
(uint32) (startpoint >> 32), (uint32) startpoint, xlogfilename);
appendStringInfo(labelfile, "CHECKPOINT LOCATION: %X/%X\n",
(uint32) (checkpointloc >> 32), (uint32) checkpointloc);
- appendStringInfo(labelfile, "BACKUP METHOD: %s\n",
- exclusive ? "pg_start_backup" : "streamed");
+ appendStringInfo(labelfile, "BACKUP METHOD: streamed\n");
appendStringInfo(labelfile, "BACKUP FROM: %s\n",
backup_started_in_recovery ? "standby" : "master");
appendStringInfo(labelfile, "START TIME: %s\n", strfbuf);
appendStringInfo(labelfile, "LABEL: %s\n", backupidstr);
appendStringInfo(labelfile, "START TIMELINE: %u\n", starttli);
-
- /*
- * Okay, write the file, or return its contents to caller.
- */
- if (exclusive)
- {
- /*
- * Check for existing backup label --- implies a backup is already
- * running. (XXX given that we checked exclusiveBackupState
- * above, maybe it would be OK to just unlink any such label
- * file?)
- */
- if (stat(BACKUP_LABEL_FILE, &stat_buf) != 0)
- {
- if (errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("a backup is already in progress"),
- errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
- BACKUP_LABEL_FILE)));
-
- fp = AllocateFile(BACKUP_LABEL_FILE, "w");
-
- if (!fp)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not create file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- if (fwrite(labelfile->data, labelfile->len, 1, fp) != 1 ||
- fflush(fp) != 0 ||
- pg_fsync(fileno(fp)) != 0 ||
- ferror(fp) ||
- FreeFile(fp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- /* Allocated locally for exclusive backups, so free separately */
- pfree(labelfile->data);
- pfree(labelfile);
-
- /* Write backup tablespace_map file. */
- if (tblspcmapfile->len > 0)
- {
- if (stat(TABLESPACE_MAP, &stat_buf) != 0)
- {
- if (errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat file \"%s\": %m",
- TABLESPACE_MAP)));
- }
- else
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("a backup is already in progress"),
- errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.",
- TABLESPACE_MAP)));
-
- fp = AllocateFile(TABLESPACE_MAP, "w");
-
- if (!fp)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not create file \"%s\": %m",
- TABLESPACE_MAP)));
- if (fwrite(tblspcmapfile->data, tblspcmapfile->len, 1, fp) != 1 ||
- fflush(fp) != 0 ||
- pg_fsync(fileno(fp)) != 0 ||
- ferror(fp) ||
- FreeFile(fp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write file \"%s\": %m",
- TABLESPACE_MAP)));
- }
-
- /* Allocated locally for exclusive backups, so free separately */
- pfree(tblspcmapfile->data);
- pfree(tblspcmapfile);
- }
}
- PG_END_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) BoolGetDatum(exclusive));
+ PG_END_ENSURE_ERROR_CLEANUP(pg_start_backup_callback, (Datum) 0);
/*
- * Mark that start phase has correctly finished for an exclusive backup.
- * Session-level locks are updated as well to reflect that state.
- *
- * Note that CHECK_FOR_INTERRUPTS() must not occur while updating backup
- * counters and session-level lock. Otherwise they can be updated
- * inconsistently, and which might cause do_pg_abort_backup() to fail.
+ * Mark that the start phase has correctly finished for the backup.
*/
- if (exclusive)
- {
- WALInsertLockAcquireExclusive();
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
-
- /* Set session-level lock */
- sessionBackupState = SESSION_BACKUP_EXCLUSIVE;
- WALInsertLockRelease();
- }
- else
- sessionBackupState = SESSION_BACKUP_NON_EXCLUSIVE;
+ sessionBackupState = SESSION_BACKUP_RUNNING;
/*
* We're done. As a convenience, return the starting WAL location.
@@ -10654,43 +10477,15 @@ do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
static void
pg_start_backup_callback(int code, Datum arg)
{
- bool exclusive = DatumGetBool(arg);
-
/* Update backup counters and forcePageWrites on failure */
WALInsertLockAcquireExclusive();
- if (exclusive)
- {
- Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STARTING);
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
- }
- else
- {
- Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
- XLogCtl->Insert.nonExclusiveBackups--;
- }
- if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
- XLogCtl->Insert.nonExclusiveBackups == 0)
- {
- XLogCtl->Insert.forcePageWrites = false;
- }
- WALInsertLockRelease();
-}
+ Assert(XLogCtl->Insert.runningBackups > 0);
+ XLogCtl->Insert.runningBackups--;
-/*
- * Error cleanup callback for pg_stop_backup
- */
-static void
-pg_stop_backup_callback(int code, Datum arg)
-{
- bool exclusive = DatumGetBool(arg);
-
- /* Update backup status on failure */
- WALInsertLockAcquireExclusive();
- if (exclusive)
+ if (XLogCtl->Insert.runningBackups == 0)
{
- Assert(XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_STOPPING);
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_IN_PROGRESS;
+ XLogCtl->Insert.forcePageWrites = false;
}
WALInsertLockRelease();
}
@@ -10708,9 +10503,6 @@ get_backup_status(void)
* do_pg_stop_backup is the workhorse of the user-visible pg_stop_backup()
* function.
*
- * If labelfile is NULL, this stops an exclusive backup. Otherwise this stops
- * the non-exclusive backup specified by 'labelfile'.
- *
* Returns the last WAL location that must be present to restore from this
* backup, and the corresponding timeline ID in *stoptli_p.
*
@@ -10720,7 +10512,6 @@ get_backup_status(void)
XLogRecPtr
do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
{
- bool exclusive = (labelfile == NULL);
bool backup_started_in_recovery = false;
XLogRecPtr startpoint;
XLogRecPtr stoppoint;
@@ -10734,7 +10525,6 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
char histfilename[MAXFNAMELEN];
char backupfrom[20];
XLogSegNo _logSegNo;
- FILE *lfp;
FILE *fp;
char ch;
int seconds_before_warning;
@@ -10747,15 +10537,6 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
backup_started_in_recovery = RecoveryInProgress();
- /*
- * Currently only non-exclusive backup can be taken during recovery.
- */
- if (backup_started_in_recovery && exclusive)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("recovery is in progress"),
- errhint("WAL control functions cannot be executed during recovery.")));
-
/*
* During recovery, we don't need to check WAL level. Because, if WAL
* level is not sufficient, it's impossible to get here during recovery.
@@ -10766,106 +10547,23 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
errmsg("WAL level not sufficient for making an online backup"),
errhint("wal_level must be set to \"replica\" or \"logical\" at server start.")));
- if (exclusive)
- {
- /*
- * At first, mark that we're now stopping an exclusive backup, to
- * ensure that there are no other sessions currently running
- * pg_start_backup() or pg_stop_backup().
- */
- WALInsertLockAcquireExclusive();
- if (XLogCtl->Insert.exclusiveBackupState != EXCLUSIVE_BACKUP_IN_PROGRESS)
- {
- WALInsertLockRelease();
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("exclusive backup not in progress")));
- }
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_STOPPING;
- WALInsertLockRelease();
-
- /*
- * Remove backup_label. In case of failure, the state for an exclusive
- * backup is switched back to in-progress.
- */
- PG_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
- {
- /*
- * Read the existing label file into memory.
- */
- struct stat statbuf;
- int r;
-
- if (stat(BACKUP_LABEL_FILE, &statbuf))
- {
- /* should not happen per the upper checks */
- if (errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("a backup is not in progress")));
- }
-
- lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
- if (!lfp)
- {
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- }
- labelfile = palloc(statbuf.st_size + 1);
- r = fread(labelfile, statbuf.st_size, 1, lfp);
- labelfile[statbuf.st_size] = '\0';
-
- /*
- * Close and remove the backup label file
- */
- if (r != 1 || ferror(lfp) || FreeFile(lfp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- durable_unlink(BACKUP_LABEL_FILE, ERROR);
-
- /*
- * Remove tablespace_map file if present, it is created only if
- * there are tablespaces.
- */
- durable_unlink(TABLESPACE_MAP, DEBUG1);
- }
- PG_END_ENSURE_ERROR_CLEANUP(pg_stop_backup_callback, (Datum) BoolGetDatum(exclusive));
- }
-
/*
- * OK to update backup counters, forcePageWrites and session-level lock.
+ * OK to update backup counters and forcePageWrites.
*
* Note that CHECK_FOR_INTERRUPTS() must not occur while updating them.
* Otherwise they can be updated inconsistently, and which might cause
* do_pg_abort_backup() to fail.
*/
WALInsertLockAcquireExclusive();
- if (exclusive)
- {
- XLogCtl->Insert.exclusiveBackupState = EXCLUSIVE_BACKUP_NONE;
- }
- else
- {
- /*
- * The user-visible pg_start/stop_backup() functions that operate on
- * exclusive backups can be called at any time, but for non-exclusive
- * backups, it is expected that each do_pg_start_backup() call is
- * matched by exactly one do_pg_stop_backup() call.
- */
- Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
- XLogCtl->Insert.nonExclusiveBackups--;
- }
- if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
- XLogCtl->Insert.nonExclusiveBackups == 0)
+ /*
+ * It is expected that each do_pg_start_backup() call is matched by exactly
+ * one do_pg_stop_backup() call.
+ */
+ Assert(XLogCtl->Insert.runningBackups > 0);
+ XLogCtl->Insert.runningBackups--;
+
+ if (XLogCtl->Insert.runningBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
}
@@ -11117,28 +10815,21 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
* This does just the most basic steps of do_pg_stop_backup(), by taking the
* system out of backup mode, thus making it a lot more safe to call from
* an error handler.
- *
- * NB: This is only for aborting a non-exclusive backup that doesn't write
- * backup_label. A backup started with pg_start_backup() needs to be finished
- * with pg_stop_backup().
*/
void
do_pg_abort_backup(void)
{
/*
- * Quick exit if session is not keeping around a non-exclusive backup
- * already started.
+ * Quick exit if session does not have a running backup.
*/
if (sessionBackupState == SESSION_BACKUP_NONE)
return;
WALInsertLockAcquireExclusive();
- Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
- Assert(sessionBackupState == SESSION_BACKUP_NON_EXCLUSIVE);
- XLogCtl->Insert.nonExclusiveBackups--;
+ Assert(XLogCtl->Insert.runningBackups > 0);
+ XLogCtl->Insert.runningBackups--;
- if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
- XLogCtl->Insert.nonExclusiveBackups == 0)
+ if (XLogCtl->Insert.runningBackups == 0)
{
XLogCtl->Insert.forcePageWrites = false;
}
@@ -11441,87 +11132,6 @@ rm_redo_error_callback(void *arg)
pfree(buf.data);
}
-/*
- * BackupInProgress: check if online backup mode is active
- *
- * This is done by checking for existence of the "backup_label" file.
- */
-bool
-BackupInProgress(void)
-{
- struct stat stat_buf;
-
- return (stat(BACKUP_LABEL_FILE, &stat_buf) == 0);
-}
-
-/*
- * CancelBackup: rename the "backup_label" and "tablespace_map"
- * files to cancel backup mode
- *
- * If the "backup_label" file exists, it will be renamed to "backup_label.old".
- * Similarly, if the "tablespace_map" file exists, it will be renamed to
- * "tablespace_map.old".
- *
- * Note that this will render an online backup in progress
- * useless. To correctly finish an online backup, pg_stop_backup must be
- * called.
- */
-void
-CancelBackup(void)
-{
- struct stat stat_buf;
-
- /* if the backup_label file is not there, return */
- if (stat(BACKUP_LABEL_FILE, &stat_buf) < 0)
- return;
-
- /* remove leftover file from previously canceled backup if it exists */
- unlink(BACKUP_LABEL_OLD);
-
- if (durable_rename(BACKUP_LABEL_FILE, BACKUP_LABEL_OLD, DEBUG1) != 0)
- {
- ereport(WARNING,
- (errcode_for_file_access(),
- errmsg("online backup mode was not canceled"),
- errdetail("File \"%s\" could not be renamed to \"%s\": %m.",
- BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
- return;
- }
-
- /* if the tablespace_map file is not there, return */
- if (stat(TABLESPACE_MAP, &stat_buf) < 0)
- {
- ereport(LOG,
- (errmsg("online backup mode canceled"),
- errdetail("File \"%s\" was renamed to \"%s\".",
- BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
- return;
- }
-
- /* remove leftover file from previously canceled backup if it exists */
- unlink(TABLESPACE_MAP_OLD);
-
- if (durable_rename(TABLESPACE_MAP, TABLESPACE_MAP_OLD, DEBUG1) == 0)
- {
- ereport(LOG,
- (errmsg("online backup mode canceled"),
- errdetail("Files \"%s\" and \"%s\" were renamed to "
- "\"%s\" and \"%s\", respectively.",
- BACKUP_LABEL_FILE, TABLESPACE_MAP,
- BACKUP_LABEL_OLD, TABLESPACE_MAP_OLD)));
- }
- else
- {
- ereport(WARNING,
- (errcode_for_file_access(),
- errmsg("online backup mode canceled"),
- errdetail("File \"%s\" was renamed to \"%s\", but "
- "file \"%s\" could not be renamed to \"%s\": %m.",
- BACKUP_LABEL_FILE, BACKUP_LABEL_OLD,
- TABLESPACE_MAP, TABLESPACE_MAP_OLD)));
- }
-}
-
/*
* Read the XLOG page containing RecPtr into readBuf (if not read already).
* Returns number of bytes read, if the page is read successfully, or -1
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index f139eeff9f..469d5e41c1 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -40,17 +40,16 @@
/*
- * Store label file and tablespace map during non-exclusive backups.
+ * Store label file and tablespace map during backups.
*/
static StringInfo label_file;
static StringInfo tblspc_map_file;
/*
- * Called when the backend exits with a running non-exclusive base backup,
- * to clean up state.
+ * Called when the backend exits with a running base backup to clean up state.
*/
static void
-nonexclusive_base_backup_cleanup(int code, Datum arg)
+base_backup_cleanup(int code, Datum arg)
{
do_pg_abort_backup();
ereport(WARNING,
@@ -74,101 +73,40 @@ pg_start_backup(PG_FUNCTION_ARGS)
{
text *backupid = PG_GETARG_TEXT_PP(0);
bool fast = PG_GETARG_BOOL(1);
- bool exclusive = PG_GETARG_BOOL(2);
char *backupidstr;
XLogRecPtr startpoint;
SessionBackupState status = get_backup_status();
+ MemoryContext oldcontext;
backupidstr = text_to_cstring(backupid);
- if (status == SESSION_BACKUP_NON_EXCLUSIVE)
+ if (status == SESSION_BACKUP_RUNNING)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("a backup is already in progress in this session")));
- if (exclusive)
- {
- startpoint = do_pg_start_backup(backupidstr, fast, NULL, NULL,
- NULL, NULL, false, true);
- }
- else
- {
- MemoryContext oldcontext;
-
- /*
- * Label file and tablespace map file need to be long-lived, since
- * they are read in pg_stop_backup.
- */
- oldcontext = MemoryContextSwitchTo(TopMemoryContext);
- label_file = makeStringInfo();
- tblspc_map_file = makeStringInfo();
- MemoryContextSwitchTo(oldcontext);
+ /*
+ * Label file and tablespace map file need to be long-lived, since
+ * they are read in pg_stop_backup.
+ */
+ oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ label_file = makeStringInfo();
+ tblspc_map_file = makeStringInfo();
+ MemoryContextSwitchTo(oldcontext);
- startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
- NULL, tblspc_map_file, false, true);
+ startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
+ NULL, tblspc_map_file, false, true);
- before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
- }
+ before_shmem_exit(base_backup_cleanup, (Datum) 0);
PG_RETURN_LSN(startpoint);
}
-/*
- * pg_stop_backup: finish taking an on-line backup dump
- *
- * We write an end-of-backup WAL record, and remove the backup label file
- * created by pg_start_backup, creating a backup history file in pg_wal
- * instead (whence it will immediately be archived). The backup history file
- * contains the same info found in the label file, plus the backup-end time
- * and WAL location. Before 9.0, the backup-end time was read from the backup
- * history file at the beginning of archive recovery, but we now use the WAL
- * record for that and the file is for informational and debug purposes only.
- *
- * Note: different from CancelBackup which just cancels online backup mode.
- *
- * Note: this version is only called to stop an exclusive backup. The function
- * pg_stop_backup_v2 (overloaded as pg_stop_backup in SQL) is called to
- * stop non-exclusive backups.
- *
- * Permission checking for this function is managed through the normal
- * GRANT system.
- */
-Datum
-pg_stop_backup(PG_FUNCTION_ARGS)
-{
- XLogRecPtr stoppoint;
- SessionBackupState status = get_backup_status();
-
- if (status == SESSION_BACKUP_NON_EXCLUSIVE)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("non-exclusive backup in progress"),
- errhint("Did you mean to use pg_stop_backup('f')?")));
-
- /*
- * Exclusive backups were typically started in a different connection, so
- * don't try to verify that status of backup is set to
- * SESSION_BACKUP_EXCLUSIVE in this function. Actual verification that an
- * exclusive backup is in fact running is handled inside
- * do_pg_stop_backup.
- */
- stoppoint = do_pg_stop_backup(NULL, true, NULL);
-
- PG_RETURN_LSN(stoppoint);
-}
-
/*
- * pg_stop_backup_v2: finish taking exclusive or nonexclusive on-line backup.
+ * pg_stop_backup: finish taking an on-line backup.
*
- * Works the same as pg_stop_backup, except for non-exclusive backups it returns
- * the backup label and tablespace map files as text fields in as part of the
- * resultset.
- *
- * The first parameter (variable 'exclusive') allows the user to tell us if
- * this is an exclusive or a non-exclusive backup.
- *
- * The second parameter (variable 'waitforarchive'), which is optional,
+ * The first parameter (variable 'waitforarchive'), which is optional,
* allows the user to choose if they want to wait for the WAL to be archived
* or if we should just return as soon as the WAL record is written.
*
@@ -176,7 +114,7 @@ pg_stop_backup(PG_FUNCTION_ARGS)
* GRANT system.
*/
Datum
-pg_stop_backup_v2(PG_FUNCTION_ARGS)
+pg_stop_backup(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc tupdesc;
@@ -186,8 +124,7 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
Datum values[3];
bool nulls[3];
- bool exclusive = PG_GETARG_BOOL(0);
- bool waitforarchive = PG_GETARG_BOOL(1);
+ bool waitforarchive = PG_GETARG_BOOL(0);
XLogRecPtr stoppoint;
SessionBackupState status = get_backup_status();
@@ -219,52 +156,30 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
MemSet(values, 0, sizeof(values));
MemSet(nulls, 0, sizeof(nulls));
- if (exclusive)
- {
- if (status == SESSION_BACKUP_NON_EXCLUSIVE)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("non-exclusive backup in progress"),
- errhint("Did you mean to use pg_stop_backup('f')?")));
-
- /*
- * Stop the exclusive backup, and since we're in an exclusive backup
- * return NULL for both backup_label and tablespace_map.
- */
- stoppoint = do_pg_stop_backup(NULL, waitforarchive, NULL);
-
- nulls[1] = true;
- nulls[2] = true;
- }
- else
- {
- if (status != SESSION_BACKUP_NON_EXCLUSIVE)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("non-exclusive backup is not in progress"),
- errhint("Did you mean to use pg_stop_backup('t')?")));
-
- /*
- * Stop the non-exclusive backup. Return a copy of the backup label
- * and tablespace map so they can be written to disk by the caller.
- */
- stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
- cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
-
- values[1] = CStringGetTextDatum(label_file->data);
- values[2] = CStringGetTextDatum(tblspc_map_file->data);
-
- /* Free structures allocated in TopMemoryContext */
- pfree(label_file->data);
- pfree(label_file);
- label_file = NULL;
- pfree(tblspc_map_file->data);
- pfree(tblspc_map_file);
- tblspc_map_file = NULL;
- }
+ if (status != SESSION_BACKUP_RUNNING)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("backup is not in progress"),
+ errhint("Did you call pg_start_backup()?")));
+
+ /*
+ * Stop the backup. Return a copy of the backup label and tablespace map so
+ * they can be written to disk by the caller.
+ */
+ stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
+ cancel_before_shmem_exit(base_backup_cleanup, (Datum) 0);
- /* Stoppoint is included on both exclusive and nonexclusive backups */
values[0] = LSNGetDatum(stoppoint);
+ values[1] = CStringGetTextDatum(label_file->data);
+ values[2] = CStringGetTextDatum(tblspc_map_file->data);
+
+ /* Free structures allocated in TopMemoryContext */
+ pfree(label_file->data);
+ pfree(label_file);
+ label_file = NULL;
+ pfree(tblspc_map_file->data);
+ pfree(tblspc_map_file);
+ tblspc_map_file = NULL;
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
tuplestore_donestoring(typstore);
@@ -626,81 +541,6 @@ pg_wal_lsn_diff(PG_FUNCTION_ARGS)
PG_RETURN_NUMERIC(result);
}
-/*
- * Returns bool with current on-line backup mode, a global state.
- */
-Datum
-pg_is_in_backup(PG_FUNCTION_ARGS)
-{
- PG_RETURN_BOOL(BackupInProgress());
-}
-
-/*
- * Returns start time of an online exclusive backup.
- *
- * When there's no exclusive backup in progress, the function
- * returns NULL.
- */
-Datum
-pg_backup_start_time(PG_FUNCTION_ARGS)
-{
- Datum xtime;
- FILE *lfp;
- char fline[MAXPGPATH];
- char backup_start_time[30];
-
- /*
- * See if label file is present
- */
- lfp = AllocateFile(BACKUP_LABEL_FILE, "r");
- if (lfp == NULL)
- {
- if (errno != ENOENT)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m",
- BACKUP_LABEL_FILE)));
- PG_RETURN_NULL();
- }
-
- /*
- * Parse the file to find the START TIME line.
- */
- backup_start_time[0] = '\0';
- while (fgets(fline, sizeof(fline), lfp) != NULL)
- {
- if (sscanf(fline, "START TIME: %25[^\n]\n", backup_start_time) == 1)
- break;
- }
-
- /* Check for a read error. */
- if (ferror(lfp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not read file \"%s\": %m", BACKUP_LABEL_FILE)));
-
- /* Close the backup label file. */
- if (FreeFile(lfp))
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not close file \"%s\": %m", BACKUP_LABEL_FILE)));
-
- if (strlen(backup_start_time) == 0)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
-
- /*
- * Convert the time string read from file to TimestampTz form.
- */
- xtime = DirectFunctionCall3(timestamptz_in,
- CStringGetDatum(backup_start_time),
- ObjectIdGetDatum(InvalidOid),
- Int32GetDatum(-1));
-
- PG_RETURN_DATUM(xtime);
-}
-
/*
* Promotes a standby server.
*
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 8630542bb3..bf30693f23 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1018,14 +1018,14 @@ COMMENT ON FUNCTION ts_debug(text) IS
--
CREATE OR REPLACE FUNCTION
- pg_start_backup(label text, fast boolean DEFAULT false, exclusive boolean DEFAULT true)
+ pg_start_backup(label text, fast boolean DEFAULT false)
RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup'
PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION pg_stop_backup (
- exclusive boolean, wait_for_archive boolean DEFAULT true,
- OUT lsn pg_lsn, OUT labelfile text, OUT spcmapfile text)
- RETURNS SETOF record STRICT VOLATILE LANGUAGE internal as 'pg_stop_backup_v2'
+ wait_for_archive boolean DEFAULT true, OUT lsn pg_lsn, OUT labelfile text,
+ OUT spcmapfile text)
+ RETURNS SETOF record STRICT VOLATILE LANGUAGE internal as 'pg_stop_backup'
PARALLEL RESTRICTED;
CREATE OR REPLACE FUNCTION
@@ -1133,9 +1133,8 @@ AS 'jsonb_insert';
-- can later change who can access these functions, or leave them as only
-- available to superuser / cluster owner, if they choose.
--
-REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean, boolean) FROM public;
-REVOKE EXECUTE ON FUNCTION pg_stop_backup() FROM public;
-REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_start_backup(text, boolean) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stop_backup(boolean) FROM public;
REVOKE EXECUTE ON FUNCTION pg_create_restore_point(text) FROM public;
REVOKE EXECUTE ON FUNCTION pg_switch_wal() FROM public;
REVOKE EXECUTE ON FUNCTION pg_wal_replay_pause() FROM public;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index a33a131182..3a8653ab4d 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -300,8 +300,7 @@ static bool FatalError = false; /* T if recovering from backend crash */
* and we switch to PM_RUN state.
*
* Normal child backends can only be launched when we are in PM_RUN or
- * PM_HOT_STANDBY state. (We also allow launch of normal
- * child backends in PM_WAIT_BACKUP state, but only for superusers.)
+ * PM_HOT_STANDBY state.
* In other states we handle connection requests by launching "dead_end"
* child processes, which will simply send the client an error message and
* quit. (We track these in the BackendList so that we can know when they
@@ -327,7 +326,6 @@ typedef enum
PM_RECOVERY, /* in archive recovery mode */
PM_HOT_STANDBY, /* in hot standby mode */
PM_RUN, /* normal "database is alive" state */
- PM_WAIT_BACKUP, /* waiting for online backup mode to end */
PM_WAIT_READONLY, /* waiting for read only backends to exit */
PM_WAIT_BACKENDS, /* waiting for live backends to exit */
PM_SHUTDOWN, /* waiting for checkpointer to do shutdown
@@ -2241,9 +2239,6 @@ retry1:
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("sorry, too many clients already")));
break;
- case CAC_WAITBACKUP:
- /* OK for now, will check in InitPostgres */
- break;
case CAC_OK:
break;
}
@@ -2352,18 +2347,10 @@ canAcceptConnections(void)
/*
* Can't start backends when in startup/shutdown/inconsistent recovery
* state.
- *
- * In state PM_WAIT_BACKUP only superusers can connect (this must be
- * allowed so that a superuser can end online backup mode); we return
- * CAC_WAITBACKUP code to indicate that this must be checked later. Note
- * that neither CAC_OK nor CAC_WAITBACKUP can safely be returned until we
- * have checked for too many children.
*/
if (pmState != PM_RUN)
{
- if (pmState == PM_WAIT_BACKUP)
- result = CAC_WAITBACKUP; /* allow superusers only */
- else if (Shutdown > NoShutdown)
+ if (Shutdown > NoShutdown)
return CAC_SHUTDOWN; /* shutdown is pending */
else if (!FatalError &&
(pmState == PM_STARTUP ||
@@ -2704,7 +2691,7 @@ pmdie(SIGNAL_ARGS)
* and walreceiver processes.
*/
pmState = (pmState == PM_RUN) ?
- PM_WAIT_BACKUP : PM_WAIT_READONLY;
+ PM_WAIT_BACKENDS : PM_WAIT_READONLY;
}
/*
@@ -2754,7 +2741,6 @@ pmdie(SIGNAL_ARGS)
pmState = PM_WAIT_BACKENDS;
}
else if (pmState == PM_RUN ||
- pmState == PM_WAIT_BACKUP ||
pmState == PM_WAIT_READONLY ||
pmState == PM_WAIT_BACKENDS ||
pmState == PM_HOT_STANDBY)
@@ -3571,7 +3557,6 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
if (pmState == PM_RECOVERY ||
pmState == PM_HOT_STANDBY ||
pmState == PM_RUN ||
- pmState == PM_WAIT_BACKUP ||
pmState == PM_WAIT_READONLY ||
pmState == PM_SHUTDOWN)
pmState = PM_WAIT_BACKENDS;
@@ -3663,15 +3648,6 @@ LogChildExit(int lev, const char *procname, int pid, int exitstatus)
static void
PostmasterStateMachine(void)
{
- if (pmState == PM_WAIT_BACKUP)
- {
- /*
- * PM_WAIT_BACKUP state ends when online backup mode is not active.
- */
- if (!BackupInProgress())
- pmState = PM_WAIT_BACKENDS;
- }
-
if (pmState == PM_WAIT_READONLY)
{
/*
@@ -3841,18 +3817,6 @@ PostmasterStateMachine(void)
}
else
{
- /*
- * Terminate exclusive backup mode to avoid recovery after a clean
- * fast shutdown. Since an exclusive backup can only be taken
- * during normal running (and not, for example, while running
- * under Hot Standby) it only makes sense to do this if we reached
- * normal running. If we're still in recovery, the backup file is
- * one we're recovering *from*, and we must keep it around so that
- * recovery restarts from the right place.
- */
- if (ReachedNormalRunning)
- CancelBackup();
-
/* Normal exit from the postmaster is here */
ExitPostmaster(0);
}
@@ -4054,8 +4018,7 @@ BackendStartup(Port *port)
/* Pass down canAcceptConnections state */
port->canAcceptConnections = canAcceptConnections();
- bn->dead_end = (port->canAcceptConnections != CAC_OK &&
- port->canAcceptConnections != CAC_WAITBACKUP);
+ bn->dead_end = port->canAcceptConnections != CAC_OK;
/*
* Unless it's a dead_end child, assign it a child slot number
@@ -5182,7 +5145,7 @@ sigusr1_handler(SIGNAL_ARGS)
}
if (CheckPostmasterSignal(PMSIGNAL_ADVANCE_STATE_MACHINE) &&
- (pmState == PM_WAIT_BACKUP || pmState == PM_WAIT_BACKENDS))
+ pmState == PM_WAIT_BACKENDS)
{
/* Advance postmaster's state machine */
PostmasterStateMachine();
@@ -5775,7 +5738,6 @@ bgworker_should_start_now(BgWorkerStartTime start_time)
case PM_SHUTDOWN:
case PM_WAIT_BACKENDS:
case PM_WAIT_READONLY:
- case PM_WAIT_BACKUP:
break;
case PM_RUN:
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index 78ed6cf797..448556d7c3 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -172,10 +172,8 @@ static const char *excludeFiles[] =
RELCACHE_INIT_FILENAME,
/*
- * If there's a backup_label or tablespace_map file, it belongs to a
- * backup started by the user with pg_start_backup(). It is *not* correct
- * for this backup. Our backup_label/tablespace_map is injected into the
- * tar separately.
+ * backup_label and tablespace_map should not exist in in a running cluster
+ * capable of doing an online backup, but exclude then just in case.
*/
BACKUP_LABEL_FILE,
TABLESPACE_MAP,
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index b636b1e262..d868c21fdc 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -788,7 +788,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
*/
if ((!am_superuser || am_walsender) &&
MyProcPort != NULL &&
- MyProcPort->canAcceptConnections == CAC_WAITBACKUP)
+ MyProcPort->canAcceptConnections == CAC_SHUTDOWN)
{
if (am_walsender)
ereport(FATAL,
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 3e1c3863c4..04eea9bfeb 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -158,6 +158,10 @@ isnt(slurp_file("$tempdir/backup/backup_label"),
'DONOTCOPY', 'existing backup_label not copied');
rmtree("$tempdir/backup");
+# Now delete the bogus backup_label file since it will interfere with startup
+unlink("$pgdata/backup_label")
+ or BAIL_OUT("unable to unlink $pgdata/backup_label");
+
$node->command_ok(
[
'pg_basebackup', '-D', "$tempdir/backup2", '--waldir',
diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c
index 222b56f58a..084ea06597 100644
--- a/src/bin/pg_rewind/filemap.c
+++ b/src/bin/pg_rewind/filemap.c
@@ -94,9 +94,9 @@ static const char *excludeFiles[] =
"pg_internal.init", /* defined as RELCACHE_INIT_FILENAME */
/*
- * If there's a backup_label or tablespace_map file, it belongs to a
- * backup started by the user with pg_start_backup(). It is *not* correct
- * for this backup. Our backup_label is written later on separately.
+ * If there is a backup_label or tablespace_map file, it indicates that
+ * a recovery failed and this cluster probably can't be rewound, but
+ * exclude them anyway if they are found.
*/
"backup_label", /* defined as BACKUP_LABEL_FILE */
"tablespace_map", /* defined as TABLESPACE_MAP */
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index f3a7ba4d42..7d0f45ff99 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -338,8 +338,7 @@ extern void assign_checkpoint_completion_target(double newval, void *extra);
typedef enum SessionBackupState
{
SESSION_BACKUP_NONE,
- SESSION_BACKUP_EXCLUSIVE,
- SESSION_BACKUP_NON_EXCLUSIVE
+ SESSION_BACKUP_RUNNING,
} SessionBackupState;
extern XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast,
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f79fcfe029..4a4c49cf99 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5814,25 +5814,15 @@
proargtypes => 'int4', prosrc => 'pg_terminate_backend' },
{ oid => '2172', descr => 'prepare for taking an online backup',
proname => 'pg_start_backup', provolatile => 'v', proparallel => 'r',
- prorettype => 'pg_lsn', proargtypes => 'text bool bool',
+ prorettype => 'pg_lsn', proargtypes => 'text bool',
prosrc => 'pg_start_backup' },
-{ oid => '2173', descr => 'finish taking an online backup',
- proname => 'pg_stop_backup', provolatile => 'v', proparallel => 'r',
- prorettype => 'pg_lsn', proargtypes => '', prosrc => 'pg_stop_backup' },
{ oid => '2739', descr => 'finish taking an online backup',
proname => 'pg_stop_backup', prorows => '1', proretset => 't',
provolatile => 'v', proparallel => 'r', prorettype => 'record',
- proargtypes => 'bool bool', proallargtypes => '{bool,bool,pg_lsn,text,text}',
- proargmodes => '{i,i,o,o,o}',
- proargnames => '{exclusive,wait_for_archive,lsn,labelfile,spcmapfile}',
- prosrc => 'pg_stop_backup_v2' },
-{ oid => '3813', descr => 'true if server is in online backup',
- proname => 'pg_is_in_backup', provolatile => 'v', prorettype => 'bool',
- proargtypes => '', prosrc => 'pg_is_in_backup' },
-{ oid => '3814', descr => 'start time of an online backup',
- proname => 'pg_backup_start_time', provolatile => 's',
- prorettype => 'timestamptz', proargtypes => '',
- prosrc => 'pg_backup_start_time' },
+ proargtypes => 'bool', proallargtypes => '{bool,pg_lsn,text,text}',
+ proargmodes => '{i,o,o,o}',
+ proargnames => '{wait_for_archive,lsn,labelfile,spcmapfile}',
+ prosrc => 'pg_stop_backup' },
{ oid => '3436', descr => 'promote standby server',
proname => 'pg_promote', provolatile => 'v', prorettype => 'bool',
proargtypes => 'bool int4', proargnames => '{wait,wait_seconds}',
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index b2c59df54e..3d7b831599 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -70,8 +70,7 @@ typedef struct
typedef enum CAC_state
{
- CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY,
- CAC_WAITBACKUP
+ CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
} CAC_state;
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index d6b32c070c..687056ba55 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -447,8 +447,4 @@ extern void process_session_preload_libraries(void);
extern void pg_bindtextdomain(const char *domain);
extern bool has_rolreplication(Oid roleid);
-/* in access/transam/xlog.c */
-extern bool BackupInProgress(void);
-extern void CancelBackup(void);
-
#endif /* MISCADMIN_H */
diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm
index 8a2c6fc122..4c27a7d362 100644
--- a/src/test/perl/PostgresNode.pm
+++ b/src/test/perl/PostgresNode.pm
@@ -546,25 +546,6 @@ sub backup
return;
}
-=item $node->backup_fs_hot(backup_name)
-
-Create a backup with a filesystem level copy in subdirectory B of
-B<< $node->backup_dir >>, including WAL.
-
-Archiving must be enabled, as B and B are
-used. This is not checked or enforced.
-
-The backup name is passed as the backup label to B.
-
-=cut
-
-sub backup_fs_hot
-{
- my ($self, $backup_name) = @_;
- $self->_backup_fs($backup_name, 1);
- return;
-}
-
=item $node->backup_fs_cold(backup_name)
Create a backup with a filesystem level copy in subdirectory B of
@@ -578,53 +559,18 @@ Use B or B if you want to back up a running server.
sub backup_fs_cold
{
my ($self, $backup_name) = @_;
- $self->_backup_fs($backup_name, 0);
- return;
-}
-
-
-# Common sub of backup_fs_hot and backup_fs_cold
-sub _backup_fs
-{
- my ($self, $backup_name, $hot) = @_;
- my $backup_path = $self->backup_dir . '/' . $backup_name;
- my $port = $self->port;
- my $name = $self->name;
-
- print "# Taking filesystem backup $backup_name from node \"$name\"\n";
-
- if ($hot)
- {
- my $stdout = $self->safe_psql('postgres',
- "SELECT * FROM pg_start_backup('$backup_name');");
- print "# pg_start_backup: $stdout\n";
- }
RecursiveCopy::copypath(
$self->data_dir,
- $backup_path,
+ $self->backup_dir . '/' . $backup_name,
filterfn => sub {
my $src = shift;
return ($src ne 'log' and $src ne 'postmaster.pid');
});
- if ($hot)
- {
-
- # We ignore pg_stop_backup's return value. We also assume archiving
- # is enabled; otherwise the caller will have to copy the remaining
- # segments.
- my $stdout =
- $self->safe_psql('postgres', 'SELECT * FROM pg_stop_backup();');
- print "# pg_stop_backup: $stdout\n";
- }
-
- print "# Backup finished\n";
return;
}
-
-
=pod
=item $node->init_from_backup(root_node, backup_name)
diff --git a/src/test/recovery/t/010_logical_decoding_timelines.pl b/src/test/recovery/t/010_logical_decoding_timelines.pl
index e582b20005..32dfda454c 100644
--- a/src/test/recovery/t/010_logical_decoding_timelines.pl
+++ b/src/test/recovery/t/010_logical_decoding_timelines.pl
@@ -66,7 +66,9 @@ $node_master->safe_psql('dropme',
$node_master->safe_psql('postgres', 'CHECKPOINT;');
my $backup_name = 'b1';
-$node_master->backup_fs_hot($backup_name);
+$node_master->stop();
+$node_master->backup_fs_cold($backup_name);
+$node_master->start();
$node_master->safe_psql('postgres',
q[SELECT pg_create_physical_replication_slot('phys_slot');]);