1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Allow an autovacuum worker to be interrupted automatically when it is found

to be locking another process (except when it's working to prevent Xid
wraparound problems).
This commit is contained in:
Alvaro Herrera
2007-10-26 20:45:10 +00:00
parent ffda32e9fd
commit acac68b2bc
5 changed files with 114 additions and 7 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.195 2007/10/24 20:55:36 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.196 2007/10/26 20:45:10 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@ -734,6 +734,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
PROC_QUEUE *waitQueue = &(lock->waitProcs);
LOCKMASK myHeldLocks = MyProc->heldLocks;
bool early_deadlock = false;
bool allow_autovacuum_cancel = true;
int myWaitStatus;
PGPROC *proc;
int i;
@ -893,6 +894,48 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
*/
myWaitStatus = MyProc->waitStatus;
/*
* If we are not deadlocked, but are waiting on an autovacuum-induced
* task, send a signal to interrupt it.
*/
if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
{
PGPROC *autovac = GetBlockingAutoVacuumPgproc();
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
/*
* Only do it if the worker is not working to protect against Xid
* wraparound.
*/
if ((autovac != NULL) &&
(autovac->vacuumFlags & PROC_IS_AUTOVACUUM) &&
!(autovac->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND))
{
int pid = autovac->pid;
elog(DEBUG2, "sending cancel to blocking autovacuum pid = %d",
pid);
/* don't hold the lock across the kill() syscall */
LWLockRelease(ProcArrayLock);
/* send the autovacuum worker Back to Old Kent Road */
if (kill(pid, SIGINT) < 0)
{
/* Just a warning to allow multiple callers */
ereport(WARNING,
(errmsg("could not send signal to process %d: %m",
pid)));
}
}
else
LWLockRelease(ProcArrayLock);
/* prevent signal from being resent more than once */
allow_autovacuum_cancel = false;
}
/*
* If awoken after the deadlock check interrupt has run, and
* log_lock_waits is on, then report about the wait.
@ -1189,13 +1232,16 @@ CheckDeadLock(void)
* RemoveFromWaitQueue took care of waking up any such processes.
*/
}
else if (log_lock_waits)
else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM)
{
/*
* Unlock my semaphore so that the interrupted ProcSleep() call can
* print the log message (we daren't do it here because we are inside
* a signal handler). It will then sleep again until someone
* releases the lock.
*
* If blocked by autovacuum, this wakeup will enable ProcSleep to send
* the cancelling signal to the autovacuum worker.
*/
PGSemaphoreUnlock(&MyProc->sem);
}