Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita5d4c04

Browse files
author
Amit Kapila
committed
Fix self-deadlock during DROP SUBSCRIPTION.
The DROP SUBSCRIPTION command performs several operations: it stops thesubscription workers, removes subscription-related entries from systemcatalogs, and deletes the replication slot on the publisher server.Previously, this command acquired an AccessExclusiveLock onpg_subscription before initiating these steps.However, while holding this lock, the command attempts to connect to thepublisher to remove the replication slot. In cases where the connection ismade to a newly created database on the same server as subscriber, thecache-building process during connection tries to acquire anAccessShareLock on pg_subscription, resulting in a self-deadlock.To resolve this issue, we reduce the lock level on pg_subscription duringDROP SUBSCRIPTION from AccessExclusiveLock to RowExclusiveLock. Earlier,the higher lock level was used to prevent the launcher from starting a newworker during the drop operation, as a restarted worker could becomeorphaned.Now, instead of relying on a strict lock, we acquire an AccessShareLock onthe specific subscription being dropped and re-validate its existenceafter acquiring the lock. If the subscription is no longer valid, theworker exits gracefully. This approach avoids the deadlock while stillensuring that orphan workers are not created.Reported-by: Alexander Lakhin <exclusion@gmail.com>Author: Dilip Kumar <dilipbalaut@gmail.com>Reviewed-by: vignesh C <vignesh21@gmail.com>Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>Backpatch-through: 13Discussion:https://postgr.es/m/18988-7312c868be2d467f@postgresql.org
1 parent4483dd9 commita5d4c04

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

‎src/backend/commands/subscriptioncmds.c‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,10 +1645,12 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
16451645
boolmust_use_password;
16461646

16471647
/*
1648-
* Lock pg_subscription with AccessExclusiveLock to ensure that the
1649-
* launcher doesn't restart new worker during dropping the subscription
1648+
* The launcher may concurrently start a new worker for this subscription.
1649+
* During initialization, the worker checks for subscription validity and
1650+
* exits if the subscription has already been dropped. See
1651+
* InitializeLogRepWorker.
16501652
*/
1651-
rel=table_open(SubscriptionRelationId,AccessExclusiveLock);
1653+
rel=table_open(SubscriptionRelationId,RowExclusiveLock);
16521654

16531655
tup=SearchSysCache2(SUBSCRIPTIONNAME,MyDatabaseId,
16541656
CStringGetDatum(stmt->subname));

‎src/backend/replication/logical/worker.c‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4682,6 +4682,13 @@ InitializeLogRepWorker(void)
46824682
StartTransactionCommand();
46834683
oldctx=MemoryContextSwitchTo(ApplyContext);
46844684

4685+
/*
4686+
* Lock the subscription to prevent it from being concurrently dropped,
4687+
* then re-verify its existence. After the initialization, the worker will
4688+
* be terminated gracefully if the subscription is dropped.
4689+
*/
4690+
LockSharedObject(SubscriptionRelationId,MyLogicalRepWorker->subid,0,
4691+
AccessShareLock);
46854692
MySubscription=GetSubscription(MyLogicalRepWorker->subid, true);
46864693
if (!MySubscription)
46874694
{

‎src/test/subscription/t/100_bugs.pl‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,34 @@ BEGIN
575575
$node_publisher->stop('fast');
576576
$node_subscriber->stop('fast');
577577

578+
# BUG #18988
579+
# The bug happened due to a self-deadlock between the DROP SUBSCRIPTION
580+
# command and the walsender process for accessing pg_subscription. This
581+
# occurred when DROP SUBSCRIPTION attempted to remove a replication slot by
582+
# connecting to a newly created database whose caches are not yet
583+
# initialized.
584+
#
585+
# The bug is fixed by reducing the lock-level during DROP SUBSCRIPTION.
586+
$node_publisher->start();
587+
588+
$publisher_connstr =$node_publisher->connstr .' dbname=regress_db';
589+
$node_publisher->safe_psql(
590+
'postgres',qq(
591+
CREATE DATABASE regress_db;
592+
CREATE SUBSCRIPTION regress_sub1 CONNECTION '$publisher_connstr' PUBLICATION regress_pub WITH (connect=false);
593+
));
594+
595+
my ($ret,$stdout,$stderr) =
596+
$node_publisher->psql('postgres',q{DROP SUBSCRIPTION regress_sub1});
597+
598+
isnt($ret, 0,"replication slot does not exist: exit code not 0");
599+
like(
600+
$stderr,
601+
qr/ERROR: could not drop replication slot "regress_sub1" on publisher/,
602+
"could not drop replication slot: error message");
603+
604+
$node_publisher->safe_psql('postgres',"DROP DATABASE regress_db");
605+
606+
$node_publisher->stop('fast');
607+
578608
done_testing();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp