Commit 993603fe authored by unknown's avatar unknown

lock0lock.c Fix slowness of deadlock detection algorithm

trx0trx.h	Fix slowness of deadlock detection algorithm


innobase/include/trx0trx.h:
  Fix slowness of deadlock detection algorithm
innobase/lock/lock0lock.c:
  Fix slowness of deadlock detection algorithm
parent aa161036
...@@ -397,6 +397,8 @@ struct trx_struct{ ...@@ -397,6 +397,8 @@ struct trx_struct{
wait_thrs; /* query threads belonging to this wait_thrs; /* query threads belonging to this
trx that are in the QUE_THR_LOCK_WAIT trx that are in the QUE_THR_LOCK_WAIT
state */ state */
ulint deadlock_mark; /* a mark field used in deadlock
checking algorithm */
/*------------------------------*/ /*------------------------------*/
mem_heap_t* lock_heap; /* memory heap for the locks of the mem_heap_t* lock_heap; /* memory heap for the locks of the
transaction; protected by transaction; protected by
......
...@@ -15,6 +15,10 @@ Created 5/7/1996 Heikki Tuuri ...@@ -15,6 +15,10 @@ Created 5/7/1996 Heikki Tuuri
#include "usr0sess.h" #include "usr0sess.h"
#include "trx0purge.h" #include "trx0purge.h"
/* Restricts the length of search we will do in the waits-for
graph of transactions */
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
/* When releasing transaction locks, this specifies how often we release /* When releasing transaction locks, this specifies how often we release
the kernel mutex for a moment to give also others access to it */ the kernel mutex for a moment to give also others access to it */
...@@ -312,11 +316,14 @@ static ...@@ -312,11 +316,14 @@ static
ibool ibool
lock_deadlock_recursive( lock_deadlock_recursive(
/*====================*/ /*====================*/
/* out: TRUE if a deadlock was detected */ /* out: TRUE if a deadlock was detected
or the calculation took too long */
trx_t* start, /* in: recursion starting point */ trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */ trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock); /* in: the lock trx is waiting to be granted */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost); /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return TRUE */
/************************************************************************* /*************************************************************************
Reserves the kernel mutex. This function is used in this module to allow Reserves the kernel mutex. This function is used in this module to allow
monitoring the contention degree on the kernel mutex caused by the lock monitoring the contention degree on the kernel mutex caused by the lock
...@@ -2655,12 +2662,25 @@ lock_deadlock_occurs( ...@@ -2655,12 +2662,25 @@ lock_deadlock_occurs(
{ {
dict_table_t* table; dict_table_t* table;
dict_index_t* index; dict_index_t* index;
trx_t* mark_trx;
ibool ret; ibool ret;
ulint cost = 0;
ut_ad(trx && lock); ut_ad(trx && lock);
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ret = lock_deadlock_recursive(trx, trx, lock); /* We check that adding this trx to the waits-for graph
does not produce a cycle. First mark all active transactions
with 0: */
mark_trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
while (mark_trx) {
mark_trx->deadlock_mark = 0;
mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx);
}
ret = lock_deadlock_recursive(trx, trx, lock, &cost);
if (ret) { if (ret) {
if (lock_get_type(lock) == LOCK_TABLE) { if (lock_get_type(lock) == LOCK_TABLE) {
...@@ -2685,10 +2705,14 @@ static ...@@ -2685,10 +2705,14 @@ static
ibool ibool
lock_deadlock_recursive( lock_deadlock_recursive(
/*====================*/ /*====================*/
/* out: TRUE if a deadlock was detected */ /* out: TRUE if a deadlock was detected
or the calculation took too long */
trx_t* start, /* in: recursion starting point */ trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */ trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock) /* in: the lock trx is waiting to be granted */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost) /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return TRUE */
{ {
lock_t* lock; lock_t* lock;
ulint bit_no; ulint bit_no;
...@@ -2697,6 +2721,20 @@ lock_deadlock_recursive( ...@@ -2697,6 +2721,20 @@ lock_deadlock_recursive(
ut_a(trx && start && wait_lock); ut_a(trx && start && wait_lock);
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
if (trx->deadlock_mark == 1) {
/* We have already exhaustively searched the subtree starting
from this trx */
return(FALSE);
}
*cost = *cost + 1;
if (*cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK) {
return(TRUE);
}
lock = wait_lock; lock = wait_lock;
if (lock_get_type(wait_lock) == LOCK_REC) { if (lock_get_type(wait_lock) == LOCK_REC) {
...@@ -2719,6 +2757,8 @@ lock_deadlock_recursive( ...@@ -2719,6 +2757,8 @@ lock_deadlock_recursive(
} }
if (lock == NULL) { if (lock == NULL) {
/* We can mark this subtree as searched */
trx->deadlock_mark = 1;
return(FALSE); return(FALSE);
} }
...@@ -2742,7 +2782,7 @@ lock_deadlock_recursive( ...@@ -2742,7 +2782,7 @@ lock_deadlock_recursive(
a lock */ a lock */
if (lock_deadlock_recursive(start, lock_trx, if (lock_deadlock_recursive(start, lock_trx,
lock_trx->wait_lock)) { lock_trx->wait_lock, cost)) {
return(TRUE); return(TRUE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment