1
0
mirror of https://github.com/postgrespro/pg_probackup.git synced 2024-11-24 08:52:38 +02:00

Rewrite delete backup logic.

This commit is contained in:
stalkerg 2016-11-09 17:29:48 +03:00
parent ed3e7a5551
commit c1f1627c0b
8 changed files with 73 additions and 68 deletions

View File

@ -18,11 +18,12 @@ int
do_delete(time_t backup_id)
{
int i;
int b_index;
int ret;
parray *backup_list;
bool do_delete = false;
XLogRecPtr oldest_lsn = InvalidXLogRecPtr;
TimeLineID oldest_tli;
pgBackup *last_backup;
/* DATE are always required */
if (backup_id == 0)
@ -41,31 +42,38 @@ do_delete(time_t backup_id)
if (!backup_list)
elog(ERROR, "No backup list found, can't process any more.");
/* Find backups to be deleted */
/* Find backup to be deleted */
for (i = 0; i < parray_num(backup_list); i++)
{
last_backup = (pgBackup *) parray_get(backup_list, i);
if (last_backup->status == BACKUP_STATUS_OK &&
last_backup->start_time == backup_id
)
goto found_backup;
}
elog(ERROR, "no backup found, cannot delete.");
found_backup:
b_index = i;
/* check for interrupt */
if (interrupted)
elog(ERROR, "interrupted during delete backup");
/* just do it */
pgBackupDeleteFiles(last_backup);
/* remove all increments after removed backup */
for (i = b_index - 1; i >= 0; i--)
{
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
/* delete backup and update status to DELETED */
if (do_delete)
{
/* check for interrupt */
if (interrupted)
elog(ERROR, "interrupted during delete backup");
if (backup->backup_mode >= BACKUP_MODE_FULL)
break;
if (backup->status == BACKUP_STATUS_OK ||
backup->backup_mode == BACKUP_MODE_DIFF_PAGE ||
backup->backup_mode == BACKUP_MODE_DIFF_PTRACK
)
pgBackupDeleteFiles(backup);
continue;
}
/* Found the latest full backup */
if (backup->backup_mode >= BACKUP_MODE_FULL &&
backup->status == BACKUP_STATUS_OK &&
backup->start_time <= backup_id)
{
do_delete = true;
oldest_lsn = backup->start_lsn;
oldest_tli = backup->tli;
}
}
/* release catalog lock */
@ -74,13 +82,37 @@ do_delete(time_t backup_id)
/* cleanup */
parray_walk(backup_list, pgBackupFree);
parray_free(backup_list);
/*
* Delete in archive WAL segments that are not needed anymore. The oldest
* segment to be kept is the first segment that the oldest full backup
* found around needs to keep.
*/
if (!XLogRecPtrIsInvalid(oldest_lsn))
if (delete_wal)
{
/* Lock backup catalog */
ret = catalog_lock();
if (ret == -1)
elog(ERROR, "can't lock backup catalog.");
else if (ret == 1)
elog(ERROR,
"another pg_arman is running, stop delete.");
backup_list = catalog_get_backup_list(0);
for (i = 0; i < parray_num(backup_list); i++)
{
last_backup = (pgBackup *) parray_get(backup_list, i);
if (last_backup->status == BACKUP_STATUS_OK)
{
oldest_lsn = last_backup->start_lsn;
oldest_tli = last_backup->tli;
}
}
catalog_unlock();
parray_walk(backup_list, pgBackupFree);
parray_free(backup_list);
}
if (delete_wal && !XLogRecPtrIsInvalid(oldest_lsn))
{
XLogSegNo targetSegNo;
char oldestSegmentNeeded[MAXFNAMELEN];
@ -263,7 +295,8 @@ pgBackupDeleteFiles(pgBackup *backup)
time2iso(timestamp, lengthof(timestamp), backup->start_time);
elog(INFO, "delete: %s", timestamp);
elog(INFO, "delete: %s %s", base36enc(backup->start_time), timestamp);
/*
* Update STATUS to BACKUP_STATUS_DELETING in preparation for the case which
@ -277,7 +310,7 @@ pgBackupDeleteFiles(pgBackup *backup)
/* list files to be deleted */
files = parray_new();
pgBackupGetPath(backup, path, lengthof(path), DATABASE_DIR);
pgBackupGetPath(backup, path, lengthof(path), NULL);
dir_list_file(files, path, NULL, true, true);
/* delete leaf node first */
@ -304,16 +337,6 @@ pgBackupDeleteFiles(pgBackup *backup)
}
}
/*
* After deleting all of the backup files, update STATUS to
* BACKUP_STATUS_DELETED.
*/
if (!check)
{
backup->status = BACKUP_STATUS_DELETED;
pgBackupWriteIni(backup);
}
parray_walk(files, pgFileFree);
parray_free(files);

View File

@ -24,7 +24,7 @@ OK. Let's try to test --keep-data-generations=1.
9
0
Number of remaining full backups validated: 2
Number of deleted backups : 2
Number of deleted backups : 0
6
###### BACKUP COMMAND TEST-0005 ######
###### switch backup mode from page to full ######

View File

@ -3,11 +3,11 @@
###### delete full backups ######
try to delete the oldest backup
2
1
Number of deleted backups should be 1, is it so?: 1
0
Number of deleted backups should be 1, is it so?: 0
###### DELETE COMMAND TEST-0002 ######
###### keep backups which are necessary for recovery ######
try to delete before third backup
3
1
Number of deleted backups should be 1, is it so?: 1
0
Number of deleted backups should be 1, is it so?: 0

View File

@ -36,6 +36,9 @@ Restore options:
Catalog options:
-a, --show-all show deleted backup too
Delete options:
--wal remove unnecessary wal archives also
Connection options:
-d, --dbname=DBNAME database to connect
-h, --host=HOSTNAME database server host or socket directory

View File

@ -17,12 +17,3 @@ remove a file from backup intentionally
0
NG: CORRUPT status is not shown.
###### SHOW COMMAND TEST-0004 ######
###### Status DELETED ######
0
0
0
0
0
OK: DELETED status is shown properly.

View File

@ -39,6 +39,7 @@ bool stream_wal = false;
bool from_replica = false;
static bool backup_logs = false;
bool progress = false;
bool delete_wal = false;
/* restore configuration */
static char *target_time;
@ -76,6 +77,8 @@ static pgut_option options[] =
{ 'u', 6, "recovery-target-timeline", &target_tli, SOURCE_ENV },
/* catalog options */
{ 'b', 'a', "show-all", &show_all },
/* delete options */
{ 'b', 12, "wal", &delete_wal },
{ 0 }
};
@ -248,6 +251,8 @@ pgut_help(bool details)
printf(_(" --recovery-target-timeline recovering into a particular timeline\n"));
printf(_("\nCatalog options:\n"));
printf(_(" -a, --show-all show deleted backup too\n"));
printf(_("\nDelete options:\n"));
printf(_(" --wal remove unnecessary wal archives also\n"));
}
static void

View File

@ -204,6 +204,7 @@ extern int num_threads;
extern bool stream_wal;
extern bool from_replica;
extern bool progress;
extern bool delete_wal;
/* in backup.c */
extern int do_backup(pgBackupOption bkupopt);

View File

@ -65,24 +65,6 @@ else
fi
echo ''
echo '###### SHOW COMMAND TEST-0004 ######'
echo '###### Status DELETED ######'
init_catalog
pg_arman backup -B ${BACKUP_PATH} -b full -p ${TEST_PGPORT} -d postgres --quiet;echo $?
pg_arman validate -B ${BACKUP_PATH} --quiet > /dev/null 2>&1;echo $?
pg_arman backup -B ${BACKUP_PATH} -b full -p ${TEST_PGPORT} -d postgres --quiet;echo $?
DELETE_DATE=$(get_time_last_backup)
pg_arman validate -B ${BACKUP_PATH} --quiet > /dev/null 2>&1;echo $?
pg_arman delete ${DELETE_DATE} -B ${BACKUP_PATH} > /dev/null 2>&1;echo $?
pg_arman show -B ${BACKUP_PATH} > ${TEST_BASE}/TEST-0004-show.out 2>&1
pg_arman show -a -B ${BACKUP_PATH} > ${TEST_BASE}/TEST-0004-show-all.out 2>&1
if ! grep "DELETED" ${TEST_BASE}/TEST-0004-show.out > /dev/null && grep "DELETED" ${TEST_BASE}/TEST-0004-show-all.out > /dev/null ; then
echo 'OK: DELETED status is shown properly.'
else
echo 'NG: DELETED status is not shown.'
fi
echo ''
# clean up the temporal test data
pg_ctl stop -D ${PGDATA_PATH} -m immediate > /dev/null 2>&1
rm -fr ${PGDATA_PATH}