Skip to content

Commit da85727

Browse files
Fix orphan on cancel of drop index concurrently.
Canceling DROP INDEX CONCURRENTLY during wait could allow an orphaned index to be left behind which could not be dropped. Backpatch to 9.2 Andres Freund, tested by Abhijit Menon-Sen
1 parent 002191a commit da85727

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

src/backend/catalog/dependency.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,7 @@ performMultipleDeletions(const ObjectAddresses *objects,
355355
/* And clean up */
356356
free_object_addresses(targetObjects);
357357

358-
/*
359-
* We closed depRel earlier in deleteOneObject if doing a drop
360-
* concurrently
361-
*/
362-
if ((flags & PERFORM_DELETION_CONCURRENTLY) != PERFORM_DELETION_CONCURRENTLY)
363-
heap_close(depRel, RowExclusiveLock);
358+
heap_close(depRel, RowExclusiveLock);
364359
}
365360

366361
/*
@@ -1000,6 +995,7 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
1000995
int nkeys;
1001996
SysScanDesc scan;
1002997
HeapTuple tup;
998+
Oid depRelOid = depRel->rd_id;
1003999

10041000
/* DROP hook of the objects being removed */
10051001
if (object_access_hook)
@@ -1012,7 +1008,33 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
10121008
}
10131009

10141010
/*
1015-
* First remove any pg_depend records that link from this object to
1011+
* Close depRel if we are doing a drop concurrently. The individual
1012+
* deletion has to commit the transaction and we don't want dangling
1013+
* references.
1014+
*/
1015+
if (flags & PERFORM_DELETION_CONCURRENTLY)
1016+
heap_close(depRel, RowExclusiveLock);
1017+
1018+
/*
1019+
* Delete the object itself, in an object-type-dependent way.
1020+
*
1021+
* Do this before removing outgoing dependencies as deletions can be
1022+
* happening in concurrent mode. That will only happen for a single object
1023+
* at once and if so the object will be invalidated inside a separate
1024+
* transaction and only dropped inside a transaction thats in-progress when
1025+
* doDeletion returns. This way no observer can see dangling dependency
1026+
* entries.
1027+
*/
1028+
doDeletion(object, flags);
1029+
1030+
/*
1031+
* Reopen depRel if we closed it before
1032+
*/
1033+
if (flags & PERFORM_DELETION_CONCURRENTLY)
1034+
depRel = heap_open(depRelOid, RowExclusiveLock);
1035+
1036+
/*
1037+
* Then remove any pg_depend records that link from this object to
10161038
* others. (Any records linking to this object should be gone already.)
10171039
*
10181040
* When dropping a whole object (subId = 0), remove all pg_depend records
@@ -1054,17 +1076,6 @@ deleteOneObject(const ObjectAddress *object, Relation depRel, int flags)
10541076
deleteSharedDependencyRecordsFor(object->classId, object->objectId,
10551077
object->objectSubId);
10561078

1057-
/*
1058-
* Close depRel if we are doing a drop concurrently because it commits the
1059-
* transaction, so we don't want dangling references.
1060-
*/
1061-
if ((flags & PERFORM_DELETION_CONCURRENTLY) == PERFORM_DELETION_CONCURRENTLY)
1062-
heap_close(depRel, RowExclusiveLock);
1063-
1064-
/*
1065-
* Now delete the object itself, in an object-type-dependent way.
1066-
*/
1067-
doDeletion(object, flags);
10681079

10691080
/*
10701081
* Delete any comments or security labels associated with this object.
@@ -1247,7 +1258,7 @@ AcquireDeletionLock(const ObjectAddress *object, int flags)
12471258
{
12481259
if (object->classId == RelationRelationId)
12491260
{
1250-
if ((flags & PERFORM_DELETION_CONCURRENTLY) == PERFORM_DELETION_CONCURRENTLY)
1261+
if (flags & PERFORM_DELETION_CONCURRENTLY)
12511262
LockRelationOid(object->objectId, ShareUpdateExclusiveLock);
12521263
else
12531264
LockRelationOid(object->objectId, AccessExclusiveLock);

0 commit comments

Comments
 (0)