From a53c4c181d59c73775a4a77f7566ee1e9fea4b19 Mon Sep 17 00:00:00 2001 From: Grigory Smolkin Date: Wed, 24 Jan 2018 04:37:47 +0300 Subject: [PATCH] backup: allow to use delete-wal without delete-expired(in accordance with documentation) --- src/backup.c | 2 +- src/delete.c | 107 ++++++++++++++++++++++++++------------------- src/pg_probackup.c | 17 ++++--- 3 files changed, 74 insertions(+), 52 deletions(-) diff --git a/src/backup.c b/src/backup.c index 9faaf44e..c8ba46f3 100644 --- a/src/backup.c +++ b/src/backup.c @@ -855,7 +855,7 @@ do_backup(time_t start_time) * After successfil backup completion remove backups * which are expired according to retention policies */ - if (delete_expired) + if (delete_expired || delete_wal) do_retention_purge(); return 0; diff --git a/src/delete.c b/src/delete.c index d82c49c3..b7e04f21 100644 --- a/src/delete.c +++ b/src/delete.c @@ -134,15 +134,19 @@ do_retention_purge(void) bool keep_next_backup = true; /* Do not delete first full backup */ bool backup_deleted = false; /* At least one backup was deleted */ - if (retention_redundancy > 0) - elog(LOG, "REDUNDANCY=%u", retention_redundancy); - if (retention_window > 0) - elog(LOG, "WINDOW=%u", retention_window); - - if (retention_redundancy == 0 && retention_window == 0 && !delete_wal) + if (delete_expired) { - elog(WARNING, "Retention policy is not set"); - return 0; + if (retention_redundancy > 0) + elog(LOG, "REDUNDANCY=%u", retention_redundancy); + if (retention_window > 0) + elog(LOG, "WINDOW=%u", retention_window); + + if (retention_redundancy == 0 && retention_window == 0) + { + elog(WARNING, "Retention policy is not set"); + if (!delete_wal) + return 0; + } } /* Get exclusive lock of backup catalog */ @@ -157,52 +161,67 @@ do_retention_purge(void) } /* Find target backups to be deleted */ - backup_num = 0; - for (i = 0; i < parray_num(backup_list); i++) + if (delete_expired && (retention_redundancy > 0 || retention_window > 0)) { - pgBackup *backup = (pgBackup *) parray_get(backup_list, i); - uint32 backup_num_evaluate = backup_num; - - /* Consider only validated and correct backups */ - if (backup->status != BACKUP_STATUS_OK) - continue; - - /* - * When a validate full backup was found, we can delete the - * backup that is older than it using the number of generations. - */ - if (backup->backup_mode == BACKUP_MODE_FULL) - backup_num++; - - /* Evaluate if this backup is eligible for removal */ - if (keep_next_backup || - backup_num_evaluate + 1 <= retention_redundancy || - (retention_window > 0 && backup->recovery_time >= days_threshold)) + backup_num = 0; + for (i = 0; i < parray_num(backup_list); i++) { - /* Save LSN and Timeline to remove unnecessary WAL segments */ - oldest_lsn = backup->start_lsn; - oldest_tli = backup->tli; + pgBackup *backup = (pgBackup *) parray_get(backup_list, i); + uint32 backup_num_evaluate = backup_num; - /* Save parent backup of this incremental backup */ - if (backup->backup_mode != BACKUP_MODE_FULL) - keep_next_backup = true; + /* Consider only validated and correct backups */ + if (backup->status != BACKUP_STATUS_OK) + continue; /* - * Previous incremental backup was kept or this is first backup - * so do not delete this backup. + * When a validate full backup was found, we can delete the + * backup that is older than it using the number of generations. */ - else - keep_next_backup = false; + if (backup->backup_mode == BACKUP_MODE_FULL) + backup_num++; - continue; + /* Evaluateretention_redundancy if this backup is eligible for removal */ + if (keep_next_backup || + retention_redundancy >= backup_num_evaluate + 1 || + (retention_window > 0 && backup->recovery_time >= days_threshold)) + { + /* Save LSN and Timeline to remove unnecessary WAL segments */ + oldest_lsn = backup->start_lsn; + oldest_tli = backup->tli; + + /* Save parent backup of this incremental backup */ + if (backup->backup_mode != BACKUP_MODE_FULL) + keep_next_backup = true; + /* + * Previous incremental backup was kept or this is first backup + * so do not delete this backup. + */ + else + keep_next_backup = false; + + continue; + } + /* Delete backup and update status to DELETED */ + pgBackupDeleteFiles(backup); + backup_deleted = true; } + } - /* Delete backup and update status to DELETED */ - pgBackupDeleteFiles(backup); - backup_deleted = true; + /* + * If oldest_lsn wasn`t set in prevous step + * get oldest backup LSN and TLI for WAL purging + */ + if (delete_wal && (XLogRecPtrIsInvalid(oldest_lsn))) + { + pgBackup *backup = (pgBackup *) parray_get(backup_list, parray_num(backup_list) - 1); + oldest_lsn = backup->start_lsn; + oldest_tli = backup->tli; } /* Purge WAL files */ - delete_walfiles(oldest_lsn, oldest_tli); + if (delete_wal) + { + delete_walfiles(oldest_lsn, oldest_tli); + } /* Cleanup */ parray_walk(backup_list, pgBackupFree); @@ -257,7 +276,7 @@ pgBackupDeleteFiles(pgBackup *backup) pgFile *file = (pgFile *) parray_get(files, i); /* print progress */ - elog(LOG, "delete file(%zd/%lu) \"%s\"", i + 1, + elog(VERBOSE, "delete file(%zd/%lu) \"%s\"", i + 1, (unsigned long) parray_num(files), file->path); if (remove(file->path)) diff --git a/src/pg_probackup.c b/src/pg_probackup.c index 30473a6e..9b38a7c0 100644 --- a/src/pg_probackup.c +++ b/src/pg_probackup.c @@ -114,13 +114,14 @@ static pgut_option options[] = { 'f', 'b', "backup-mode", opt_backup_mode, SOURCE_CMDLINE }, { 'b', 'C', "smooth-checkpoint", &smooth_checkpoint, SOURCE_CMDLINE }, { 's', 'S', "slot", &replication_slot, SOURCE_CMDLINE }, - { 'u', 11, "archive-timeout", &archive_timeout, SOURCE_CMDLINE }, - { 'b', 12, "delete-expired", &delete_expired, SOURCE_CMDLINE }, - { 's', 13, "master-db", &master_db, SOURCE_CMDLINE, }, - { 's', 14, "master-host", &master_host, SOURCE_CMDLINE, }, - { 's', 15, "master-port", &master_port, SOURCE_CMDLINE, }, - { 's', 16, "master-user", &master_user, SOURCE_CMDLINE, }, - { 'u', 17, "replica-timeout", &replica_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S }, + { 'u', 11, "archive-timeout", &archive_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S }, + { 'b', 12, "delete-wal", &delete_wal, SOURCE_CMDLINE }, + { 'b', 13, "delete-expired", &delete_expired, SOURCE_CMDLINE }, + { 's', 14, "master-db", &master_db, SOURCE_CMDLINE, }, + { 's', 15, "master-host", &master_host, SOURCE_CMDLINE, }, + { 's', 16, "master-port", &master_port, SOURCE_CMDLINE, }, + { 's', 17, "master-user", &master_user, SOURCE_CMDLINE, }, + { 'u', 18, "replica-timeout", &replica_timeout, SOURCE_CMDLINE, SOURCE_DEFAULT, OPTION_UNIT_S }, /* TODO not completed feature. Make it unavailiable from user level { 'b', 18, "remote", &is_remote_backup, SOURCE_CMDLINE, }, */ /* restore options */ @@ -457,6 +458,8 @@ main(int argc, char *argv[]) elog(ERROR, "You cannot specify --delete-expired and --backup-id options together"); if (!delete_expired && !delete_wal && !backup_id_string_param) elog(ERROR, "You must specify at least one of the delete options: --expired |--wal |--backup_id"); + if (delete_wal && !delete_expired && !backup_id_string_param) + return do_retention_purge(); if (delete_expired) return do_retention_purge(); else