|
|
@ -8,7 +8,7 @@ |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* |
|
|
|
* IDENTIFICATION |
|
|
|
* IDENTIFICATION |
|
|
|
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.184 2007/02/15 23:23:23 alvherre Exp $ |
|
|
|
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.185 2007/03/03 18:46:40 momjian Exp $ |
|
|
|
* |
|
|
|
* |
|
|
|
*------------------------------------------------------------------------- |
|
|
|
*------------------------------------------------------------------------- |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -48,6 +48,7 @@ |
|
|
|
/* GUC variables */ |
|
|
|
/* GUC variables */ |
|
|
|
int DeadlockTimeout = 1000; |
|
|
|
int DeadlockTimeout = 1000; |
|
|
|
int StatementTimeout = 0; |
|
|
|
int StatementTimeout = 0; |
|
|
|
|
|
|
|
bool log_lock_waits = false; |
|
|
|
|
|
|
|
|
|
|
|
/* Pointer to this process's PGPROC struct, if any */ |
|
|
|
/* Pointer to this process's PGPROC struct, if any */ |
|
|
|
PGPROC *MyProc = NULL; |
|
|
|
PGPROC *MyProc = NULL; |
|
|
@ -979,6 +980,7 @@ static void |
|
|
|
CheckDeadLock(void) |
|
|
|
CheckDeadLock(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
DeadlockState deadlock_state = DS_DEADLOCK_NOT_FOUND; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Acquire exclusive lock on the entire shared lock data structures. Must |
|
|
|
* Acquire exclusive lock on the entire shared lock data structures. Must |
|
|
@ -1004,21 +1006,12 @@ CheckDeadLock(void) |
|
|
|
* This is quicker than checking our semaphore's state, since no kernel |
|
|
|
* This is quicker than checking our semaphore's state, since no kernel |
|
|
|
* call is needed, and it is safe because we hold the lock partition lock. |
|
|
|
* call is needed, and it is safe because we hold the lock partition lock. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (MyProc->links.prev == INVALID_OFFSET || |
|
|
|
if (MyProc->links.prev != INVALID_OFFSET && |
|
|
|
MyProc->links.next == INVALID_OFFSET) |
|
|
|
MyProc->links.next != INVALID_OFFSET) |
|
|
|
goto check_done; |
|
|
|
deadlock_state = DeadLockCheck(MyProc); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef LOCK_DEBUG |
|
|
|
if (deadlock_state == DS_HARD_DEADLOCK) |
|
|
|
if (Debug_deadlocks) |
|
|
|
|
|
|
|
DumpAllLocks(); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!DeadLockCheck(MyProc)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
/* No deadlock, so keep waiting */ |
|
|
|
|
|
|
|
goto check_done; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Oops. We have a deadlock. |
|
|
|
* Oops. We have a deadlock. |
|
|
|
* |
|
|
|
* |
|
|
@ -1049,15 +1042,41 @@ CheckDeadLock(void) |
|
|
|
* them anymore. However, RemoveFromWaitQueue took care of waking up any |
|
|
|
* them anymore. However, RemoveFromWaitQueue took care of waking up any |
|
|
|
* such processes. |
|
|
|
* such processes. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Release locks acquired at head of routine. Order is not critical, so |
|
|
|
* Release locks acquired at head of routine. Order is not critical, so |
|
|
|
* do it back-to-front to avoid waking another CheckDeadLock instance |
|
|
|
* do it back-to-front to avoid waking another CheckDeadLock instance |
|
|
|
* before it can get all the locks. |
|
|
|
* before it can get all the locks. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
check_done: |
|
|
|
|
|
|
|
for (i = NUM_LOCK_PARTITIONS; --i >= 0;) |
|
|
|
for (i = NUM_LOCK_PARTITIONS; --i >= 0;) |
|
|
|
LWLockRelease(FirstLockMgrLock + i); |
|
|
|
LWLockRelease(FirstLockMgrLock + i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Issue any log messages requested. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Deadlock ERROR messages are issued as part of transaction abort, so
|
|
|
|
|
|
|
|
* these messages should not raise error states intentionally. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (log_lock_waits) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
switch (deadlock_state) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case DS_SOFT_DEADLOCK: |
|
|
|
|
|
|
|
ereport(LOG, |
|
|
|
|
|
|
|
(errmsg("deadlock avoided by rearranging lock order"))); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case DS_DEADLOCK_NOT_FOUND: |
|
|
|
|
|
|
|
ereport(LOG, |
|
|
|
|
|
|
|
(errmsg("statement waiting for lock for at least %d ms", |
|
|
|
|
|
|
|
DeadlockTimeout))); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case DS_HARD_DEADLOCK: |
|
|
|
|
|
|
|
break; /* ERROR message handled during abort */ |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|