mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Only kill sync workers at commit time in subscription DDL
This allows a transaction abort to avoid killing those workers. Author: Petr Jelinek <petr.jelinek@2ndquadrant.com>
This commit is contained in:
parent
ff98a5e1e4
commit
7e174fa793
@ -2277,6 +2277,15 @@ PrepareTransaction(void)
|
|||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot PREPARE a transaction that has exported snapshots")));
|
errmsg("cannot PREPARE a transaction that has exported snapshots")));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't allow PREPARE but for transaction that has/might kill logical
|
||||||
|
* replication workers.
|
||||||
|
*/
|
||||||
|
if (XactManipulatesLogicalReplicationWorkers())
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("cannot PREPARE a transaction that has manipulated logical replication workers")));
|
||||||
|
|
||||||
/* Prevent cancel/die interrupt while cleaning up */
|
/* Prevent cancel/die interrupt while cleaning up */
|
||||||
HOLD_INTERRUPTS();
|
HOLD_INTERRUPTS();
|
||||||
|
|
||||||
|
@ -597,7 +597,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
|
|||||||
|
|
||||||
RemoveSubscriptionRel(sub->oid, relid);
|
RemoveSubscriptionRel(sub->oid, relid);
|
||||||
|
|
||||||
logicalrep_worker_stop(sub->oid, relid);
|
logicalrep_worker_stop_at_commit(sub->oid, relid);
|
||||||
|
|
||||||
namespace = get_namespace_name(get_rel_namespace(relid));
|
namespace = get_namespace_name(get_rel_namespace(relid));
|
||||||
ereport(NOTICE,
|
ereport(NOTICE,
|
||||||
@ -819,6 +819,8 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
|
|||||||
char *subname;
|
char *subname;
|
||||||
char *conninfo;
|
char *conninfo;
|
||||||
char *slotname;
|
char *slotname;
|
||||||
|
List *subworkers;
|
||||||
|
ListCell *lc;
|
||||||
char originname[NAMEDATALEN];
|
char originname[NAMEDATALEN];
|
||||||
char *err = NULL;
|
char *err = NULL;
|
||||||
RepOriginId originid;
|
RepOriginId originid;
|
||||||
@ -909,15 +911,33 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
|
|||||||
|
|
||||||
ReleaseSysCache(tup);
|
ReleaseSysCache(tup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are dropping the replication slot, stop all the subscription
|
||||||
|
* workers immediately, so that the slot becomes accessible. Otherwise
|
||||||
|
* just schedule the stopping for the end of the transaction.
|
||||||
|
*
|
||||||
|
* New workers won't be started because we hold an exclusive lock on the
|
||||||
|
* subscription till the end of the transaction.
|
||||||
|
*/
|
||||||
|
LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
|
||||||
|
subworkers = logicalrep_workers_find(subid, false);
|
||||||
|
LWLockRelease(LogicalRepWorkerLock);
|
||||||
|
foreach (lc, subworkers)
|
||||||
|
{
|
||||||
|
LogicalRepWorker *w = (LogicalRepWorker *) lfirst(lc);
|
||||||
|
if (slotname)
|
||||||
|
logicalrep_worker_stop(w->subid, w->relid);
|
||||||
|
else
|
||||||
|
logicalrep_worker_stop_at_commit(w->subid, w->relid);
|
||||||
|
}
|
||||||
|
list_free(subworkers);
|
||||||
|
|
||||||
/* Clean up dependencies */
|
/* Clean up dependencies */
|
||||||
deleteSharedDependencyRecordsFor(SubscriptionRelationId, subid, 0);
|
deleteSharedDependencyRecordsFor(SubscriptionRelationId, subid, 0);
|
||||||
|
|
||||||
/* Remove any associated relation synchronization states. */
|
/* Remove any associated relation synchronization states. */
|
||||||
RemoveSubscriptionRel(subid, InvalidOid);
|
RemoveSubscriptionRel(subid, InvalidOid);
|
||||||
|
|
||||||
/* Kill the apply worker so that the slot becomes accessible. */
|
|
||||||
logicalrep_worker_stop(subid, InvalidOid);
|
|
||||||
|
|
||||||
/* Remove the origin tracking if exists. */
|
/* Remove the origin tracking if exists. */
|
||||||
snprintf(originname, sizeof(originname), "pg_%u", subid);
|
snprintf(originname, sizeof(originname), "pg_%u", subid);
|
||||||
originid = replorigin_by_name(originname, true);
|
originid = replorigin_by_name(originname, true);
|
||||||
|
@ -73,6 +73,14 @@ typedef struct LogicalRepCtxStruct
|
|||||||
|
|
||||||
LogicalRepCtxStruct *LogicalRepCtx;
|
LogicalRepCtxStruct *LogicalRepCtx;
|
||||||
|
|
||||||
|
typedef struct LogicalRepWorkerId
|
||||||
|
{
|
||||||
|
Oid subid;
|
||||||
|
Oid relid;
|
||||||
|
} LogicalRepWorkerId;
|
||||||
|
|
||||||
|
static List *on_commit_stop_workers = NIL;
|
||||||
|
|
||||||
static void ApplyLauncherWakeup(void);
|
static void ApplyLauncherWakeup(void);
|
||||||
static void logicalrep_launcher_onexit(int code, Datum arg);
|
static void logicalrep_launcher_onexit(int code, Datum arg);
|
||||||
static void logicalrep_worker_onexit(int code, Datum arg);
|
static void logicalrep_worker_onexit(int code, Datum arg);
|
||||||
@ -249,6 +257,30 @@ logicalrep_worker_find(Oid subid, Oid relid, bool only_running)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Similar to logicalrep_worker_find(), but returns list of all workers for
|
||||||
|
* the subscription, instead just one.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
logicalrep_workers_find(Oid subid, bool only_running)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
List *res = NIL;
|
||||||
|
|
||||||
|
Assert(LWLockHeldByMe(LogicalRepWorkerLock));
|
||||||
|
|
||||||
|
/* Search for attached worker for a given subscription id. */
|
||||||
|
for (i = 0; i < max_logical_replication_workers; i++)
|
||||||
|
{
|
||||||
|
LogicalRepWorker *w = &LogicalRepCtx->workers[i];
|
||||||
|
|
||||||
|
if (w->in_use && w->subid == subid && (!only_running || w->proc))
|
||||||
|
res = lappend(res, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start new apply background worker.
|
* Start new apply background worker.
|
||||||
*/
|
*/
|
||||||
@ -513,6 +545,27 @@ logicalrep_worker_stop(Oid subid, Oid relid)
|
|||||||
LWLockRelease(LogicalRepWorkerLock);
|
LWLockRelease(LogicalRepWorkerLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request worker for specified sub/rel to be stopped on commit.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
logicalrep_worker_stop_at_commit(Oid subid, Oid relid)
|
||||||
|
{
|
||||||
|
LogicalRepWorkerId *wid;
|
||||||
|
MemoryContext oldctx;
|
||||||
|
|
||||||
|
/* Make sure we store the info in context that survives until commit. */
|
||||||
|
oldctx = MemoryContextSwitchTo(TopTransactionContext);
|
||||||
|
|
||||||
|
wid = palloc(sizeof(LogicalRepWorkerId));
|
||||||
|
wid->subid = subid;
|
||||||
|
wid->relid = relid;
|
||||||
|
|
||||||
|
on_commit_stop_workers = lappend(on_commit_stop_workers, wid);
|
||||||
|
|
||||||
|
MemoryContextSwitchTo(oldctx);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wake up (using latch) any logical replication worker for specified sub/rel.
|
* Wake up (using latch) any logical replication worker for specified sub/rel.
|
||||||
*/
|
*/
|
||||||
@ -753,15 +806,41 @@ ApplyLauncherShmemInit(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether current transaction has manipulated logical replication
|
||||||
|
* workers.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
XactManipulatesLogicalReplicationWorkers(void)
|
||||||
|
{
|
||||||
|
return (on_commit_stop_workers != NIL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wakeup the launcher on commit if requested.
|
* Wakeup the launcher on commit if requested.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
AtEOXact_ApplyLauncher(bool isCommit)
|
AtEOXact_ApplyLauncher(bool isCommit)
|
||||||
{
|
{
|
||||||
if (isCommit && on_commit_launcher_wakeup)
|
if (isCommit)
|
||||||
ApplyLauncherWakeup();
|
{
|
||||||
|
ListCell *lc;
|
||||||
|
|
||||||
|
foreach (lc, on_commit_stop_workers)
|
||||||
|
{
|
||||||
|
LogicalRepWorkerId *wid = lfirst(lc);
|
||||||
|
logicalrep_worker_stop(wid->subid, wid->relid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on_commit_launcher_wakeup)
|
||||||
|
ApplyLauncherWakeup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No need to pfree on_commit_stop_workers. It was allocated in
|
||||||
|
* transaction memory context, which is going to be cleaned soon.
|
||||||
|
*/
|
||||||
|
on_commit_stop_workers = NIL;
|
||||||
on_commit_launcher_wakeup = false;
|
on_commit_launcher_wakeup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ extern Size ApplyLauncherShmemSize(void);
|
|||||||
extern void ApplyLauncherShmemInit(void);
|
extern void ApplyLauncherShmemInit(void);
|
||||||
|
|
||||||
extern void ApplyLauncherWakeupAtCommit(void);
|
extern void ApplyLauncherWakeupAtCommit(void);
|
||||||
|
extern bool XactManipulatesLogicalReplicationWorkers(void);
|
||||||
extern void AtEOXact_ApplyLauncher(bool isCommit);
|
extern void AtEOXact_ApplyLauncher(bool isCommit);
|
||||||
|
|
||||||
extern bool IsLogicalLauncher(void);
|
extern bool IsLogicalLauncher(void);
|
||||||
|
@ -71,9 +71,11 @@ extern bool in_remote_transaction;
|
|||||||
extern void logicalrep_worker_attach(int slot);
|
extern void logicalrep_worker_attach(int slot);
|
||||||
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
|
extern LogicalRepWorker *logicalrep_worker_find(Oid subid, Oid relid,
|
||||||
bool only_running);
|
bool only_running);
|
||||||
|
extern List *logicalrep_workers_find(Oid subid, bool only_running);
|
||||||
extern void logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
|
extern void logicalrep_worker_launch(Oid dbid, Oid subid, const char *subname,
|
||||||
Oid userid, Oid relid);
|
Oid userid, Oid relid);
|
||||||
extern void logicalrep_worker_stop(Oid subid, Oid relid);
|
extern void logicalrep_worker_stop(Oid subid, Oid relid);
|
||||||
|
extern void logicalrep_worker_stop_at_commit(Oid subid, Oid relid);
|
||||||
extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
|
extern void logicalrep_worker_wakeup(Oid subid, Oid relid);
|
||||||
extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
|
extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user