Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4cff100

Browse files
committed
Fix parallel pg_restore to handle comments on POST_DATA items correctly.
The previous coding would try to process all SECTION_NONE items in the initial sequential-restore pass, which failed if they were dependencies of not-yet-restored items. Fix by postponing such items into the parallel processing pass once we have skipped any non-PRE_DATA item. Back-patch into 9.0; the original parallel-restore coding in 8.4 did not have this bug, so no need to change it. Report and diagnosis by Arnd Hannemann.
1 parent 472f608 commit 4cff100

File tree

1 file changed

+50
-15
lines changed

1 file changed

+50
-15
lines changed

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3218,12 +3218,12 @@ dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
32183218
* Main engine for parallel restore.
32193219
*
32203220
* Work is done in three phases.
3221-
* First we process tocEntries until we come to one that is marked
3222-
* SECTION_DATA or SECTION_POST_DATA, in a single connection, just as for a
3223-
* standard restore. Second we process the remaining non-ACL steps in
3224-
* parallel worker children (threads on Windows, processes on Unix), each of
3225-
* which connects separately to the database. Finally we process all the ACL
3226-
* entries in a single connection (that happens back in RestoreArchive).
3221+
* First we process all SECTION_PRE_DATA tocEntries, in a single connection,
3222+
* just as for a standard restore. Second we process the remaining non-ACL
3223+
* steps in parallel worker children (threads on Windows, processes on Unix),
3224+
* each of which connects separately to the database. Finally we process all
3225+
* the ACL entries in a single connection (that happens back in
3226+
* RestoreArchive).
32273227
*/
32283228
static void
32293229
restore_toc_entries_parallel(ArchiveHandle *AH)
@@ -3233,6 +3233,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
32333233
ParallelSlot *slots;
32343234
int work_status;
32353235
int next_slot;
3236+
bool skipped_some;
32363237
TocEntry pending_list;
32373238
TocEntry ready_list;
32383239
TocEntry *next_work_item;
@@ -3262,12 +3263,31 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
32623263
* showing all the dependencies of SECTION_PRE_DATA items, so we do not
32633264
* risk trying to process them out-of-order.
32643265
*/
3266+
skipped_some = false;
32653267
for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
32663268
{
3267-
/* Non-PRE_DATA items are just ignored for now */
3268-
if (next_work_item->section == SECTION_DATA ||
3269-
next_work_item->section == SECTION_POST_DATA)
3270-
continue;
3269+
/* NB: process-or-continue logic must be the inverse of loop below */
3270+
if (next_work_item->section != SECTION_PRE_DATA)
3271+
{
3272+
/* DATA and POST_DATA items are just ignored for now */
3273+
if (next_work_item->section == SECTION_DATA ||
3274+
next_work_item->section == SECTION_POST_DATA)
3275+
{
3276+
skipped_some = true;
3277+
continue;
3278+
}
3279+
else
3280+
{
3281+
/*
3282+
* SECTION_NONE items, such as comments, can be processed now
3283+
* if we are still in the PRE_DATA part of the archive. Once
3284+
* we've skipped any items, we have to consider whether the
3285+
* comment's dependencies are satisfied, so skip it for now.
3286+
*/
3287+
if (skipped_some)
3288+
continue;
3289+
}
3290+
}
32713291

32723292
ahlog(AH, 1, "processing item %d %s %s\n",
32733293
next_work_item->dumpId,
@@ -3310,17 +3330,32 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
33103330
*/
33113331
par_list_header_init(&pending_list);
33123332
par_list_header_init(&ready_list);
3333+
skipped_some = false;
33133334
for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
33143335
{
3315-
/* All PRE_DATA items were dealt with above */
3336+
/* NB: process-or-continue logic must be the inverse of loop above */
3337+
if (next_work_item->section == SECTION_PRE_DATA)
3338+
{
3339+
/* All PRE_DATA items were dealt with above */
3340+
continue;
3341+
}
33163342
if (next_work_item->section == SECTION_DATA ||
33173343
next_work_item->section == SECTION_POST_DATA)
33183344
{
3319-
if (next_work_item->depCount > 0)
3320-
par_list_append(&pending_list, next_work_item);
3321-
else
3322-
par_list_append(&ready_list, next_work_item);
3345+
/* set this flag at same point that previous loop did */
3346+
skipped_some = true;
33233347
}
3348+
else
3349+
{
3350+
/* SECTION_NONE items must be processed if previous loop didn't */
3351+
if (!skipped_some)
3352+
continue;
3353+
}
3354+
3355+
if (next_work_item->depCount > 0)
3356+
par_list_append(&pending_list, next_work_item);
3357+
else
3358+
par_list_append(&ready_list, next_work_item);
33243359
}
33253360

33263361
/*

0 commit comments

Comments
 (0)