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

Commit 2ee9022

Browse files
michail-nikolaevCommitfest Bot
authored and
Commitfest Bot
committed
Track and drop auxiliary indexes in DROP/REINDEX
During concurrent index operations, auxiliary indexes may be left as orphaned objects when errors occur (junk auxiliary indexes). This patch improves the handling of such auxiliary indexes: - add auxiliaryForIndexId parameter to index_create() to track dependencies between main and auxiliary indexes - automatically drop auxiliary indexes when the main index is dropped - delete junk auxiliary indexes properly during REINDEX operations
1 parent 6f44213 commit 2ee9022

File tree

12 files changed

+357
-35
lines changed

12 files changed

+357
-35
lines changed

doc/src/sgml/ref/create_index.sgml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -668,10 +668,16 @@ Indexes:
668668
"idx_ccaux" stir (col) INVALID
669669
</programlisting>
670670

671-
The recommended recovery
672-
method in such cases is to drop these indexes and try again to perform
673-
<command>CREATE INDEX CONCURRENTLY</command>. (Another possibility is
674-
to rebuild the index with <command>REINDEX INDEX CONCURRENTLY</command>).
671+
The recommended recovery method in such cases is to drop the index with
672+
<command>DROP INDEX</command>. The auxiliary index (suffixed with
673+
<literal>ccaux</literal>) will be automatically dropped when the main
674+
index is dropped. After dropping the indexes, you can try again to perform
675+
<command>CREATE INDEX CONCURRENTLY</command>. (Another possibility is to
676+
rebuild the index with <command>REINDEX INDEX CONCURRENTLY</command>,
677+
which will also handle cleanup of any invalid auxiliary indexes.)
678+
If the only invalid index is one suffixed <literal>ccaux</literal>
679+
recommended recovery method is just <literal>DROP INDEX</literal>
680+
for that index.
675681
</para>
676682

677683
<para>

doc/src/sgml/ref/reindex.sgml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,15 @@ Indexes:
477477
<literal>_ccnew</literal> or <literal>_ccaux</literal>, then it corresponds to the transient or auxiliary
478478
index created during the concurrent operation, and the recommended
479479
recovery method is to drop these indexes using <literal>DROP INDEX</literal>,
480-
then attempt <command>REINDEX CONCURRENTLY</command> again.
480+
then attempt <command>REINDEX CONCURRENTLY</command> again. The auxiliary index
481+
(suffixed with <literal>_ccaux</literal>) will be automatically dropped
482+
along with its main index.
481483
If the invalid index is instead suffixed <literal>_ccold</literal>,
482484
it corresponds to the original index which could not be dropped;
483485
the recommended recovery method is to just drop said index, since the
484-
rebuild proper has been successful.
486+
rebuild proper has been successful. If the only
487+
invalid index is one suffixed <literal>ccaux</literal> recommended
488+
recovery method is just <literal>DROP INDEX</literal> for that index.
485489
A nonzero number may be appended to the suffix of the invalid index
486490
names to keep them unique, like <literal>_ccnew1</literal>,
487491
<literal>_ccold2</literal>, etc.

src/backend/catalog/dependency.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ performDeletion(const ObjectAddress *object,
286286
* Acquire deletion lock on the target object. (Ideally the caller has
287287
* done this already, but many places are sloppy about it.)
288288
*/
289-
AcquireDeletionLock(object, 0);
289+
AcquireDeletionLock(object, flags);
290290

291291
/*
292292
* Construct a list of objects to delete (ie, the given object plus

src/backend/catalog/index.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,8 @@ UpdateIndexRelation(Oid indexoid,
688688
* parent index; otherwise InvalidOid.
689689
* parentConstraintId: if creating a constraint on a partition, the OID
690690
* of the constraint in the parent; otherwise InvalidOid.
691+
* auxiliaryForIndexId: if creating auxiliary index, the OID of the main
692+
* index; otherwise InvalidOid.
691693
* relFileNumber: normally, pass InvalidRelFileNumber to get new storage.
692694
* May be nonzero to attach an existing valid build.
693695
* indexInfo: same info executor uses to insert into the index
@@ -734,6 +736,7 @@ index_create(Relation heapRelation,
734736
Oid indexRelationId,
735737
Oid parentIndexRelid,
736738
Oid parentConstraintId,
739+
Oid auxiliaryForIndexId,
737740
RelFileNumber relFileNumber,
738741
IndexInfo *indexInfo,
739742
const List *indexColNames,
@@ -776,6 +779,8 @@ index_create(Relation heapRelation,
776779
((flags & INDEX_CREATE_ADD_CONSTRAINT) != 0));
777780
/* partitioned indexes must never be "built" by themselves */
778781
Assert(!partitioned || (flags & INDEX_CREATE_SKIP_BUILD));
782+
/* auxiliaryForIndexId and INDEX_CREATE_AUXILIARY are required both or neither */
783+
Assert(OidIsValid(auxiliaryForIndexId) == auxiliary);
779784

780785
relkind = partitioned ? RELKIND_PARTITIONED_INDEX : RELKIND_INDEX;
781786
is_exclusion = (indexInfo->ii_ExclusionOps != NULL);
@@ -1177,6 +1182,15 @@ index_create(Relation heapRelation,
11771182
recordDependencyOn(&myself, &referenced, DEPENDENCY_PARTITION_SEC);
11781183
}
11791184

1185+
/*
1186+
* Record dependency on the main index in case of auxiliary index.
1187+
*/
1188+
if (OidIsValid(auxiliaryForIndexId))
1189+
{
1190+
ObjectAddressSet(referenced, RelationRelationId, auxiliaryForIndexId);
1191+
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
1192+
}
1193+
11801194
/* placeholder for normal dependencies */
11811195
addrs = new_object_addresses();
11821196

@@ -1459,6 +1473,7 @@ index_concurrently_create_copy(Relation heapRelation, Oid oldIndexId,
14591473
InvalidOid, /* indexRelationId */
14601474
InvalidOid, /* parentIndexRelid */
14611475
InvalidOid, /* parentConstraintId */
1476+
InvalidOid, /* auxiliaryForIndexId */
14621477
InvalidRelFileNumber, /* relFileNumber */
14631478
newInfo,
14641479
indexColNames,
@@ -1609,6 +1624,7 @@ index_concurrently_create_aux(Relation heapRelation, Oid mainIndexId,
16091624
InvalidOid, /* indexRelationId */
16101625
InvalidOid, /* parentIndexRelid */
16111626
InvalidOid, /* parentConstraintId */
1627+
mainIndexId, /* auxiliaryForIndexId */
16121628
InvalidRelFileNumber, /* relFileNumber */
16131629
newInfo,
16141630
indexColNames,
@@ -3842,6 +3858,7 @@ reindex_index(const ReindexStmt *stmt, Oid indexId,
38423858
heapRelation;
38433859
Oid heapId;
38443860
Oid save_userid;
3861+
Oid junkAuxIndexId;
38453862
int save_sec_context;
38463863
int save_nestlevel;
38473864
IndexInfo *indexInfo;
@@ -3898,6 +3915,19 @@ reindex_index(const ReindexStmt *stmt, Oid indexId,
38983915
pgstat_progress_update_multi_param(2, progress_cols, progress_vals);
38993916
}
39003917

3918+
/* Check for the auxiliary index for that index, it needs to dropped */
3919+
junkAuxIndexId = get_auxiliary_index(indexId);
3920+
if (OidIsValid(junkAuxIndexId))
3921+
{
3922+
ObjectAddress object;
3923+
object.classId = RelationRelationId;
3924+
object.objectId = junkAuxIndexId;
3925+
object.objectSubId = 0;
3926+
performDeletion(&object, DROP_RESTRICT,
3927+
PERFORM_DELETION_INTERNAL |
3928+
PERFORM_DELETION_QUIETLY);
3929+
}
3930+
39013931
/*
39023932
* Open the target index relation and get an exclusive lock on it, to
39033933
* ensure that no one else is touching this particular index.
@@ -4186,7 +4216,8 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, int flags,
41864216
{
41874217
Relation rel;
41884218
Oid toast_relid;
4189-
List *indexIds;
4219+
List *indexIds,
4220+
*auxIndexIds = NIL;
41904221
char persistence;
41914222
bool result = false;
41924223
ListCell *indexId;
@@ -4275,13 +4306,30 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, int flags,
42754306
else
42764307
persistence = rel->rd_rel->relpersistence;
42774308

4309+
foreach(indexId, indexIds)
4310+
{
4311+
Oid indexOid = lfirst_oid(indexId);
4312+
Oid indexAm = get_rel_relam(indexOid);
4313+
4314+
/* All STIR indexes are auxiliary indexes */
4315+
if (indexAm == STIR_AM_OID)
4316+
{
4317+
if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
4318+
RemoveReindexPending(indexOid);
4319+
auxIndexIds = lappend_oid(auxIndexIds, indexOid);
4320+
}
4321+
}
4322+
42784323
/* Reindex all the indexes. */
42794324
i = 1;
42804325
foreach(indexId, indexIds)
42814326
{
42824327
Oid indexOid = lfirst_oid(indexId);
42834328
Oid indexNamespaceId = get_rel_namespace(indexOid);
4284-
Oid indexAm = get_rel_relam(indexOid);
4329+
4330+
/* Auxiliary indexes are going to be dropped during main index rebuild */
4331+
if (list_member_oid(auxIndexIds, indexOid))
4332+
continue;
42854333

42864334
/*
42874335
* Skip any invalid indexes on a TOAST table. These can only be
@@ -4307,18 +4355,6 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, int flags,
43074355
continue;
43084356
}
43094357

4310-
if (indexAm == STIR_AM_OID)
4311-
{
4312-
ereport(WARNING,
4313-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4314-
errmsg("skipping reindex of auxiliary index \"%s.%s\"",
4315-
get_namespace_name(indexNamespaceId),
4316-
get_rel_name(indexOid))));
4317-
if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
4318-
RemoveReindexPending(indexOid);
4319-
continue;
4320-
}
4321-
43224358
reindex_index(stmt, indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
43234359
persistence, params);
43244360

src/backend/catalog/pg_depend.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,63 @@ get_index_constraint(Oid indexId)
10351035
return constraintId;
10361036
}
10371037

1038+
/*
1039+
* get_auxiliary_index
1040+
* Given the OID of an index, return the OID of its auxiliary
1041+
* index, or InvalidOid if there is no auxiliary index.
1042+
*/
1043+
Oid
1044+
get_auxiliary_index(Oid indexId)
1045+
{
1046+
Oid auxiliaryIndexOid = InvalidOid;
1047+
Relation depRel;
1048+
ScanKeyData key[3];
1049+
SysScanDesc scan;
1050+
HeapTuple tup;
1051+
1052+
/* Search the dependency table for the index */
1053+
depRel = table_open(DependRelationId, AccessShareLock);
1054+
1055+
ScanKeyInit(&key[0],
1056+
Anum_pg_depend_refclassid,
1057+
BTEqualStrategyNumber, F_OIDEQ,
1058+
ObjectIdGetDatum(RelationRelationId));
1059+
ScanKeyInit(&key[1],
1060+
Anum_pg_depend_refobjid,
1061+
BTEqualStrategyNumber, F_OIDEQ,
1062+
ObjectIdGetDatum(indexId));
1063+
ScanKeyInit(&key[2],
1064+
Anum_pg_depend_refobjsubid,
1065+
BTEqualStrategyNumber, F_INT4EQ,
1066+
Int32GetDatum(0));
1067+
1068+
scan = systable_beginscan(depRel, DependReferenceIndexId, true,
1069+
NULL, 3, key);
1070+
1071+
1072+
while (HeapTupleIsValid(tup = systable_getnext(scan)))
1073+
{
1074+
Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
1075+
1076+
/*
1077+
* We assume any AUTO dependency on index with rel_kind
1078+
* of RELKIND_INDEX is that we are looking for.
1079+
*/
1080+
if (deprec->classid == RelationRelationId &&
1081+
(deprec->deptype == DEPENDENCY_AUTO) &&
1082+
get_rel_relkind(deprec->objid) == RELKIND_INDEX)
1083+
{
1084+
auxiliaryIndexOid = deprec->objid;
1085+
break;
1086+
}
1087+
}
1088+
1089+
systable_endscan(scan);
1090+
table_close(depRel, AccessShareLock);
1091+
1092+
return auxiliaryIndexOid;
1093+
}
1094+
10381095
/*
10391096
* get_index_ref_constraints
10401097
* Given the OID of an index, return the OID of all foreign key

src/backend/catalog/toasting.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
319319
coloptions[1] = 0;
320320

321321
index_create(toast_rel, toast_idxname, toastIndexOid, InvalidOid,
322-
InvalidOid, InvalidOid,
322+
InvalidOid, InvalidOid, InvalidOid,
323323
indexInfo,
324324
list_make2("chunk_id", "chunk_seq"),
325325
BTREE_AM_OID,

src/backend/commands/indexcmds.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,7 @@ DefineIndex(Oid tableId,
12601260

12611261
indexRelationId =
12621262
index_create(rel, indexRelationName, indexRelationId, parentIndexId,
1263-
parentConstraintId,
1263+
parentConstraintId, InvalidOid,
12641264
stmt->oldNumber, indexInfo, indexColNames,
12651265
accessMethodId, tablespaceId,
12661266
collationIds, opclassIds, opclassOptions,
@@ -3639,6 +3639,7 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
36393639
{
36403640
Oid indexId;
36413641
Oid auxIndexId;
3642+
Oid junkAuxIndexId;
36423643
Oid tableId;
36433644
Oid amId;
36443645
bool safe; /* for set_indexsafe_procflags */
@@ -3988,13 +3989,15 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
39883989
ReindexIndexInfo *newidx;
39893990
Oid newIndexId;
39903991
Oid auxIndexId;
3992+
Oid junkAuxIndexId;
39913993
Relation indexRel;
39923994
Relation heapRel;
39933995
Oid save_userid;
39943996
int save_sec_context;
39953997
int save_nestlevel;
39963998
Relation newIndexRel;
39973999
Relation auxIndexRel;
4000+
Relation junkAuxIndexRel;
39984001
LockRelId *lockrelid;
39994002
Oid tablespaceid;
40004003

@@ -4068,12 +4071,17 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
40684071
tablespaceid,
40694072
auxConcurrentName);
40704073

4074+
/* Search for auxiliary index for reindexed index, to drop it */
4075+
junkAuxIndexId = get_auxiliary_index(idx->indexId);
4076+
40714077
/*
40724078
* Now open the relation of the new index, a session-level lock is
40734079
* also needed on it.
40744080
*/
40754081
newIndexRel = index_open(newIndexId, ShareUpdateExclusiveLock);
40764082
auxIndexRel = index_open(auxIndexId, ShareUpdateExclusiveLock);
4083+
if (OidIsValid(junkAuxIndexId))
4084+
junkAuxIndexRel = index_open(junkAuxIndexId, ShareUpdateExclusiveLock);
40774085

40784086
/*
40794087
* Save the list of OIDs and locks in private context
@@ -4083,6 +4091,7 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
40834091
newidx = palloc_object(ReindexIndexInfo);
40844092
newidx->indexId = newIndexId;
40854093
newidx->auxIndexId = auxIndexId;
4094+
newidx->junkAuxIndexId = junkAuxIndexId;
40864095
newidx->safe = idx->safe;
40874096
newidx->tableId = idx->tableId;
40884097
newidx->amId = idx->amId;
@@ -4104,10 +4113,18 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
41044113
lockrelid = palloc_object(LockRelId);
41054114
*lockrelid = auxIndexRel->rd_lockInfo.lockRelId;
41064115
relationLocks = lappend(relationLocks, lockrelid);
4116+
if (OidIsValid(junkAuxIndexId))
4117+
{
4118+
lockrelid = palloc_object(LockRelId);
4119+
*lockrelid = junkAuxIndexRel->rd_lockInfo.lockRelId;
4120+
relationLocks = lappend(relationLocks, lockrelid);
4121+
}
41074122

41084123
MemoryContextSwitchTo(oldcontext);
41094124

41104125
index_close(indexRel, NoLock);
4126+
if (OidIsValid(junkAuxIndexId))
4127+
index_close(junkAuxIndexRel, NoLock);
41114128
index_close(auxIndexRel, NoLock);
41124129
index_close(newIndexRel, NoLock);
41134130

@@ -4288,7 +4305,8 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
42884305

42894306
/*
42904307
* At this moment all target indexes are marked as "ready-to-insert". So,
4291-
* we are free to start process of dropping auxiliary indexes.
4308+
* we are free to start process of dropping auxiliary indexes - including
4309+
* just indexes detected earlier.
42924310
*/
42934311
foreach(lc, newIndexIds)
42944312
{
@@ -4311,6 +4329,9 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
43114329
*/
43124330
PushActiveSnapshot(GetTransactionSnapshot());
43134331
index_set_state_flags(newidx->auxIndexId, INDEX_DROP_CLEAR_READY);
4332+
/* Ensure just index is marked as non-ready */
4333+
if (OidIsValid(newidx->junkAuxIndexId))
4334+
index_set_state_flags(newidx->junkAuxIndexId, INDEX_DROP_CLEAR_READY);
43144335
PopActiveSnapshot();
43154336

43164337
CommitTransactionCommand();
@@ -4529,6 +4550,8 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
45294550
PushActiveSnapshot(GetTransactionSnapshot());
45304551

45314552
index_concurrently_set_dead(newidx->tableId, newidx->auxIndexId);
4553+
if (OidIsValid(newidx->junkAuxIndexId))
4554+
index_concurrently_set_dead(newidx->tableId, newidx->junkAuxIndexId);
45324555

45334556
PopActiveSnapshot();
45344557
}
@@ -4580,6 +4603,14 @@ ReindexRelationConcurrently(const ReindexStmt *stmt, Oid relationOid, const Rein
45804603
object.objectSubId = 0;
45814604

45824605
add_exact_object_address(&object, objects);
4606+
4607+
if (OidIsValid(idx->junkAuxIndexId))
4608+
{
4609+
4610+
object.objectId = idx->junkAuxIndexId;
4611+
object.objectSubId = 0;
4612+
add_exact_object_address(&object, objects);
4613+
}
45834614
}
45844615

45854616
/*

0 commit comments

Comments
 (0)