From fc50b9e287e8c3c29be21d82c07c39023cbf3882 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 23 Jun 2017 21:26:46 -0400 Subject: [PATCH v2] Parametrize locking in RemoveSubscriptionRel Revising the change in 521fd4795e3ec3d0b263b62e5eb58e1557be9c86, we need to take a stronger lock when removing entries from pg_subscription_rel when ALTER/DROP SUBSCRIPTION. Otherwise, users might see "tuple concurrently updated" when table sync workers make updates at the same time as DDL commands are run. For DROP TABLE, we keep the lower lock level that was put in place by the above commit, so that DROP TABLE does not deadlock with whole-database VACUUM. --- src/backend/catalog/heap.c | 2 +- src/backend/catalog/pg_subscription.c | 6 +++--- src/backend/commands/subscriptioncmds.c | 4 ++-- src/include/catalog/pg_subscription_rel.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index a376b99f1e..8a96bbece6 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -1844,7 +1844,7 @@ heap_drop_with_catalog(Oid relid) /* * Remove any associated relation synchronization states. */ - RemoveSubscriptionRel(InvalidOid, relid); + RemoveSubscriptionRel(InvalidOid, relid, RowExclusiveLock); /* * Forget any ON COMMIT action for the rel diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c index c69c461b62..1d80191ca8 100644 --- a/src/backend/catalog/pg_subscription.c +++ b/src/backend/catalog/pg_subscription.c @@ -369,7 +369,7 @@ GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn, * subscription, or for a particular relation, or both. */ void -RemoveSubscriptionRel(Oid subid, Oid relid) +RemoveSubscriptionRel(Oid subid, Oid relid, LOCKMODE lockmode) { Relation rel; HeapScanDesc scan; @@ -377,7 +377,7 @@ RemoveSubscriptionRel(Oid subid, Oid relid) HeapTuple tup; int nkeys = 0; - rel = heap_open(SubscriptionRelRelationId, RowExclusiveLock); + rel = heap_open(SubscriptionRelRelationId, lockmode); if (OidIsValid(subid)) { @@ -405,7 +405,7 @@ RemoveSubscriptionRel(Oid subid, Oid relid) } heap_endscan(scan); - heap_close(rel, RowExclusiveLock); + heap_close(rel, NoLock); } diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 9cbd36f646..57954c978b 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -595,7 +595,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data) { char *namespace; - RemoveSubscriptionRel(sub->oid, relid); + RemoveSubscriptionRel(sub->oid, relid, ShareRowExclusiveLock); logicalrep_worker_stop(sub->oid, relid); @@ -910,7 +910,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) deleteSharedDependencyRecordsFor(SubscriptionRelationId, subid, 0); /* Remove any associated relation synchronization states. */ - RemoveSubscriptionRel(subid, InvalidOid); + RemoveSubscriptionRel(subid, InvalidOid, ShareRowExclusiveLock); /* Kill the apply worker so that the slot becomes accessible. */ logicalrep_worker_stop(subid, InvalidOid); diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h index 991ca9d552..a1f1db08d0 100644 --- a/src/include/catalog/pg_subscription_rel.h +++ b/src/include/catalog/pg_subscription_rel.h @@ -74,7 +74,7 @@ extern Oid SetSubscriptionRelState(Oid subid, Oid relid, char state, XLogRecPtr sublsn, bool update_only); extern char GetSubscriptionRelState(Oid subid, Oid relid, XLogRecPtr *sublsn, bool missing_ok); -extern void RemoveSubscriptionRel(Oid subid, Oid relid); +extern void RemoveSubscriptionRel(Oid subid, Oid relid, LOCKMODE lockmode); extern List *GetSubscriptionRelations(Oid subid); extern List *GetSubscriptionNotReadyRelations(Oid subid); -- 2.13.1