Skip to content

Commit 1bc1f1d

Browse files
author
Michael Paquier
committed
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...
1 parent 26b8870 commit 1bc1f1d

File tree

3 files changed

+64
-48
lines changed

3 files changed

+64
-48
lines changed

backup.c

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,9 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
8282
/* repack the options */
8383
bool smooth_checkpoint = bkupopt.smooth_checkpoint;
8484

85-
/*
86-
* In archive backup mode, check if there is an already validated
87-
* full backup on current timeline.
88-
*/
85+
/* Leave in case od archive mode */
8986
if (current.backup_mode == BACKUP_MODE_ARCHIVE)
90-
{
91-
pgBackup *prev_backup;
92-
93-
prev_backup = catalog_get_last_data_backup(backup_list);
94-
if (prev_backup == NULL)
95-
{
96-
elog(ERROR_SYSTEM, _("Full backup detected but it is not "
97-
"validated so archive backup cannot be taken. "
98-
"backup. Validate it and retry."));
99-
}
10087
return NULL;
101-
}
10288

10389
elog(INFO, _("database backup start"));
10490

@@ -113,6 +99,21 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
11399
*/
114100
current.tli = get_current_timeline();
115101

102+
/*
103+
* In incremental backup mode, check if there is an already-validated
104+
* full backup on current timeline.
105+
*/
106+
if (current.backup_mode == BACKUP_MODE_INCREMENTAL)
107+
{
108+
pgBackup *prev_backup;
109+
110+
prev_backup = catalog_get_last_data_backup(backup_list, current.tli);
111+
if (prev_backup == NULL)
112+
elog(ERROR_SYSTEM, _("Valid full backup not found for "
113+
"incremental backup. Either create a full backup "
114+
"or validate existing one."));
115+
}
116+
116117
/* notify start of backup to PostgreSQL server */
117118
time2iso(label, lengthof(label), current.start_time);
118119
strncat(label, " with pg_rman", lengthof(label));
@@ -167,30 +168,22 @@ do_backup_database(parray *backup_list, pgBackupOption bkupopt)
167168
* To take incremental backup, the file list of the last completed database
168169
* backup is needed.
169170
*/
170-
if (current.backup_mode < BACKUP_MODE_FULL)
171+
if (current.backup_mode == BACKUP_MODE_INCREMENTAL)
171172
{
172173
pgBackup *prev_backup;
173174

174175
/* find last completed database backup */
175-
prev_backup = catalog_get_last_data_backup(backup_list);
176-
if (prev_backup == NULL || prev_backup->tli != current.tli)
177-
{
178-
elog(ERROR_SYSTEM, _("Full backup detected but it is not "
179-
"validated so incremental backup cannot be taken"));
180-
}
181-
else
182-
{
183-
pgBackupGetPath(prev_backup, prev_file_txt, lengthof(prev_file_txt),
184-
DATABASE_FILE_LIST);
185-
prev_files = dir_read_file_list(pgdata, prev_file_txt);
176+
prev_backup = catalog_get_last_data_backup(backup_list, current.tli);
177+
pgBackupGetPath(prev_backup, prev_file_txt, lengthof(prev_file_txt),
178+
DATABASE_FILE_LIST);
179+
prev_files = dir_read_file_list(pgdata, prev_file_txt);
186180

187-
/*
188-
* Do backup only pages having larger LSN than previous backup.
189-
*/
190-
lsn = &prev_backup->start_lsn;
191-
elog(LOG, _("backup only the page that there was of the update from LSN(%X/%08X).\n"),
192-
(uint32) (*lsn >> 32), (uint32) *lsn);
193-
}
181+
/*
182+
* Do backup only pages having larger LSN than previous backup.
183+
*/
184+
lsn = &prev_backup->start_lsn;
185+
elog(LOG, _("backup only the page that there was of the update from LSN(%X/%08X).\n"),
186+
(uint32) (*lsn >> 32), (uint32) *lsn);
194187
}
195188

196189
/* initialize backup list from non-snapshot */
@@ -455,15 +448,28 @@ do_backup_arclog(parray *backup_list)
455448
/* initialize size summary */
456449
current.read_arclog_bytes = 0;
457450

458-
/* switch xlog if database is not backed up */
451+
/*
452+
* Switch xlog if database is not backed up, current timeline of
453+
* server is obtained here.
454+
*/
459455
if ((uint32) current.stop_lsn == 0)
460456
pg_switch_xlog(&current);
461457

458+
/*
459+
* Check if there is a full backup present on current timeline.
460+
* For an incremental or full backup, we are sure that there is one
461+
* so this error can be bypassed safely.
462+
*/
463+
if (current.backup_mode == BACKUP_MODE_ARCHIVE &&
464+
catalog_get_last_data_backup(backup_list, current.tli) == NULL)
465+
elog(ERROR_SYSTEM, _("No valid full or incremental backup detected "
466+
"on current timeline "));
467+
462468
/*
463469
* To take incremental backup, the file list of the last completed
464470
* database backup is needed.
465471
*/
466-
prev_backup = catalog_get_last_arclog_backup(backup_list);
472+
prev_backup = catalog_get_last_arclog_backup(backup_list, current.tli);
467473
if (verbose && prev_backup == NULL)
468474
printf(_("no previous full backup, performing a full backup instead\n"));
469475

@@ -587,7 +593,8 @@ do_backup_srvlog(parray *backup_list)
587593
* To take incremental backup, the file list of the last completed database
588594
* backup is needed.
589595
*/
590-
prev_backup = catalog_get_last_srvlog_backup(backup_list);
596+
prev_backup = catalog_get_last_srvlog_backup(backup_list,
597+
get_current_timeline());
591598
if (verbose && prev_backup == NULL)
592599
printf(_("no previous full backup, performing a full backup instead\n"));
593600

catalog.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ catalog_get_backup_list(const pgBackupRange *range)
244244
* Find the last completed database backup from the backup list.
245245
*/
246246
pgBackup *
247-
catalog_get_last_data_backup(parray *backup_list)
247+
catalog_get_last_data_backup(parray *backup_list, TimeLineID tli)
248248
{
249249
int i;
250250
pgBackup *backup = NULL;
@@ -256,9 +256,10 @@ catalog_get_last_data_backup(parray *backup_list)
256256

257257
/*
258258
* We need completed database backup in the case of a full or
259-
* incremental backup.
259+
* incremental backup on current timeline.
260260
*/
261261
if (backup->status == BACKUP_STATUS_OK &&
262+
backup->tli == tli &&
262263
(backup->backup_mode == BACKUP_MODE_INCREMENTAL ||
263264
backup->backup_mode == BACKUP_MODE_FULL))
264265
return backup;
@@ -268,10 +269,11 @@ catalog_get_last_data_backup(parray *backup_list)
268269
}
269270

270271
/*
271-
* Find the last completed archived WAL backup from the backup list.
272+
* Find the last completed archived WAL backup from the backup list
273+
* on current timeline.
272274
*/
273275
pgBackup *
274-
catalog_get_last_arclog_backup(parray *backup_list)
276+
catalog_get_last_arclog_backup(parray *backup_list, TimeLineID tli)
275277
{
276278
int i;
277279
pgBackup *backup = NULL;
@@ -282,18 +284,20 @@ catalog_get_last_arclog_backup(parray *backup_list)
282284
backup = (pgBackup *) parray_get(backup_list, i);
283285

284286
/* we need completed archived WAL backup */
285-
if (backup->status == BACKUP_STATUS_OK)
287+
if (backup->status == BACKUP_STATUS_OK &&
288+
backup->tli == tli)
286289
return backup;
287290
}
288291

289292
return NULL;
290293
}
291294

292295
/*
293-
* Find the last completed serverlog backup from the backup list.
296+
* Find the last completed serverlog backup from the backup list
297+
* on current timeline.
294298
*/
295299
pgBackup *
296-
catalog_get_last_srvlog_backup(parray *backup_list)
300+
catalog_get_last_srvlog_backup(parray *backup_list, TimeLineID tli)
297301
{
298302
int i;
299303
pgBackup *backup = NULL;
@@ -304,7 +308,9 @@ catalog_get_last_srvlog_backup(parray *backup_list)
304308
backup = (pgBackup *) parray_get(backup_list, i);
305309

306310
/* we need completed serverlog backup */
307-
if (backup->status == BACKUP_STATUS_OK && backup->with_serverlog)
311+
if (backup->status == BACKUP_STATUS_OK &&
312+
backup->with_serverlog &&
313+
backup->tli == tli)
308314
return backup;
309315
}
310316

pg_rman.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,12 @@ extern void pgBackupValidate(pgBackup *backup,
265265
/* in catalog.c */
266266
extern pgBackup *catalog_get_backup(time_t timestamp);
267267
extern parray *catalog_get_backup_list(const pgBackupRange *range);
268-
extern pgBackup *catalog_get_last_data_backup(parray *backup_list);
269-
extern pgBackup *catalog_get_last_arclog_backup(parray *backup_list);
270-
extern pgBackup *catalog_get_last_srvlog_backup(parray *backup_list);
268+
extern pgBackup *catalog_get_last_data_backup(parray *backup_list,
269+
TimeLineID tli);
270+
extern pgBackup *catalog_get_last_arclog_backup(parray *backup_list,
271+
TimeLineID tli);
272+
extern pgBackup *catalog_get_last_srvlog_backup(parray *backup_list,
273+
TimeLineID tli);
271274

272275
extern int catalog_lock(void);
273276
extern void catalog_unlock(void);

0 commit comments

Comments
 (0)