Skip to content

Commit b22e2d6

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 848cd32 commit b22e2d6

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
@@ -3153,12 +3153,12 @@ dumpTimestamp(ArchiveHandle *AH, const char *msg, time_t tim)
31533153
* Main engine for parallel restore.
31543154
*
31553155
* Work is done in three phases.
3156-
* First we process tocEntries until we come to one that is marked
3157-
* SECTION_DATA or SECTION_POST_DATA, in a single connection, just as for a
3158-
* standard restore. Second we process the remaining non-ACL steps in
3159-
* parallel worker children (threads on Windows, processes on Unix), each of
3160-
* which connects separately to the database. Finally we process all the ACL
3161-
* entries in a single connection (that happens back in RestoreArchive).
3156+
* First we process all SECTION_PRE_DATA tocEntries, in a single connection,
3157+
* just as for a standard restore. Second we process the remaining non-ACL
3158+
* steps in parallel worker children (threads on Windows, processes on Unix),
3159+
* each of which connects separately to the database. Finally we process all
3160+
* the ACL entries in a single connection (that happens back in
3161+
* RestoreArchive).
31623162
*/
31633163
static void
31643164
restore_toc_entries_parallel(ArchiveHandle *AH)
@@ -3168,6 +3168,7 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
31683168
ParallelSlot *slots;
31693169
int work_status;
31703170
int next_slot;
3171+
bool skipped_some;
31713172
TocEntry pending_list;
31723173
TocEntry ready_list;
31733174
TocEntry *next_work_item;
@@ -3197,12 +3198,31 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
31973198
* showing all the dependencies of SECTION_PRE_DATA items, so we do not
31983199
* risk trying to process them out-of-order.
31993200
*/
3201+
skipped_some = false;
32003202
for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
32013203
{
3202-
/* Non-PRE_DATA items are just ignored for now */
3203-
if (next_work_item->section == SECTION_DATA ||
3204-
next_work_item->section == SECTION_POST_DATA)
3205-
continue;
3204+
/* NB: process-or-continue logic must be the inverse of loop below */
3205+
if (next_work_item->section != SECTION_PRE_DATA)
3206+
{
3207+
/* DATA and POST_DATA items are just ignored for now */
3208+
if (next_work_item->section == SECTION_DATA ||
3209+
next_work_item->section == SECTION_POST_DATA)
3210+
{
3211+
skipped_some = true;
3212+
continue;
3213+
}
3214+
else
3215+
{
3216+
/*
3217+
* SECTION_NONE items, such as comments, can be processed now
3218+
* if we are still in the PRE_DATA part of the archive. Once
3219+
* we've skipped any items, we have to consider whether the
3220+
* comment's dependencies are satisfied, so skip it for now.
3221+
*/
3222+
if (skipped_some)
3223+
continue;
3224+
}
3225+
}
32063226

32073227
ahlog(AH, 1, "processing item %d %s %s\n",
32083228
next_work_item->dumpId,
@@ -3245,17 +3265,32 @@ restore_toc_entries_parallel(ArchiveHandle *AH)
32453265
*/
32463266
par_list_header_init(&pending_list);
32473267
par_list_header_init(&ready_list);
3268+
skipped_some = false;
32483269
for (next_work_item = AH->toc->next; next_work_item != AH->toc; next_work_item = next_work_item->next)
32493270
{
3250-
/* All PRE_DATA items were dealt with above */
3271+
/* NB: process-or-continue logic must be the inverse of loop above */
3272+
if (next_work_item->section == SECTION_PRE_DATA)
3273+
{
3274+
/* All PRE_DATA items were dealt with above */
3275+
continue;
3276+
}
32513277
if (next_work_item->section == SECTION_DATA ||
32523278
next_work_item->section == SECTION_POST_DATA)
32533279
{
3254-
if (next_work_item->depCount > 0)
3255-
par_list_append(&pending_list, next_work_item);
3256-
else
3257-
par_list_append(&ready_list, next_work_item);
3280+
/* set this flag at same point that previous loop did */
3281+
skipped_some = true;
32583282
}
3283+
else
3284+
{
3285+
/* SECTION_NONE items must be processed if previous loop didn't */
3286+
if (!skipped_some)
3287+
continue;
3288+
}
3289+
3290+
if (next_work_item->depCount > 0)
3291+
par_list_append(&pending_list, next_work_item);
3292+
else
3293+
par_list_append(&ready_list, next_work_item);
32593294
}
32603295

32613296
/*

0 commit comments

Comments
 (0)