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

Commit1813806

Browse files
committed
Fix reindexing of pg_class indexes some more.
Commits3dbb317 et al failed under CLOBBER_CACHE_ALWAYS testing.Investigation showed that to reindex pg_class_oid_index, we mustsuppress accesses to the index (via SetReindexProcessing) before we callRelationSetNewRelfilenode, or at least before we do CommandCounterIncrementtherein; otherwise, relcache reloads happening within the CCI may try tofetch pg_class rows using the index's new relfilenode value, which is asyet an empty file.Of course, the point of3dbb317 was that that ordering didn't workeither, because then RelationSetNewRelfilenode's own update of the index'spg_class row cannot access the index, should it need to.There are various ways we might have got around that, but Andres Freundcame up with a brilliant solution: for a mapped index, we can really justskip the pg_class update altogether. The only fields it was actuallychanging were relpages etc, but it was just setting them to zeroes whichis useless make-work. (Correct new values will be installed at the endof index build.) All pg_class indexes are mapped and probably always willbe, so this eliminates the problem by removing work rather than adding it,always a pleasant outcome. Having taught RelationSetNewRelfilenode to doit that way, we can revert the code reordering in reindex_index. (ButI left the moved setup code where it was; there seems no reason why ithas to run without use of the old index. If you're trying to fix abusted pg_class index, you'll have had to disable system index usealtogether to get this far.)Moreover, this means we don't need RelationSetIndexList at all, becausereindex_relation's hacking to make "REINDEX TABLE pg_class" work islikewise now unnecessary. We'll leave that code in place in the backbranches, but a follow-on patch will remove it in HEAD.In passing, do some minor cleanup for commit5c15606 (in HEAD only),notably removing a duplicate newrnode assignment.Patch by me, using a core idea due to Andres Freund. Back-patch to allsupported branches, as3dbb317 was.Discussion:https://postgr.es/m/28926.1556664156@sss.pgh.pa.us
1 parentad79180 commit1813806

File tree

2 files changed

+49
-65
lines changed

2 files changed

+49
-65
lines changed

‎src/backend/catalog/index.c

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3377,21 +3377,16 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence,
33773377
indexInfo->ii_ExclusionStrats=NULL;
33783378
}
33793379

3380-
/*
3381-
* Build a new physical relation for the index. Need to do that before
3382-
* "officially" starting the reindexing with SetReindexProcessing -
3383-
* otherwise the necessary pg_class changes cannot be made with
3384-
* encountering assertions.
3385-
*/
3386-
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3387-
InvalidMultiXactId);
3388-
33893380
/* ensure SetReindexProcessing state isn't leaked */
33903381
PG_TRY();
33913382
{
33923383
/* Suppress use of the target index while rebuilding it */
33933384
SetReindexProcessing(heapId,indexId);
33943385

3386+
/* Create a new physical relation for the index */
3387+
RelationSetNewRelfilenode(iRel,persistence,InvalidTransactionId,
3388+
InvalidMultiXactId);
3389+
33953390
/* Initialize the index and rebuild */
33963391
/* Note: we do not need to re-establish pkey setting */
33973392
index_build(heapRelation,iRel,indexInfo, false, true);
@@ -3537,7 +3532,6 @@ reindex_relation(Oid relid, int flags, int options)
35373532
Relationrel;
35383533
Oidtoast_relid;
35393534
List*indexIds;
3540-
boolis_pg_class;
35413535
boolresult;
35423536

35433537
/*
@@ -3556,37 +3550,8 @@ reindex_relation(Oid relid, int flags, int options)
35563550
*/
35573551
indexIds=RelationGetIndexList(rel);
35583552

3559-
/*
3560-
* reindex_index will attempt to update the pg_class rows for the relation
3561-
* and index. If we are processing pg_class itself, we want to make sure
3562-
* that the updates do not try to insert index entries into indexes we
3563-
* have not processed yet. (When we are trying to recover from corrupted
3564-
* indexes, that could easily cause a crash.) We can accomplish this
3565-
* because CatalogTupleInsert/CatalogTupleUpdate will use the relcache's
3566-
* index list to know which indexes to update. We just force the index
3567-
* list to be only the stuff we've processed.
3568-
*
3569-
* It is okay to not insert entries into the indexes we have not processed
3570-
* yet because all of this is transaction-safe. If we fail partway
3571-
* through, the updated rows are dead and it doesn't matter whether they
3572-
* have index entries. Also, a new pg_class index will be created with a
3573-
* correct entry for its own pg_class row because we do
3574-
* RelationSetNewRelfilenode() before we do index_build().
3575-
*
3576-
* Note that we also clear pg_class's rd_oidindex until the loop is done,
3577-
* so that that index can't be accessed either. This means we cannot
3578-
* safely generate new relation OIDs while in the loop; shouldn't be a
3579-
* problem.
3580-
*/
3581-
is_pg_class= (RelationGetRelid(rel)==RelationRelationId);
3582-
3583-
/* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
3584-
if (is_pg_class)
3585-
(void)RelationGetIndexAttrBitmap(rel,INDEX_ATTR_BITMAP_ALL);
3586-
35873553
PG_TRY();
35883554
{
3589-
List*doneIndexes;
35903555
ListCell*indexId;
35913556
charpersistence;
35923557

@@ -3614,24 +3579,17 @@ reindex_relation(Oid relid, int flags, int options)
36143579
persistence=rel->rd_rel->relpersistence;
36153580

36163581
/* Reindex all the indexes. */
3617-
doneIndexes=NIL;
36183582
foreach(indexId,indexIds)
36193583
{
36203584
OidindexOid=lfirst_oid(indexId);
36213585

3622-
if (is_pg_class)
3623-
RelationSetIndexList(rel,doneIndexes,InvalidOid);
3624-
36253586
reindex_index(indexOid, !(flags&REINDEX_REL_CHECK_CONSTRAINTS),
36263587
persistence,options);
36273588

36283589
CommandCounterIncrement();
36293590

36303591
/* Index should no longer be in the pending list */
36313592
Assert(!ReindexIsProcessingIndex(indexOid));
3632-
3633-
if (is_pg_class)
3634-
doneIndexes=lappend_oid(doneIndexes,indexOid);
36353593
}
36363594
}
36373595
PG_CATCH();
@@ -3643,9 +3601,6 @@ reindex_relation(Oid relid, int flags, int options)
36433601
PG_END_TRY();
36443602
ResetReindexPending();
36453603

3646-
if (is_pg_class)
3647-
RelationSetIndexList(rel,indexIds,ClassOidIndexId);
3648-
36493604
/*
36503605
* Close rel, but continue to hold the lock.
36513606
*/

‎src/backend/utils/cache/relcache.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,38 +3501,67 @@ RelationSetNewRelfilenode(Relation relation, char persistence,
35013501
RelationDropStorage(relation);
35023502

35033503
/*
3504-
* Now update the pg_class row. However, if we're dealing with a mapped
3505-
* index, pg_class.relfilenode doesn't change; instead we have to send the
3506-
* update to the relation mapper.
3504+
* If we're dealing with a mapped index, pg_class.relfilenode doesn't
3505+
* change; instead we have to send the update to the relation mapper.
3506+
*
3507+
* For mapped indexes, we don't actually change the pg_class entry at all;
3508+
* this is essential when reindexing pg_class itself. That leaves us with
3509+
* possibly-inaccurate values of relpages etc, but those will be fixed up
3510+
* later.
35073511
*/
35083512
if (RelationIsMapped(relation))
3513+
{
3514+
/* This case is only supported for indexes */
3515+
Assert(relation->rd_rel->relkind==RELKIND_INDEX);
3516+
3517+
/* Since we're not updating pg_class, these had better not change */
3518+
Assert(classform->relfrozenxid==freezeXid);
3519+
Assert(classform->relminmxid==minmulti);
3520+
Assert(classform->relpersistence==persistence);
3521+
3522+
/*
3523+
* In some code paths it's possible that the tuple update we'd
3524+
* otherwise do here is the only thing that would assign an XID for
3525+
* the current transaction. However, we must have an XID to delete
3526+
* files, so make sure one is assigned.
3527+
*/
3528+
(void)GetCurrentTransactionId();
3529+
3530+
/* Do the deed */
35093531
RelationMapUpdateMap(RelationGetRelid(relation),
35103532
newrelfilenode,
35113533
relation->rd_rel->relisshared,
35123534
false);
3535+
3536+
/* Since we're not updating pg_class, must trigger inval manually */
3537+
CacheInvalidateRelcache(relation);
3538+
}
35133539
else
3540+
{
3541+
/* Normal case, update the pg_class entry */
35143542
classform->relfilenode=newrelfilenode;
35153543

3516-
/*These changes are safe evenfora mapped relation */
3517-
if (relation->rd_rel->relkind!=RELKIND_SEQUENCE)
3518-
{
3519-
classform->relpages=0;/* it's empty until further notice */
3520-
classform->reltuples=0;
3521-
classform->relallvisible=0;
3522-
}
3523-
classform->relfrozenxid=freezeXid;
3524-
classform->relminmxid=minmulti;
3525-
classform->relpersistence=persistence;
3544+
/*relpages etc. never changeforsequences */
3545+
if (relation->rd_rel->relkind!=RELKIND_SEQUENCE)
3546+
{
3547+
classform->relpages=0;/* it's empty until further notice */
3548+
classform->reltuples=0;
3549+
classform->relallvisible=0;
3550+
}
3551+
classform->relfrozenxid=freezeXid;
3552+
classform->relminmxid=minmulti;
3553+
classform->relpersistence=persistence;
35263554

3527-
CatalogTupleUpdate(pg_class,&tuple->t_self,tuple);
3555+
CatalogTupleUpdate(pg_class,&tuple->t_self,tuple);
3556+
}
35283557

35293558
heap_freetuple(tuple);
35303559

35313560
heap_close(pg_class,RowExclusiveLock);
35323561

35333562
/*
3534-
* Make the pg_class row changevisible, as well as the relation map
3535-
*change if any. This willcause the relcache entry to get updated, too.
3563+
* Make the pg_class row changeor relation map change visible. This will
3564+
* cause the relcache entry to get updated, too.
35363565
*/
35373566
CommandCounterIncrement();
35383567

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp