Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita1ef01f

Browse files
committed
Improve pg_dump's dependency-sorting logic to enforce section dump order.
As of 9.2, with the --section option, it is very important that the conceptof "pre data", "data", and "post data" sections of the output be honoredstrictly; else a dump divided into separate sectional files might beunrestorable. However, the dependency-sorting logic knew nothing ofsections and would happily select output orderings that didn't fit thatstructure. Doing so was mostly harmless before 9.2, but now we need to besure it doesn't do that. To fix, create dummy objects representing thesection boundaries and add dependencies between them and all the normalobjects. (This might sound expensive but it seems to only add a percent ortwo to pg_dump's runtime.)This also fixes a problem introduced in 9.1 by the feature that allowsincomplete GROUP BY lists when a primary key is given in GROUP BY.That means that views can depend on primary key constraints. Previously,pg_dump would deal with that by simply emitting the primary key constraintbefore the view definition (and hence before the data section of theoutput). That's bad enough for simple serial restores, where creating anindex before the data is loaded works, but is undesirable for speedreasons. But it could lead to outright failure of parallel restores, asseen in bug #6699 from Joe Van Dyk. That happened because pg_restore wouldswitch into parallel mode as soon as it reached the constraint, and thenvery possibly would try to emit the view definition before the primary keywas committed (as a consequence of another bug that causes the view not tobe correctly marked as depending on the constraint). Adding the sectionboundary constraints forces the dependency-sorting code to break the viewinto separate table and rule declarations, allowing the rule, and hence theprimary key constraint it depends on, to revert to their intended locationin the post-data section. This also somewhat accidentally works around thebogus-dependency-marking problem, because the rule will be correctly shownas depending on the constraint, so parallel pg_restore will now do theright thing. (We will fix the bogus-dependency problem for real in aseparate patch, but that patch is not easily back-portable to 9.1, so thefact that this patch is enough to dodge the only known symptom isfortunate.)Back-patch to 9.1, except for the hunk that adds verification that thefinished archive TOC list is in correct section order; the place whereit was convenient to add that doesn't exist in 9.1.
1 parent77ed0c6 commita1ef01f

File tree

4 files changed

+238
-30
lines changed

4 files changed

+238
-30
lines changed

‎src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,42 @@ SetArchiveRestoreOptions(Archive *AHX, RestoreOptions *ropt)
247247
curSection=SECTION_PRE_DATA;
248248
for (te=AH->toc->next;te!=AH->toc;te=te->next)
249249
{
250+
/*
251+
* When writing an archive, we also take this opportunity to check
252+
* that we have generated the entries in a sane order that respects
253+
* the section divisions. When reading, don't complain, since buggy
254+
* old versions of pg_dump might generate out-of-order archives.
255+
*/
256+
if (AH->mode!=archModeRead)
257+
{
258+
switch (te->section)
259+
{
260+
caseSECTION_NONE:
261+
/* ok to be anywhere */
262+
break;
263+
caseSECTION_PRE_DATA:
264+
if (curSection!=SECTION_PRE_DATA)
265+
write_msg(modulename,
266+
"WARNING: archive items not in correct section order\n");
267+
break;
268+
caseSECTION_DATA:
269+
if (curSection==SECTION_POST_DATA)
270+
write_msg(modulename,
271+
"WARNING: archive items not in correct section order\n");
272+
break;
273+
caseSECTION_POST_DATA:
274+
/* ok no matter which section we were in */
275+
break;
276+
default:
277+
exit_horribly(modulename,"unexpected section code %d\n",
278+
(int)te->section);
279+
break;
280+
}
281+
}
282+
250283
if (te->section!=SECTION_NONE)
251284
curSection=te->section;
285+
252286
te->reqs=_tocEntryRequired(te,curSection,ropt);
253287
}
254288
}

‎src/bin/pg_dump/pg_dump.c

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
210210
constchar*acls);
211211

212212
staticvoidgetDependencies(Archive*fout);
213+
214+
staticDumpableObject*createBoundaryObjects(void);
215+
staticvoidaddBoundaryDependencies(DumpableObject**dobjs,intnumObjs,
216+
DumpableObject*boundaryObjs);
217+
213218
staticvoidgetDomainConstraints(Archive*fout,TypeInfo*tyinfo);
214219
staticvoidgetTableData(TableInfo*tblinfo,intnumTables,booloids);
215220
staticvoidmakeTableDataInfo(TableInfo*tbinfo,booloids);
@@ -270,6 +275,7 @@ main(int argc, char **argv)
270275
intnumTables;
271276
DumpableObject**dobjs;
272277
intnumObjs;
278+
DumpableObject*boundaryObjs;
273279
inti;
274280
enumtrivalueprompt_password=TRI_DEFAULT;
275281
intcompressLevel=-1;
@@ -691,6 +697,17 @@ main(int argc, char **argv)
691697
*/
692698
getDependencies(fout);
693699

700+
/* Lastly, create dummy objects to represent the section boundaries */
701+
boundaryObjs=createBoundaryObjects();
702+
703+
/* Get pointers to all the known DumpableObjects */
704+
getDumpableObjects(&dobjs,&numObjs);
705+
706+
/*
707+
* Add dummy dependencies to enforce the dump section ordering.
708+
*/
709+
addBoundaryDependencies(dobjs,numObjs,boundaryObjs);
710+
694711
/*
695712
* Sort the objects into a safe dump order (no forward references).
696713
*
@@ -700,14 +717,13 @@ main(int argc, char **argv)
700717
* will dump identically. Before 7.3 we don't have dependencies and we
701718
* use OID ordering as an (unreliable) guide to creation order.
702719
*/
703-
getDumpableObjects(&dobjs,&numObjs);
704-
705720
if (fout->remoteVersion >=70300)
706721
sortDumpableObjectsByTypeName(dobjs,numObjs);
707722
else
708723
sortDumpableObjectsByTypeOid(dobjs,numObjs);
709724

710-
sortDumpableObjects(dobjs,numObjs);
725+
sortDumpableObjects(dobjs,numObjs,
726+
boundaryObjs[0].dumpId,boundaryObjs[1].dumpId);
711727

712728
/*
713729
* Create archive TOC entries for all the objects to be dumped, in a safe
@@ -7184,6 +7200,10 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
71847200
dobj->dependencies,dobj->nDeps,
71857201
dumpBlobs,NULL);
71867202
break;
7203+
caseDO_PRE_DATA_BOUNDARY:
7204+
caseDO_POST_DATA_BOUNDARY:
7205+
/* never dumped, nothing to do */
7206+
break;
71877207
}
71887208
}
71897209

@@ -11672,7 +11692,7 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
1167211692
daclinfo->dobj.namespace ?daclinfo->dobj.namespace->dobj.name :NULL,
1167311693
NULL,
1167411694
daclinfo->defaclrole,
11675-
false,"DEFAULT ACL",SECTION_NONE,
11695+
false,"DEFAULT ACL",SECTION_POST_DATA,
1167611696
q->data,"",NULL,
1167711697
daclinfo->dobj.dependencies,daclinfo->dobj.nDeps,
1167811698
NULL,NULL);
@@ -14027,6 +14047,113 @@ getDependencies(Archive *fout)
1402714047
}
1402814048

1402914049

14050+
/*
14051+
* createBoundaryObjects - create dummy DumpableObjects to represent
14052+
* dump section boundaries.
14053+
*/
14054+
staticDumpableObject*
14055+
createBoundaryObjects(void)
14056+
{
14057+
DumpableObject*dobjs;
14058+
14059+
dobjs= (DumpableObject*)pg_malloc(2*sizeof(DumpableObject));
14060+
14061+
dobjs[0].objType=DO_PRE_DATA_BOUNDARY;
14062+
dobjs[0].catId=nilCatalogId;
14063+
AssignDumpId(dobjs+0);
14064+
dobjs[0].name=pg_strdup("PRE-DATA BOUNDARY");
14065+
14066+
dobjs[1].objType=DO_POST_DATA_BOUNDARY;
14067+
dobjs[1].catId=nilCatalogId;
14068+
AssignDumpId(dobjs+1);
14069+
dobjs[1].name=pg_strdup("POST-DATA BOUNDARY");
14070+
14071+
returndobjs;
14072+
}
14073+
14074+
/*
14075+
* addBoundaryDependencies - add dependencies as needed to enforce the dump
14076+
* section boundaries.
14077+
*/
14078+
staticvoid
14079+
addBoundaryDependencies(DumpableObject**dobjs,intnumObjs,
14080+
DumpableObject*boundaryObjs)
14081+
{
14082+
DumpableObject*preDataBound=boundaryObjs+0;
14083+
DumpableObject*postDataBound=boundaryObjs+1;
14084+
inti;
14085+
14086+
for (i=0;i<numObjs;i++)
14087+
{
14088+
DumpableObject*dobj=dobjs[i];
14089+
14090+
/*
14091+
* The classification of object types here must match the SECTION_xxx
14092+
* values assigned during subsequent ArchiveEntry calls!
14093+
*/
14094+
switch (dobj->objType)
14095+
{
14096+
caseDO_NAMESPACE:
14097+
caseDO_EXTENSION:
14098+
caseDO_TYPE:
14099+
caseDO_SHELL_TYPE:
14100+
caseDO_FUNC:
14101+
caseDO_AGG:
14102+
caseDO_OPERATOR:
14103+
caseDO_OPCLASS:
14104+
caseDO_OPFAMILY:
14105+
caseDO_COLLATION:
14106+
caseDO_CONVERSION:
14107+
caseDO_TABLE:
14108+
caseDO_ATTRDEF:
14109+
caseDO_PROCLANG:
14110+
caseDO_CAST:
14111+
caseDO_DUMMY_TYPE:
14112+
caseDO_TSPARSER:
14113+
caseDO_TSDICT:
14114+
caseDO_TSTEMPLATE:
14115+
caseDO_TSCONFIG:
14116+
caseDO_FDW:
14117+
caseDO_FOREIGN_SERVER:
14118+
caseDO_BLOB:
14119+
/* Pre-data objects: must come before the pre-data boundary */
14120+
addObjectDependency(preDataBound,dobj->dumpId);
14121+
break;
14122+
caseDO_TABLE_DATA:
14123+
caseDO_BLOB_DATA:
14124+
/* Data objects: must come between the boundaries */
14125+
addObjectDependency(dobj,preDataBound->dumpId);
14126+
addObjectDependency(postDataBound,dobj->dumpId);
14127+
break;
14128+
caseDO_INDEX:
14129+
caseDO_TRIGGER:
14130+
caseDO_DEFAULT_ACL:
14131+
/* Post-data objects: must come after the post-data boundary */
14132+
addObjectDependency(dobj,postDataBound->dumpId);
14133+
break;
14134+
caseDO_RULE:
14135+
/* Rules are post-data, but only if dumped separately */
14136+
if (((RuleInfo*)dobj)->separate)
14137+
addObjectDependency(dobj,postDataBound->dumpId);
14138+
break;
14139+
caseDO_CONSTRAINT:
14140+
caseDO_FK_CONSTRAINT:
14141+
/* Constraints are post-data, but only if dumped separately */
14142+
if (((ConstraintInfo*)dobj)->separate)
14143+
addObjectDependency(dobj,postDataBound->dumpId);
14144+
break;
14145+
caseDO_PRE_DATA_BOUNDARY:
14146+
/* nothing to do */
14147+
break;
14148+
caseDO_POST_DATA_BOUNDARY:
14149+
/* must come after the pre-data boundary */
14150+
addObjectDependency(dobj,preDataBound->dumpId);
14151+
break;
14152+
}
14153+
}
14154+
}
14155+
14156+
1403014157
/*
1403114158
* selectSourceSchema - make the specified schema the active search path
1403214159
* in the source database.

‎src/bin/pg_dump/pg_dump.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ typedef enum
9797
DO_OPERATOR,
9898
DO_OPCLASS,
9999
DO_OPFAMILY,
100+
DO_COLLATION,
100101
DO_CONVERSION,
101102
DO_TABLE,
102103
DO_ATTRDEF,
@@ -118,7 +119,8 @@ typedef enum
118119
DO_DEFAULT_ACL,
119120
DO_BLOB,
120121
DO_BLOB_DATA,
121-
DO_COLLATION
122+
DO_PRE_DATA_BOUNDARY,
123+
DO_POST_DATA_BOUNDARY
122124
}DumpableObjectType;
123125

124126
typedefstruct_dumpableObject
@@ -520,7 +522,8 @@ extern bool simple_string_list_member(SimpleStringList *list, const char *val);
520522

521523
externvoidparseOidArray(constchar*str,Oid*array,intarraysize);
522524

523-
externvoidsortDumpableObjects(DumpableObject**objs,intnumObjs);
525+
externvoidsortDumpableObjects(DumpableObject**objs,intnumObjs,
526+
DumpIdpreBoundaryId,DumpIdpostBoundaryId);
524527
externvoidsortDumpableObjectsByTypeName(DumpableObject**objs,intnumObjs);
525528
externvoidsortDumpableObjectsByTypeOid(DumpableObject**objs,intnumObjs);
526529

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp