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

Commit 5be594c

Browse files
committed
Heed lock protocol in DROP OWNED BY
We were acquiring object locks then deleting objects one by one, instead of acquiring all object locks first, ignoring those that did not exist, and then deleting all objects together. The latter is the correct protocol to use, and what this commits changes to code to do. Failing to follow that leads to "cache lookup failed for relation XYZ" error reports when DROP OWNED runs concurrently with other DDL -- for example, a session termination that removes some temp tables. Author: Álvaro Herrera Reported-by: Mithun Chicklore Yogendra (Mithun CY) Reviewed-by: Ahsan Hadi, Tom Lane Discussion: https://postgr.es/m/CADq3xVZTbzK4ZLKq+dn_vB4QafXXbmMgDP3trY-GuLnib2Ai1w@mail.gmail.com
1 parent f215993 commit 5be594c

File tree

4 files changed

+36
-8
lines changed

4 files changed

+36
-8
lines changed

src/backend/catalog/dependency.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
200200
static void deleteOneObject(const ObjectAddress *object,
201201
Relation *depRel, int32 flags);
202202
static void doDeletion(const ObjectAddress *object, int flags);
203-
static void AcquireDeletionLock(const ObjectAddress *object, int flags);
204-
static void ReleaseDeletionLock(const ObjectAddress *object);
205203
static bool find_expr_references_walker(Node *node,
206204
find_expr_references_context *context);
207205
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
@@ -1527,11 +1525,14 @@ doDeletion(const ObjectAddress *object, int flags)
15271525
/*
15281526
* AcquireDeletionLock - acquire a suitable lock for deleting an object
15291527
*
1528+
* Accepts the same flags as performDeletion (though currently only
1529+
* PERFORM_DELETION_CONCURRENTLY does anything).
1530+
*
15301531
* We use LockRelation for relations, LockDatabaseObject for everything
1531-
* else. Note that dependency.c is not concerned with deleting any kind of
1532-
* shared-across-databases object, so we have no need for LockSharedObject.
1532+
* else. Shared-across-databases objects are not currently supported
1533+
* because no caller cares, but could be modified to use LockSharedObject.
15331534
*/
1534-
static void
1535+
void
15351536
AcquireDeletionLock(const ObjectAddress *object, int flags)
15361537
{
15371538
if (object->classId == RelationRelationId)
@@ -1557,8 +1558,10 @@ AcquireDeletionLock(const ObjectAddress *object, int flags)
15571558

15581559
/*
15591560
* ReleaseDeletionLock - release an object deletion lock
1561+
*
1562+
* Companion to AcquireDeletionLock.
15601563
*/
1561-
static void
1564+
void
15621565
ReleaseDeletionLock(const ObjectAddress *object)
15631566
{
15641567
if (object->classId == RelationRelationId)

src/backend/catalog/pg_shdepend.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,14 +1324,29 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
13241324
sdepForm->objid);
13251325
break;
13261326
case SHARED_DEPENDENCY_POLICY:
1327-
/* If unable to remove role from policy, remove policy. */
1327+
/*
1328+
* Try to remove role from policy; if unable to, remove
1329+
* policy.
1330+
*/
13281331
if (!RemoveRoleFromObjectPolicy(roleid,
13291332
sdepForm->classid,
13301333
sdepForm->objid))
13311334
{
13321335
obj.classId = sdepForm->classid;
13331336
obj.objectId = sdepForm->objid;
13341337
obj.objectSubId = sdepForm->objsubid;
1338+
/*
1339+
* Acquire lock on object, then verify this dependency
1340+
* is still relevant. If not, the object might have
1341+
* been dropped or the policy modified. Ignore the
1342+
* object in that case.
1343+
*/
1344+
AcquireDeletionLock(&obj, 0);
1345+
if (!systable_recheck_tuple(scan, tuple))
1346+
{
1347+
ReleaseDeletionLock(&obj);
1348+
break;
1349+
}
13351350
add_exact_object_address(&obj, deleteobjs);
13361351
}
13371352
break;
@@ -1342,6 +1357,13 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
13421357
obj.classId = sdepForm->classid;
13431358
obj.objectId = sdepForm->objid;
13441359
obj.objectSubId = sdepForm->objsubid;
1360+
/* as above */
1361+
AcquireDeletionLock(&obj, 0);
1362+
if (!systable_recheck_tuple(scan, tuple))
1363+
{
1364+
ReleaseDeletionLock(&obj);
1365+
break;
1366+
}
13451367
add_exact_object_address(&obj, deleteobjs);
13461368
}
13471369
break;

src/backend/commands/subscriptioncmds.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,6 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
915915
if (slotname)
916916
PreventInTransactionBlock(isTopLevel, "DROP SUBSCRIPTION");
917917

918-
919918
ObjectAddressSet(myself, SubscriptionRelationId, subid);
920919
EventTriggerSQLDropAddObject(&myself, true, true);
921920

src/include/catalog/dependency.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ typedef enum ObjectClass
142142

143143
/* in dependency.c */
144144

145+
extern void AcquireDeletionLock(const ObjectAddress *object, int flags);
146+
147+
extern void ReleaseDeletionLock(const ObjectAddress *object);
148+
145149
extern void performDeletion(const ObjectAddress *object,
146150
DropBehavior behavior, int flags);
147151

0 commit comments

Comments
 (0)