mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
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
This commit is contained in:
parent
f21599311e
commit
5be594caf8
@ -200,8 +200,6 @@ static void reportDependentObjects(const ObjectAddresses *targetObjects,
|
|||||||
static void deleteOneObject(const ObjectAddress *object,
|
static void deleteOneObject(const ObjectAddress *object,
|
||||||
Relation *depRel, int32 flags);
|
Relation *depRel, int32 flags);
|
||||||
static void doDeletion(const ObjectAddress *object, int flags);
|
static void doDeletion(const ObjectAddress *object, int flags);
|
||||||
static void AcquireDeletionLock(const ObjectAddress *object, int flags);
|
|
||||||
static void ReleaseDeletionLock(const ObjectAddress *object);
|
|
||||||
static bool find_expr_references_walker(Node *node,
|
static bool find_expr_references_walker(Node *node,
|
||||||
find_expr_references_context *context);
|
find_expr_references_context *context);
|
||||||
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
|
static void eliminate_duplicate_dependencies(ObjectAddresses *addrs);
|
||||||
@ -1527,11 +1525,14 @@ doDeletion(const ObjectAddress *object, int flags)
|
|||||||
/*
|
/*
|
||||||
* AcquireDeletionLock - acquire a suitable lock for deleting an object
|
* AcquireDeletionLock - acquire a suitable lock for deleting an object
|
||||||
*
|
*
|
||||||
|
* Accepts the same flags as performDeletion (though currently only
|
||||||
|
* PERFORM_DELETION_CONCURRENTLY does anything).
|
||||||
|
*
|
||||||
* We use LockRelation for relations, LockDatabaseObject for everything
|
* We use LockRelation for relations, LockDatabaseObject for everything
|
||||||
* else. Note that dependency.c is not concerned with deleting any kind of
|
* else. Shared-across-databases objects are not currently supported
|
||||||
* shared-across-databases object, so we have no need for LockSharedObject.
|
* because no caller cares, but could be modified to use LockSharedObject.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
AcquireDeletionLock(const ObjectAddress *object, int flags)
|
AcquireDeletionLock(const ObjectAddress *object, int flags)
|
||||||
{
|
{
|
||||||
if (object->classId == RelationRelationId)
|
if (object->classId == RelationRelationId)
|
||||||
@ -1557,8 +1558,10 @@ AcquireDeletionLock(const ObjectAddress *object, int flags)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ReleaseDeletionLock - release an object deletion lock
|
* ReleaseDeletionLock - release an object deletion lock
|
||||||
|
*
|
||||||
|
* Companion to AcquireDeletionLock.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
ReleaseDeletionLock(const ObjectAddress *object)
|
ReleaseDeletionLock(const ObjectAddress *object)
|
||||||
{
|
{
|
||||||
if (object->classId == RelationRelationId)
|
if (object->classId == RelationRelationId)
|
||||||
|
@ -1324,7 +1324,10 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
sdepForm->objid);
|
sdepForm->objid);
|
||||||
break;
|
break;
|
||||||
case SHARED_DEPENDENCY_POLICY:
|
case SHARED_DEPENDENCY_POLICY:
|
||||||
/* If unable to remove role from policy, remove policy. */
|
/*
|
||||||
|
* Try to remove role from policy; if unable to, remove
|
||||||
|
* policy.
|
||||||
|
*/
|
||||||
if (!RemoveRoleFromObjectPolicy(roleid,
|
if (!RemoveRoleFromObjectPolicy(roleid,
|
||||||
sdepForm->classid,
|
sdepForm->classid,
|
||||||
sdepForm->objid))
|
sdepForm->objid))
|
||||||
@ -1332,6 +1335,18 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
obj.classId = sdepForm->classid;
|
obj.classId = sdepForm->classid;
|
||||||
obj.objectId = sdepForm->objid;
|
obj.objectId = sdepForm->objid;
|
||||||
obj.objectSubId = sdepForm->objsubid;
|
obj.objectSubId = sdepForm->objsubid;
|
||||||
|
/*
|
||||||
|
* Acquire lock on object, then verify this dependency
|
||||||
|
* is still relevant. If not, the object might have
|
||||||
|
* been dropped or the policy modified. Ignore the
|
||||||
|
* object in that case.
|
||||||
|
*/
|
||||||
|
AcquireDeletionLock(&obj, 0);
|
||||||
|
if (!systable_recheck_tuple(scan, tuple))
|
||||||
|
{
|
||||||
|
ReleaseDeletionLock(&obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
add_exact_object_address(&obj, deleteobjs);
|
add_exact_object_address(&obj, deleteobjs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1342,6 +1357,13 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
|
|||||||
obj.classId = sdepForm->classid;
|
obj.classId = sdepForm->classid;
|
||||||
obj.objectId = sdepForm->objid;
|
obj.objectId = sdepForm->objid;
|
||||||
obj.objectSubId = sdepForm->objsubid;
|
obj.objectSubId = sdepForm->objsubid;
|
||||||
|
/* as above */
|
||||||
|
AcquireDeletionLock(&obj, 0);
|
||||||
|
if (!systable_recheck_tuple(scan, tuple))
|
||||||
|
{
|
||||||
|
ReleaseDeletionLock(&obj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
add_exact_object_address(&obj, deleteobjs);
|
add_exact_object_address(&obj, deleteobjs);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -915,7 +915,6 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
|
|||||||
if (slotname)
|
if (slotname)
|
||||||
PreventInTransactionBlock(isTopLevel, "DROP SUBSCRIPTION");
|
PreventInTransactionBlock(isTopLevel, "DROP SUBSCRIPTION");
|
||||||
|
|
||||||
|
|
||||||
ObjectAddressSet(myself, SubscriptionRelationId, subid);
|
ObjectAddressSet(myself, SubscriptionRelationId, subid);
|
||||||
EventTriggerSQLDropAddObject(&myself, true, true);
|
EventTriggerSQLDropAddObject(&myself, true, true);
|
||||||
|
|
||||||
|
@ -142,6 +142,10 @@ typedef enum ObjectClass
|
|||||||
|
|
||||||
/* in dependency.c */
|
/* in dependency.c */
|
||||||
|
|
||||||
|
extern void AcquireDeletionLock(const ObjectAddress *object, int flags);
|
||||||
|
|
||||||
|
extern void ReleaseDeletionLock(const ObjectAddress *object);
|
||||||
|
|
||||||
extern void performDeletion(const ObjectAddress *object,
|
extern void performDeletion(const ObjectAddress *object,
|
||||||
DropBehavior behavior, int flags);
|
DropBehavior behavior, int flags);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user