mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-03-03 15:42:18 +02:00
PGPRO-2589: use parent_link instead of start-time sorting in merge, validate and restore
This commit is contained in:
parent
068218c544
commit
b2cb9cf940
@ -393,7 +393,7 @@ catalog_get_backup_list(time_t requested_backup_id)
|
||||
if (curr->backup_mode == BACKUP_MODE_FULL)
|
||||
continue;
|
||||
|
||||
for (j = i+1; j < parray_num(backups); j++)
|
||||
for (j = 0; j < parray_num(backups); j++)
|
||||
{
|
||||
pgBackup *ancestor = parray_get(backups, j);
|
||||
|
||||
@ -1034,8 +1034,12 @@ find_parent_full_backup(pgBackup *current_backup)
|
||||
}
|
||||
|
||||
if (base_full_backup->backup_mode != BACKUP_MODE_FULL)
|
||||
elog(ERROR, "Failed to find FULL backup parent for %s",
|
||||
base36enc(current_backup->start_time));
|
||||
{
|
||||
|
||||
elog(WARNING, "Backup %s is missing",
|
||||
base36enc(base_full_backup->parent_backup));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return base_full_backup;
|
||||
}
|
||||
|
85
src/merge.c
85
src/merge.c
@ -53,12 +53,10 @@ void
|
||||
do_merge(time_t backup_id)
|
||||
{
|
||||
parray *backups;
|
||||
parray *merge_list = parray_new();
|
||||
pgBackup *dest_backup = NULL;
|
||||
pgBackup *full_backup = NULL;
|
||||
time_t prev_parent = INVALID_BACKUP_ID;
|
||||
int i;
|
||||
int dest_backup_idx = 0;
|
||||
int full_backup_idx = 0;
|
||||
|
||||
if (backup_id == INVALID_BACKUP_ID)
|
||||
elog(ERROR, "required parameter is not specified: --backup-id");
|
||||
@ -71,73 +69,79 @@ do_merge(time_t backup_id)
|
||||
/* Get list of all backups sorted in order of descending start time */
|
||||
backups = catalog_get_backup_list(INVALID_BACKUP_ID);
|
||||
|
||||
/* Find destination and parent backups */
|
||||
/* Find destination backup first */
|
||||
for (i = 0; i < parray_num(backups); i++)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *) parray_get(backups, i);
|
||||
|
||||
if (backup->start_time > backup_id)
|
||||
continue;
|
||||
else if (backup->start_time == backup_id && !dest_backup)
|
||||
/* found target */
|
||||
if (backup->start_time == backup_id)
|
||||
{
|
||||
/* sanity */
|
||||
if (backup->status != BACKUP_STATUS_OK &&
|
||||
/* It is possible that previous merging was interrupted */
|
||||
backup->status != BACKUP_STATUS_MERGING &&
|
||||
backup->status != BACKUP_STATUS_DELETING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(backup->start_time), status2str(backup->status));
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(backup->start_time), status2str(backup->status));
|
||||
|
||||
if (backup->backup_mode == BACKUP_MODE_FULL)
|
||||
elog(ERROR, "Backup %s is full backup",
|
||||
base36enc(backup->start_time));
|
||||
|
||||
dest_backup = backup;
|
||||
dest_backup_idx = i;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_backup == NULL)
|
||||
elog(ERROR, "Target backup %s was not found", base36enc(backup_id));
|
||||
|
||||
if (backup->start_time != prev_parent)
|
||||
continue;
|
||||
|
||||
if (backup->status != BACKUP_STATUS_OK &&
|
||||
/* It is possible that previous merging was interrupted */
|
||||
backup->status != BACKUP_STATUS_MERGING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(backup->start_time), status2str(backup->status));
|
||||
|
||||
/* If we already found dest_backup, look for full backup */
|
||||
if (dest_backup && backup->backup_mode == BACKUP_MODE_FULL)
|
||||
{
|
||||
full_backup = backup;
|
||||
full_backup_idx = i;
|
||||
|
||||
/* Found target and full backups, so break the loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prev_parent = backup->parent_backup;
|
||||
}
|
||||
|
||||
/* sanity */
|
||||
if (dest_backup == NULL)
|
||||
elog(ERROR, "Target backup %s was not found", base36enc(backup_id));
|
||||
|
||||
/* get full backup */
|
||||
full_backup = find_parent_full_backup(dest_backup);
|
||||
|
||||
/* sanity */
|
||||
if (full_backup == NULL)
|
||||
elog(ERROR, "Parent full backup for the given backup %s was not found",
|
||||
base36enc(backup_id));
|
||||
|
||||
Assert(full_backup_idx != dest_backup_idx);
|
||||
/* sanity */
|
||||
if (full_backup->status != BACKUP_STATUS_OK &&
|
||||
/* It is possible that previous merging was interrupted */
|
||||
full_backup->status != BACKUP_STATUS_MERGING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(full_backup->start_time), status2str(full_backup->status));
|
||||
|
||||
catalog_lock_backup_list(backups, full_backup_idx, dest_backup_idx);
|
||||
//Assert(full_backup_idx != dest_backup_idx);
|
||||
|
||||
/* form merge list */
|
||||
while(dest_backup->parent_backup_link)
|
||||
{
|
||||
/* sanity */
|
||||
if (dest_backup->status != BACKUP_STATUS_OK &&
|
||||
/* It is possible that previous merging was interrupted */
|
||||
dest_backup->status != BACKUP_STATUS_MERGING &&
|
||||
dest_backup->status != BACKUP_STATUS_DELETING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(dest_backup->start_time), status2str(dest_backup->status));
|
||||
|
||||
parray_append(merge_list, dest_backup);
|
||||
dest_backup = dest_backup->parent_backup_link;
|
||||
}
|
||||
|
||||
/* Add FULL backup for easy locking */
|
||||
parray_append(merge_list, full_backup);
|
||||
|
||||
/* Lock merge chain */
|
||||
catalog_lock_backup_list(merge_list, parray_num(merge_list) - 1, 0);
|
||||
|
||||
/*
|
||||
* Found target and full backups, merge them and intermediate backups
|
||||
*/
|
||||
for (i = full_backup_idx; i > dest_backup_idx; i--)
|
||||
for (i = parray_num(merge_list) - 2; i >= 0; i--)
|
||||
{
|
||||
pgBackup *from_backup = (pgBackup *) parray_get(backups, i - 1);
|
||||
pgBackup *from_backup = (pgBackup *) parray_get(merge_list, i);
|
||||
|
||||
merge_backups(full_backup, from_backup);
|
||||
}
|
||||
@ -149,6 +153,7 @@ do_merge(time_t backup_id)
|
||||
/* cleanup */
|
||||
parray_walk(backups, pgBackupFree);
|
||||
parray_free(backups);
|
||||
parray_free(merge_list);
|
||||
|
||||
elog(INFO, "Merge of backup %s completed", base36enc(backup_id));
|
||||
}
|
||||
|
@ -55,9 +55,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
pgBackup *dest_backup = NULL;
|
||||
pgBackup *base_full_backup = NULL;
|
||||
pgBackup *corrupted_backup = NULL;
|
||||
int dest_backup_index = 0;
|
||||
int base_full_backup_index = 0;
|
||||
int corrupted_backup_index = 0;
|
||||
char *action = is_restore ? "Restore":"Validate";
|
||||
parray *parent_chain = NULL;
|
||||
|
||||
@ -179,8 +176,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
if (dest_backup == NULL)
|
||||
elog(ERROR, "Backup satisfying target options is not found.");
|
||||
|
||||
dest_backup_index = get_backup_index_number(backups, dest_backup);
|
||||
|
||||
/* If we already found dest_backup, look for full backup. */
|
||||
if (dest_backup->backup_mode == BACKUP_MODE_FULL)
|
||||
base_full_backup = dest_backup;
|
||||
@ -201,7 +196,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
missing_backup_start_time = tmp_backup->parent_backup;
|
||||
missing_backup_id = base36enc_dup(tmp_backup->parent_backup);
|
||||
|
||||
for (j = get_backup_index_number(backups, tmp_backup); j >= 0; j--)
|
||||
for (j = 0; j < parray_num(backups); j++)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *) parray_get(backups, j);
|
||||
|
||||
@ -235,7 +230,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
/* parent_backup_id contain human-readable backup ID of oldest invalid backup */
|
||||
parent_backup_id = base36enc_dup(tmp_backup->start_time);
|
||||
|
||||
for (j = get_backup_index_number(backups, tmp_backup) - 1; j >= 0; j--)
|
||||
for (j = 0; j < parray_num(backups); j++)
|
||||
{
|
||||
|
||||
pgBackup *backup = (pgBackup *) parray_get(backups, j);
|
||||
@ -261,6 +256,11 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
}
|
||||
}
|
||||
tmp_backup = find_parent_full_backup(dest_backup);
|
||||
|
||||
/* sanity */
|
||||
if (!tmp_backup)
|
||||
elog(ERROR, "Parent full backup for the given backup %s was not found",
|
||||
base36enc(dest_backup->start_time));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -276,8 +276,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
if (base_full_backup == NULL)
|
||||
elog(ERROR, "Full backup satisfying target options is not found.");
|
||||
|
||||
base_full_backup_index = get_backup_index_number(backups, base_full_backup);
|
||||
|
||||
/*
|
||||
* Ensure that directories provided in tablespace mapping are valid
|
||||
* i.e. empty or not exist.
|
||||
@ -297,17 +295,16 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
/* Take every backup that is a child of base_backup AND parent of dest_backup
|
||||
* including base_backup and dest_backup
|
||||
*/
|
||||
for (i = base_full_backup_index; i >= dest_backup_index; i--)
|
||||
{
|
||||
tmp_backup = (pgBackup *) parray_get(backups, i);
|
||||
|
||||
if (is_parent(base_full_backup->start_time, tmp_backup, true) &&
|
||||
is_parent(tmp_backup->start_time, dest_backup, true))
|
||||
{
|
||||
parray_append(parent_chain, tmp_backup);
|
||||
}
|
||||
tmp_backup = dest_backup;
|
||||
while(tmp_backup->parent_backup_link)
|
||||
{
|
||||
parray_append(parent_chain, tmp_backup);
|
||||
tmp_backup = tmp_backup->parent_backup_link;
|
||||
}
|
||||
|
||||
parray_append(parent_chain, base_full_backup);
|
||||
|
||||
/* for validation or restore with enabled validation */
|
||||
if (!is_restore || !rt->restore_no_validate)
|
||||
{
|
||||
@ -317,7 +314,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
/*
|
||||
* Validate backups from base_full_backup to dest_backup.
|
||||
*/
|
||||
for (i = 0; i < parray_num(parent_chain); i++)
|
||||
for (i = parray_num(parent_chain) - 1; i >= 0; i--)
|
||||
{
|
||||
tmp_backup = (pgBackup *) parray_get(parent_chain, i);
|
||||
|
||||
@ -344,10 +341,6 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
if (tmp_backup->status != BACKUP_STATUS_OK)
|
||||
{
|
||||
corrupted_backup = tmp_backup;
|
||||
/* we need corrupted backup index from 'backups' not parent_chain
|
||||
* so we can properly orphanize all its descendants
|
||||
*/
|
||||
corrupted_backup_index = get_backup_index_number(backups, corrupted_backup);
|
||||
break;
|
||||
}
|
||||
/* We do not validate WAL files of intermediate backups
|
||||
@ -373,7 +366,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
char *corrupted_backup_id;
|
||||
corrupted_backup_id = base36enc_dup(corrupted_backup->start_time);
|
||||
|
||||
for (j = corrupted_backup_index - 1; j >= 0; j--)
|
||||
for (j = 0; j < parray_num(backups); j++)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *) parray_get(backups, j);
|
||||
|
||||
@ -418,7 +411,7 @@ do_restore_or_validate(time_t target_backup_id, pgRecoveryTarget *rt,
|
||||
*/
|
||||
if (is_restore)
|
||||
{
|
||||
for (i = 0; i < parray_num(parent_chain); i++)
|
||||
for (i = parray_num(parent_chain) - 1; i >= 0; i--)
|
||||
{
|
||||
pgBackup *backup = (pgBackup *) parray_get(parent_chain, i);
|
||||
|
||||
|
@ -452,6 +452,11 @@ do_validate_instance(void)
|
||||
continue;
|
||||
}
|
||||
base_full_backup = find_parent_full_backup(current_backup);
|
||||
|
||||
/* sanity */
|
||||
if (!base_full_backup)
|
||||
elog(ERROR, "Parent full backup for the given backup %s was not found",
|
||||
base36enc(current_backup->start_time));
|
||||
}
|
||||
/* chain is whole, all parents are valid at first glance,
|
||||
* current backup validation can proceed
|
||||
@ -568,7 +573,7 @@ do_validate_instance(void)
|
||||
|
||||
if (backup->status == BACKUP_STATUS_OK)
|
||||
{
|
||||
//tmp_backup = find_parent_full_backup(dest_backup);
|
||||
|
||||
/* Revalidation successful, validate corresponding WAL files */
|
||||
validate_wal(backup, arclog_path, 0,
|
||||
0, 0, current_backup->tli,
|
||||
|
Loading…
x
Reference in New Issue
Block a user