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

Commit4fdc559

Browse files
committed
Avoid trying to restore table ACLs and per-column ACLs in parallel.
Parallel pg_restore has always supposed that ACL items for differentobjects are independent and can be restored in parallel withoutconflicts. However, there is one case where this fails: becauseREVOKE on a table is defined to also revoke the privilege(s) atcolumn level, we can't restore per-column ACLs till after we restoreany table-level privileges on their table. Failure to honor thisrestriction can lead to "tuple concurrently updated" errors duringparallel restore, or even to the per-column ACLs silently disappearingbecause the table-level REVOKE is executed afterwards.To fix, add a dependency from each column-level ACL item to its table'sACL item, if there is one. Note that this doesn't fix the hazardfor pre-existing archive files, only for ones made with a correctedpg_dump. Given that the bug's been there quite awhile withoutfield reports, I think this is acceptable.This requires changing the API of pg_dump's dumpACL() function.To keep its argument list from getting even longer, I removed the"CatalogId objCatId" argument, which has been unused for ages.Per report from Justin Pryzby. Back-patch to all supported branches.Discussion:https://postgr.es/m/20200706050129.GW4107@telsasoft.com
1 parent0ecd36e commit4fdc559

File tree

3 files changed

+59
-30
lines changed

3 files changed

+59
-30
lines changed

‎src/bin/pg_dump/common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
*/
3131
staticDumpableObject**dumpIdMap=NULL;
3232
staticintallocedDumpIds=0;
33-
staticDumpIdlastDumpId=0;
33+
staticDumpIdlastDumpId=0;/* Note: 0 is InvalidDumpId */
3434

3535
/*
3636
* Variables for mapping CatalogId to DumpableObject

‎src/bin/pg_dump/pg_backup.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ typedef struct
234234

235235
typedefintDumpId;
236236

237+
#defineInvalidDumpId 0
238+
239+
/*
240+
* Function pointer prototypes for assorted callback methods.
241+
*/
242+
237243
typedefint (*DataDumperPtr) (Archive*AH,void*userArg);
238244

239245
typedefvoid (*SetupWorkerPtrType) (Archive*AH);

‎src/bin/pg_dump/pg_dump.c

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ static void dumpUserMappings(Archive *fout,
216216
const char *owner, CatalogId catalogId, DumpId dumpId);
217217
static void dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo);
218218

219-
staticvoid dumpACL(Archive *fout,CatalogId objCatId, DumpIdobjDumpId,
219+
staticDumpId dumpACL(Archive *fout,DumpId objDumpId, DumpIdaltDumpId,
220220
const char *type, const char *name, const char *subname,
221221
const char *nspname, const char *owner,
222222
const char *acls, const char *racls,
@@ -2827,7 +2827,7 @@ dumpDatabase(Archive *fout)
28272827
* Dump ACL if any. Note that we do not support initial privileges
28282828
* (pg_init_privs) on databases.
28292829
*/
2830-
dumpACL(fout,dbCatId, dbDumpId, "DATABASE",
2830+
dumpACL(fout,dbDumpId, InvalidDumpId, "DATABASE",
28312831
qdatname, NULL, NULL,
28322832
dba, datacl, rdatacl, "", "");
28332833

@@ -3365,7 +3365,7 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
33653365

33663366
/* Dump ACL if any */
33673367
if (binfo->blobacl && (binfo->dobj.dump & DUMP_COMPONENT_ACL))
3368-
dumpACL(fout, binfo->dobj.catId, binfo->dobj.dumpId, "LARGE OBJECT",
3368+
dumpACL(fout, binfo->dobj.dumpId, InvalidDumpId, "LARGE OBJECT",
33693369
binfo->dobj.name, NULL,
33703370
NULL, binfo->rolname, binfo->blobacl, binfo->rblobacl,
33713371
binfo->initblobacl, binfo->initrblobacl);
@@ -10032,7 +10032,7 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
1003210032
nspinfo->dobj.catId, 0, nspinfo->dobj.dumpId);
1003310033

1003410034
if (nspinfo->dobj.dump & DUMP_COMPONENT_ACL)
10035-
dumpACL(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId, "SCHEMA",
10035+
dumpACL(fout, nspinfo->dobj.dumpId, InvalidDumpId, "SCHEMA",
1003610036
qnspname, NULL, NULL,
1003710037
nspinfo->rolname, nspinfo->nspacl, nspinfo->rnspacl,
1003810038
nspinfo->initnspacl, nspinfo->initrnspacl);
@@ -10319,7 +10319,7 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
1031910319
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1032010320

1032110321
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
10322-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
10322+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1032310323
qtypname, NULL,
1032410324
tyinfo->dobj.namespace->dobj.name,
1032510325
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -10446,7 +10446,7 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
1044610446
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1044710447

1044810448
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
10449-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
10449+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1045010450
qtypname, NULL,
1045110451
tyinfo->dobj.namespace->dobj.name,
1045210452
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -10519,7 +10519,7 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
1051910519
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1052010520

1052110521
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
10522-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
10522+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1052310523
qtypname, NULL,
1052410524
tyinfo->dobj.namespace->dobj.name,
1052510525
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -10801,7 +10801,7 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
1080110801
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1080210802

1080310803
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
10804-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
10804+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1080510805
qtypname, NULL,
1080610806
tyinfo->dobj.namespace->dobj.name,
1080710807
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -10958,7 +10958,7 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
1095810958
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1095910959

1096010960
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
10961-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
10961+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1096210962
qtypname, NULL,
1096310963
tyinfo->dobj.namespace->dobj.name,
1096410964
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -11181,7 +11181,7 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
1118111181
tyinfo->dobj.catId, 0, tyinfo->dobj.dumpId);
1118211182

1118311183
if (tyinfo->dobj.dump & DUMP_COMPONENT_ACL)
11184-
dumpACL(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId, "TYPE",
11184+
dumpACL(fout, tyinfo->dobj.dumpId, InvalidDumpId, "TYPE",
1118511185
qtypname, NULL,
1118611186
tyinfo->dobj.namespace->dobj.name,
1118711187
tyinfo->rolname, tyinfo->typacl, tyinfo->rtypacl,
@@ -11481,7 +11481,7 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
1148111481
plang->dobj.catId, 0, plang->dobj.dumpId);
1148211482

1148311483
if (plang->lanpltrusted && plang->dobj.dump & DUMP_COMPONENT_ACL)
11484-
dumpACL(fout, plang->dobj.catId, plang->dobj.dumpId, "LANGUAGE",
11484+
dumpACL(fout, plang->dobj.dumpId, InvalidDumpId, "LANGUAGE",
1148511485
qlanname, NULL, NULL,
1148611486
plang->lanowner, plang->lanacl, plang->rlanacl,
1148711487
plang->initlanacl, plang->initrlanacl);
@@ -12159,7 +12159,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
1215912159
finfo->dobj.catId, 0, finfo->dobj.dumpId);
1216012160

1216112161
if (finfo->dobj.dump & DUMP_COMPONENT_ACL)
12162-
dumpACL(fout, finfo->dobj.catId, finfo->dobj.dumpId, keyword,
12162+
dumpACL(fout, finfo->dobj.dumpId, InvalidDumpId, keyword,
1216312163
funcsig, NULL,
1216412164
finfo->dobj.namespace->dobj.name,
1216512165
finfo->rolname, finfo->proacl, finfo->rproacl,
@@ -14176,7 +14176,7 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
1417614176
aggsig = format_function_signature(fout, &agginfo->aggfn, true);
1417714177

1417814178
if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_ACL)
14179-
dumpACL(fout, agginfo->aggfn.dobj.catId, agginfo->aggfn.dobj.dumpId,
14179+
dumpACL(fout, agginfo->aggfn.dobj.dumpId, InvalidDumpId,
1418014180
"FUNCTION", aggsig, NULL,
1418114181
agginfo->aggfn.dobj.namespace->dobj.name,
1418214182
agginfo->aggfn.rolname, agginfo->aggfn.proacl,
@@ -14586,7 +14586,7 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
1458614586

1458714587
/* Handle the ACL */
1458814588
if (fdwinfo->dobj.dump & DUMP_COMPONENT_ACL)
14589-
dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
14589+
dumpACL(fout, fdwinfo->dobj.dumpId, InvalidDumpId,
1459014590
"FOREIGN DATA WRAPPER", qfdwname, NULL,
1459114591
NULL, fdwinfo->rolname,
1459214592
fdwinfo->fdwacl, fdwinfo->rfdwacl,
@@ -14677,7 +14677,7 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
1467714677

1467814678
/* Handle the ACL */
1467914679
if (srvinfo->dobj.dump & DUMP_COMPONENT_ACL)
14680-
dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
14680+
dumpACL(fout, srvinfo->dobj.dumpId, InvalidDumpId,
1468114681
"FOREIGN SERVER", qsrvname, NULL,
1468214682
NULL, srvinfo->rolname,
1468314683
srvinfo->srvacl, srvinfo->rsrvacl,
@@ -14873,8 +14873,9 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
1487314873
/*----------
1487414874
* Write out grant/revoke information
1487514875
*
14876-
* 'objCatId' is the catalog ID of the underlying object.
1487714876
* 'objDumpId' is the dump ID of the underlying object.
14877+
* 'altDumpId' can be a second dumpId that the ACL entry must also depend on,
14878+
*or InvalidDumpId if there is no need for a second dependency.
1487814879
* 'type' must be one of
1487914880
*TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
1488014881
*FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT.
@@ -14897,25 +14898,29 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
1489714898
* NB: initacls/initracls are needed because extensions can set privileges on
1489814899
* an object during the extension's script file and we record those into
1489914900
* pg_init_privs as that object's initial privileges.
14901+
*
14902+
* Returns the dump ID assigned to the ACL TocEntry, or InvalidDumpId if
14903+
* no ACL entry was created.
1490014904
*----------
1490114905
*/
14902-
staticvoid
14903-
dumpACL(Archive *fout,CatalogId objCatId, DumpIdobjDumpId,
14906+
staticDumpId
14907+
dumpACL(Archive *fout,DumpId objDumpId, DumpIdaltDumpId,
1490414908
const char *type, const char *name, const char *subname,
1490514909
const char *nspname, const char *owner,
1490614910
const char *acls, const char *racls,
1490714911
const char *initacls, const char *initracls)
1490814912
{
14913+
DumpIdaclDumpId = InvalidDumpId;
1490914914
DumpOptions *dopt = fout->dopt;
1491014915
PQExpBuffer sql;
1491114916

1491214917
/* Do nothing if ACL dump is not enabled */
1491314918
if (dopt->aclsSkip)
14914-
return;
14919+
return InvalidDumpId;
1491514920

1491614921
/* --data-only skips ACLs *except* BLOB ACLs */
1491714922
if (dopt->dataOnly && strcmp(type, "LARGE OBJECT") != 0)
14918-
return;
14923+
return InvalidDumpId;
1491914924

1492014925
sql = createPQExpBuffer();
1492114926

@@ -14949,24 +14954,35 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
1494914954
if (sql->len > 0)
1495014955
{
1495114956
PQExpBuffer tag = createPQExpBuffer();
14957+
DumpIdaclDeps[2];
14958+
intnDeps = 0;
1495214959

1495314960
if (subname)
1495414961
appendPQExpBuffer(tag, "COLUMN %s.%s", name, subname);
1495514962
else
1495614963
appendPQExpBuffer(tag, "%s %s", type, name);
1495714964

14958-
ArchiveEntry(fout, nilCatalogId, createDumpId(),
14965+
aclDeps[nDeps++] = objDumpId;
14966+
if (altDumpId != InvalidDumpId)
14967+
aclDeps[nDeps++] = altDumpId;
14968+
14969+
aclDumpId = createDumpId();
14970+
14971+
ArchiveEntry(fout, nilCatalogId, aclDumpId,
1495914972
tag->data, nspname,
1496014973
NULL,
1496114974
owner ? owner : "",
1496214975
false, "ACL", SECTION_NONE,
1496314976
sql->data, "", NULL,
14964-
&(objDumpId), 1,
14977+
aclDeps, nDeps,
1496514978
NULL, NULL);
14979+
1496614980
destroyPQExpBuffer(tag);
1496714981
}
1496814982

1496914983
destroyPQExpBuffer(sql);
14984+
14985+
return aclDumpId;
1497014986
}
1497114987

1497214988
/*
@@ -15288,6 +15304,7 @@ static void
1528815304
dumpTable(Archive *fout, TableInfo *tbinfo)
1528915305
{
1529015306
DumpOptions *dopt = fout->dopt;
15307+
DumpIdtableAclDumpId = InvalidDumpId;
1529115308
char *namecopy;
1529215309

1529315310
/*
@@ -15309,11 +15326,12 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
1530915326
const char *objtype =
1531015327
(tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE";
1531115328

15312-
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
15313-
objtype, namecopy, NULL,
15314-
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
15315-
tbinfo->relacl, tbinfo->rrelacl,
15316-
tbinfo->initrelacl, tbinfo->initrrelacl);
15329+
tableAclDumpId =
15330+
dumpACL(fout, tbinfo->dobj.dumpId, InvalidDumpId,
15331+
objtype, namecopy, NULL,
15332+
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
15333+
tbinfo->relacl, tbinfo->rrelacl,
15334+
tbinfo->initrelacl, tbinfo->initrrelacl);
1531715335
}
1531815336

1531915337
/*
@@ -15397,8 +15415,13 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
1539715415
char *attnamecopy;
1539815416

1539915417
attnamecopy = pg_strdup(fmtId(attname));
15400-
/* Column's GRANT type is always TABLE */
15401-
dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
15418+
15419+
/*
15420+
* Column's GRANT type is always TABLE. Each column ACL depends
15421+
* on the table-level ACL, since we can restore column ACLs in
15422+
* parallel but the table-level ACL has to be done first.
15423+
*/
15424+
dumpACL(fout, tbinfo->dobj.dumpId, tableAclDumpId,
1540215425
"TABLE", namecopy, attnamecopy,
1540315426
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
1540415427
attacl, rattacl, initattacl, initrattacl);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp