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:
parent
ed3e7a5551
commit
c1f1627c0b
95
delete.c
95
delete.c
@ -18,11 +18,12 @@ int
|
|||||||
do_delete(time_t backup_id)
|
do_delete(time_t backup_id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
int b_index;
|
||||||
int ret;
|
int ret;
|
||||||
parray *backup_list;
|
parray *backup_list;
|
||||||
bool do_delete = false;
|
|
||||||
XLogRecPtr oldest_lsn = InvalidXLogRecPtr;
|
XLogRecPtr oldest_lsn = InvalidXLogRecPtr;
|
||||||
TimeLineID oldest_tli;
|
TimeLineID oldest_tli;
|
||||||
|
pgBackup *last_backup;
|
||||||
|
|
||||||
/* DATE are always required */
|
/* DATE are always required */
|
||||||
if (backup_id == 0)
|
if (backup_id == 0)
|
||||||
@ -41,31 +42,38 @@ do_delete(time_t backup_id)
|
|||||||
if (!backup_list)
|
if (!backup_list)
|
||||||
elog(ERROR, "No backup list found, can't process any more.");
|
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++)
|
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);
|
pgBackup *backup = (pgBackup *) parray_get(backup_list, i);
|
||||||
|
if (backup->backup_mode >= BACKUP_MODE_FULL)
|
||||||
/* delete backup and update status to DELETED */
|
break;
|
||||||
if (do_delete)
|
if (backup->status == BACKUP_STATUS_OK ||
|
||||||
{
|
backup->backup_mode == BACKUP_MODE_DIFF_PAGE ||
|
||||||
/* check for interrupt */
|
backup->backup_mode == BACKUP_MODE_DIFF_PTRACK
|
||||||
if (interrupted)
|
)
|
||||||
elog(ERROR, "interrupted during delete backup");
|
|
||||||
|
|
||||||
pgBackupDeleteFiles(backup);
|
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 */
|
/* release catalog lock */
|
||||||
@ -74,13 +82,37 @@ do_delete(time_t backup_id)
|
|||||||
/* cleanup */
|
/* cleanup */
|
||||||
parray_walk(backup_list, pgBackupFree);
|
parray_walk(backup_list, pgBackupFree);
|
||||||
parray_free(backup_list);
|
parray_free(backup_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete in archive WAL segments that are not needed anymore. The oldest
|
* 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
|
* segment to be kept is the first segment that the oldest full backup
|
||||||
* found around needs to keep.
|
* 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;
|
XLogSegNo targetSegNo;
|
||||||
char oldestSegmentNeeded[MAXFNAMELEN];
|
char oldestSegmentNeeded[MAXFNAMELEN];
|
||||||
@ -263,7 +295,8 @@ pgBackupDeleteFiles(pgBackup *backup)
|
|||||||
|
|
||||||
time2iso(timestamp, lengthof(timestamp), backup->start_time);
|
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
|
* Update STATUS to BACKUP_STATUS_DELETING in preparation for the case which
|
||||||
@ -277,7 +310,7 @@ pgBackupDeleteFiles(pgBackup *backup)
|
|||||||
|
|
||||||
/* list files to be deleted */
|
/* list files to be deleted */
|
||||||
files = parray_new();
|
files = parray_new();
|
||||||
pgBackupGetPath(backup, path, lengthof(path), DATABASE_DIR);
|
pgBackupGetPath(backup, path, lengthof(path), NULL);
|
||||||
dir_list_file(files, path, NULL, true, true);
|
dir_list_file(files, path, NULL, true, true);
|
||||||
|
|
||||||
/* delete leaf node first */
|
/* 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_walk(files, pgFileFree);
|
||||||
parray_free(files);
|
parray_free(files);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ OK. Let's try to test --keep-data-generations=1.
|
|||||||
9
|
9
|
||||||
0
|
0
|
||||||
Number of remaining full backups validated: 2
|
Number of remaining full backups validated: 2
|
||||||
Number of deleted backups : 2
|
Number of deleted backups : 0
|
||||||
6
|
6
|
||||||
###### BACKUP COMMAND TEST-0005 ######
|
###### BACKUP COMMAND TEST-0005 ######
|
||||||
###### switch backup mode from page to full ######
|
###### switch backup mode from page to full ######
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
###### delete full backups ######
|
###### delete full backups ######
|
||||||
try to delete the oldest backup
|
try to delete the oldest backup
|
||||||
2
|
2
|
||||||
1
|
0
|
||||||
Number of deleted backups should be 1, is it so?: 1
|
Number of deleted backups should be 1, is it so?: 0
|
||||||
###### DELETE COMMAND TEST-0002 ######
|
###### DELETE COMMAND TEST-0002 ######
|
||||||
###### keep backups which are necessary for recovery ######
|
###### keep backups which are necessary for recovery ######
|
||||||
try to delete before third backup
|
try to delete before third backup
|
||||||
3
|
3
|
||||||
1
|
0
|
||||||
Number of deleted backups should be 1, is it so?: 1
|
Number of deleted backups should be 1, is it so?: 0
|
||||||
|
@ -36,6 +36,9 @@ Restore options:
|
|||||||
Catalog options:
|
Catalog options:
|
||||||
-a, --show-all show deleted backup too
|
-a, --show-all show deleted backup too
|
||||||
|
|
||||||
|
Delete options:
|
||||||
|
--wal remove unnecessary wal archives also
|
||||||
|
|
||||||
Connection options:
|
Connection options:
|
||||||
-d, --dbname=DBNAME database to connect
|
-d, --dbname=DBNAME database to connect
|
||||||
-h, --host=HOSTNAME database server host or socket directory
|
-h, --host=HOSTNAME database server host or socket directory
|
||||||
|
@ -17,12 +17,3 @@ remove a file from backup intentionally
|
|||||||
0
|
0
|
||||||
NG: CORRUPT status is not shown.
|
NG: CORRUPT status is not shown.
|
||||||
|
|
||||||
###### SHOW COMMAND TEST-0004 ######
|
|
||||||
###### Status DELETED ######
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
0
|
|
||||||
OK: DELETED status is shown properly.
|
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ bool stream_wal = false;
|
|||||||
bool from_replica = false;
|
bool from_replica = false;
|
||||||
static bool backup_logs = false;
|
static bool backup_logs = false;
|
||||||
bool progress = false;
|
bool progress = false;
|
||||||
|
bool delete_wal = false;
|
||||||
|
|
||||||
/* restore configuration */
|
/* restore configuration */
|
||||||
static char *target_time;
|
static char *target_time;
|
||||||
@ -76,6 +77,8 @@ static pgut_option options[] =
|
|||||||
{ 'u', 6, "recovery-target-timeline", &target_tli, SOURCE_ENV },
|
{ 'u', 6, "recovery-target-timeline", &target_tli, SOURCE_ENV },
|
||||||
/* catalog options */
|
/* catalog options */
|
||||||
{ 'b', 'a', "show-all", &show_all },
|
{ 'b', 'a', "show-all", &show_all },
|
||||||
|
/* delete options */
|
||||||
|
{ 'b', 12, "wal", &delete_wal },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -248,6 +251,8 @@ pgut_help(bool details)
|
|||||||
printf(_(" --recovery-target-timeline recovering into a particular timeline\n"));
|
printf(_(" --recovery-target-timeline recovering into a particular timeline\n"));
|
||||||
printf(_("\nCatalog options:\n"));
|
printf(_("\nCatalog options:\n"));
|
||||||
printf(_(" -a, --show-all show deleted backup too\n"));
|
printf(_(" -a, --show-all show deleted backup too\n"));
|
||||||
|
printf(_("\nDelete options:\n"));
|
||||||
|
printf(_(" --wal remove unnecessary wal archives also\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -204,6 +204,7 @@ extern int num_threads;
|
|||||||
extern bool stream_wal;
|
extern bool stream_wal;
|
||||||
extern bool from_replica;
|
extern bool from_replica;
|
||||||
extern bool progress;
|
extern bool progress;
|
||||||
|
extern bool delete_wal;
|
||||||
|
|
||||||
/* in backup.c */
|
/* in backup.c */
|
||||||
extern int do_backup(pgBackupOption bkupopt);
|
extern int do_backup(pgBackupOption bkupopt);
|
||||||
|
18
sql/show.sh
18
sql/show.sh
@ -65,24 +65,6 @@ else
|
|||||||
fi
|
fi
|
||||||
echo ''
|
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
|
# clean up the temporal test data
|
||||||
pg_ctl stop -D ${PGDATA_PATH} -m immediate > /dev/null 2>&1
|
pg_ctl stop -D ${PGDATA_PATH} -m immediate > /dev/null 2>&1
|
||||||
rm -fr ${PGDATA_PATH}
|
rm -fr ${PGDATA_PATH}
|
||||||
|
Loading…
Reference in New Issue
Block a user