1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2025-02-03 14:01:57 +02:00

Improve backup mode management

This commit makes mandatory the presence of a full backup when doing
an incremental or archive backup on an existing timeline. In this case
the process will now simply error out and not take any backup. It looks
safer to use that as a default by the way, so as user will be forced
to take a full backup once a recovery has been done.

Database backup also contained the following condition when doing an
incremental backup:
prev_backup->tli != current.tli
This means that an incremental backup cannot be taken if there is not
already a full backup present in the same timeline. The same condition
should also be used for archive backup but it didn't seem to be the
case...
This commit is contained in:
Michael Paquier 2013-12-25 05:27:25 +09:00
parent 26b8870665
commit 1bc1f1d1b6
3 changed files with 64 additions and 48 deletions

View File

@ -82,23 +82,9 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
/* repack the options */
bool smooth_checkpoint = bkupopt.smooth_checkpoint;
/*
* In archive backup mode, check if there is an already validated
* full backup on current timeline.
*/
/* Leave in case od archive mode */
if (current.backup_mode == BACKUP_MODE_ARCHIVE)
{
pgBackup *prev_backup;
prev_backup = catalog_get_last_data_backup(backup_list);
if (prev_backup == NULL)
{
elog(ERROR_SYSTEM, _("Full backup detected but it is not "
"validated so archive backup cannot be taken. "
"backup. Validate it and retry."));
}
return NULL;
}
elog(INFO, _("database backup start"));
@ -113,6 +99,21 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
*/
current.tli = get_current_timeline();
/*
* In incremental backup mode, check if there is an already-validated
* full backup on current timeline.
*/
if (current.backup_mode == BACKUP_MODE_INCREMENTAL)
{
pgBackup *prev_backup;
prev_backup = catalog_get_last_data_backup(backup_list, current.tli);
if (prev_backup == NULL)
elog(ERROR_SYSTEM, _("Valid full backup not found for "
"incremental backup. Either create a full backup "
"or validate existing one."));
}
/* notify start of backup to PostgreSQL server */
time2iso(label, lengthof(label), current.start_time);
strncat(label, " with pg_rman", lengthof(label));
@ -167,30 +168,22 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
* To take incremental backup, the file list of the last completed database
* backup is needed.
*/
if (current.backup_mode < BACKUP_MODE_FULL)
if (current.backup_mode == BACKUP_MODE_INCREMENTAL)
{
pgBackup *prev_backup;
/* find last completed database backup */
prev_backup = catalog_get_last_data_backup(backup_list);
if (prev_backup == NULL || prev_backup->tli != current.tli)
{
elog(ERROR_SYSTEM, _("Full backup detected but it is not "
"validated so incremental backup cannot be taken"));
}
else
{
pgBackupGetPath(prev_backup, prev_file_txt, lengthof(prev_file_txt),
DATABASE_FILE_LIST);
prev_files = dir_read_file_list(pgdata, prev_file_txt);
prev_backup = catalog_get_last_data_backup(backup_list, current.tli);
pgBackupGetPath(prev_backup, prev_file_txt, lengthof(prev_file_txt),
DATABASE_FILE_LIST);
prev_files = dir_read_file_list(pgdata, prev_file_txt);
/*
* Do backup only pages having larger LSN than previous backup.
*/
lsn = &prev_backup->start_lsn;
elog(LOG, _("backup only the page that there was of the update from LSN(%X/%08X).\n"),
(uint32) (*lsn >> 32), (uint32) *lsn);
}
/*
* Do backup only pages having larger LSN than previous backup.
*/
lsn = &prev_backup->start_lsn;
elog(LOG, _("backup only the page that there was of the update from LSN(%X/%08X).\n"),
(uint32) (*lsn >> 32), (uint32) *lsn);
}
/* initialize backup list from non-snapshot */
@ -455,15 +448,28 @@ do_backup_arclog(parray *backup_list)
/* initialize size summary */
current.read_arclog_bytes = 0;
/* switch xlog if database is not backed up */
/*
* Switch xlog if database is not backed up, current timeline of
* server is obtained here.
*/
if ((uint32) current.stop_lsn == 0)
pg_switch_xlog(&current);
/*
* Check if there is a full backup present on current timeline.
* For an incremental or full backup, we are sure that there is one
* so this error can be bypassed safely.
*/
if (current.backup_mode == BACKUP_MODE_ARCHIVE &&
catalog_get_last_data_backup(backup_list, current.tli) == NULL)
elog(ERROR_SYSTEM, _("No valid full or incremental backup detected "
"on current timeline "));
/*
* To take incremental backup, the file list of the last completed
* database backup is needed.
*/
prev_backup = catalog_get_last_arclog_backup(backup_list);
prev_backup = catalog_get_last_arclog_backup(backup_list, current.tli);
if (verbose && prev_backup == NULL)
printf(_("no previous full backup, performing a full backup instead\n"));
@ -587,7 +593,8 @@ do_backup_srvlog(parray *backup_list)
* To take incremental backup, the file list of the last completed database
* backup is needed.
*/
prev_backup = catalog_get_last_srvlog_backup(backup_list);
prev_backup = catalog_get_last_srvlog_backup(backup_list,
get_current_timeline());
if (verbose && prev_backup == NULL)
printf(_("no previous full backup, performing a full backup instead\n"));

View File

@ -244,7 +244,7 @@ err_proc:
* Find the last completed database backup from the backup list.
*/
pgBackup *
catalog_get_last_data_backup(parray *backup_list)
catalog_get_last_data_backup(parray *backup_list, TimeLineID tli)
{
int i;
pgBackup *backup = NULL;
@ -256,9 +256,10 @@ catalog_get_last_data_backup(parray *backup_list)
/*
* We need completed database backup in the case of a full or
* incremental backup.
* incremental backup on current timeline.
*/
if (backup->status == BACKUP_STATUS_OK &&
backup->tli == tli &&
(backup->backup_mode == BACKUP_MODE_INCREMENTAL ||
backup->backup_mode == BACKUP_MODE_FULL))
return backup;
@ -268,10 +269,11 @@ catalog_get_last_data_backup(parray *backup_list)
}
/*
* Find the last completed archived WAL backup from the backup list.
* Find the last completed archived WAL backup from the backup list
* on current timeline.
*/
pgBackup *
catalog_get_last_arclog_backup(parray *backup_list)
catalog_get_last_arclog_backup(parray *backup_list, TimeLineID tli)
{
int i;
pgBackup *backup = NULL;
@ -282,7 +284,8 @@ catalog_get_last_arclog_backup(parray *backup_list)
backup = (pgBackup *) parray_get(backup_list, i);
/* we need completed archived WAL backup */
if (backup->status == BACKUP_STATUS_OK)
if (backup->status == BACKUP_STATUS_OK &&
backup->tli == tli)
return backup;
}
@ -290,10 +293,11 @@ catalog_get_last_arclog_backup(parray *backup_list)
}
/*
* Find the last completed serverlog backup from the backup list.
* Find the last completed serverlog backup from the backup list
* on current timeline.
*/
pgBackup *
catalog_get_last_srvlog_backup(parray *backup_list)
catalog_get_last_srvlog_backup(parray *backup_list, TimeLineID tli)
{
int i;
pgBackup *backup = NULL;
@ -304,7 +308,9 @@ catalog_get_last_srvlog_backup(parray *backup_list)
backup = (pgBackup *) parray_get(backup_list, i);
/* we need completed serverlog backup */
if (backup->status == BACKUP_STATUS_OK && backup->with_serverlog)
if (backup->status == BACKUP_STATUS_OK &&
backup->with_serverlog &&
backup->tli == tli)
return backup;
}

View File

@ -265,9 +265,12 @@ extern void pgBackupValidate(pgBackup *backup,
/* in catalog.c */
extern pgBackup *catalog_get_backup(time_t timestamp);
extern parray *catalog_get_backup_list(const pgBackupRange *range);
extern pgBackup *catalog_get_last_data_backup(parray *backup_list);
extern pgBackup *catalog_get_last_arclog_backup(parray *backup_list);
extern pgBackup *catalog_get_last_srvlog_backup(parray *backup_list);
extern pgBackup *catalog_get_last_data_backup(parray *backup_list,
TimeLineID tli);
extern pgBackup *catalog_get_last_arclog_backup(parray *backup_list,
TimeLineID tli);
extern pgBackup *catalog_get_last_srvlog_backup(parray *backup_list,
TimeLineID tli);
extern int catalog_lock(void);
extern void catalog_unlock(void);