Skip to content

Commit 91d9746

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 ad53d6e commit 91d9746

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

src/backend/catalog/dependency.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,6 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
176176
static void deleteOneObject(const ObjectAddress *object,
177177
Relation *depRel, int32 flags);
178178
static void doDeletion(const ObjectAddress *object, int flags);
179-
static void AcquireDeletionLock(const ObjectAddress *object, int flags);
180-
static void ReleaseDeletionLock(const ObjectAddress *object);
181179
static bool find_expr_references_walker(Node *node,
182180
find_expr_references_context *context);
183181
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
@@ -1279,11 +1277,14 @@ doDeletion(const ObjectAddress *object, int flags)
12791277
/*
12801278
* AcquireDeletionLock - acquire a suitable lock for deleting an object
12811279
*
1280+
* Accepts the same flags as performDeletion (though currently only
1281+
* PERFORM_DELETION_CONCURRENTLY does anything).
1282+
*
12821283
* We use LockRelation for relations, LockDatabaseObject for everything
1283-
* else. Note that dependency.c is not concerned with deleting any kind of
1284-
* shared-across-databases object, so we have no need for LockSharedObject.
1284+
* else. Shared-across-databases objects are not currently supported
1285+
* because no caller cares, but could be modified to use LockSharedObject.
12851286
*/
1286-
static void
1287+
void
12871288
AcquireDeletionLock(const ObjectAddress *object, int flags)
12881289
{
12891290
if (object->classId == RelationRelationId)
@@ -1309,8 +1310,10 @@ AcquireDeletionLock(const ObjectAddress *object, int flags)
13091310

13101311
/*
13111312
* ReleaseDeletionLock - release an object deletion lock
1313+
*
1314+
* Companion to AcquireDeletionLock.
13121315
*/
1313-
static void
1316+
void
13141317
ReleaseDeletionLock(const ObjectAddress *object)
13151318
{
13161319
if (object->classId == RelationRelationId)

src/backend/catalog/pg_shdepend.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,14 +1248,29 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
12481248
sdepForm->objid);
12491249
break;
12501250
case SHARED_DEPENDENCY_POLICY:
1251-
/* If unable to remove role from policy, remove policy. */
1251+
/*
1252+
* Try to remove role from policy; if unable to, remove
1253+
* policy.
1254+
*/
12521255
if (!RemoveRoleFromObjectPolicy(roleid,
12531256
sdepForm->classid,
12541257
sdepForm->objid))
12551258
{
12561259
obj.classId = sdepForm->classid;
12571260
obj.objectId = sdepForm->objid;
12581261
obj.objectSubId = sdepForm->objsubid;
1262+
/*
1263+
* Acquire lock on object, then verify this dependency
1264+
* is still relevant. If not, the object might have
1265+
* been dropped or the policy modified. Ignore the
1266+
* object in that case.
1267+
*/
1268+
AcquireDeletionLock(&obj, 0);
1269+
if (!systable_recheck_tuple(scan, tuple))
1270+
{
1271+
ReleaseDeletionLock(&obj);
1272+
break;
1273+
}
12591274
add_exact_object_address(&obj, deleteobjs);
12601275
}
12611276
break;
@@ -1266,6 +1281,13 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
12661281
obj.classId = sdepForm->classid;
12671282
obj.objectId = sdepForm->objid;
12681283
obj.objectSubId = sdepForm->objsubid;
1284+
/* as above */
1285+
AcquireDeletionLock(&obj, 0);
1286+
if (!systable_recheck_tuple(scan, tuple))
1287+
{
1288+
ReleaseDeletionLock(&obj);
1289+
break;
1290+
}
12691291
add_exact_object_address(&obj, deleteobjs);
12701292
}
12711293
break;

src/include/catalog/dependency.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ typedef enum ObjectClass
164164
#define PERFORM_DELETION_INTERNAL 0x0001
165165
#define PERFORM_DELETION_CONCURRENTLY 0x0002
166166

167+
extern void AcquireDeletionLock(const ObjectAddress *object, int flags);
168+
169+
extern void ReleaseDeletionLock(const ObjectAddress *object);
170+
167171
extern void performDeletion(const ObjectAddress *object,
168172
DropBehavior behavior, int flags);
169173

0 commit comments

Comments
 (0)