Commit 7201c801 authored by jyang's avatar jyang

branches/5.1: Fix bug #49001, "SHOW INNODB STATUS deadlock info

incorrect when deadlock detection aborts". Print the correct
lock owner when recursive function lock_deadlock_recursive()
exceeds its maximum depth LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK.

rb://217, approved by Marko.
parent 1a866c2c
...@@ -306,6 +306,7 @@ FILE* lock_latest_err_file; ...@@ -306,6 +306,7 @@ FILE* lock_latest_err_file;
/* Flags for recursive deadlock search */ /* Flags for recursive deadlock search */
#define LOCK_VICTIM_IS_START 1 #define LOCK_VICTIM_IS_START 1
#define LOCK_VICTIM_IS_OTHER 2 #define LOCK_VICTIM_IS_OTHER 2
#define LOCK_EXCEED_MAX_DEPTH 3
/************************************************************************ /************************************************************************
Checks if a lock request results in a deadlock. */ Checks if a lock request results in a deadlock. */
...@@ -332,16 +333,18 @@ lock_deadlock_recursive( ...@@ -332,16 +333,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a was found and we chose some other trx as a
victim: we must do the search again in this victim: we must do the search again in this
last case because there may be another last case because there may be another
deadlock! */ deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
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 ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_... far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */ we return LOCK_EXCEED_MAX_DEPTH */
ulint depth); /* in: recursion depth: if this exceeds ulint depth); /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */ return LOCK_EXCEED_MAX_DEPTH */
/************************************************************************* /*************************************************************************
Gets the nth bit of a record lock. */ Gets the nth bit of a record lock. */
...@@ -3084,8 +3087,6 @@ lock_deadlock_occurs( ...@@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
lock_t* lock, /* in: lock the transaction is requesting */ lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx) /* in: transaction */ trx_t* trx) /* in: transaction */
{ {
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx; trx_t* mark_trx;
ulint ret; ulint ret;
ulint cost = 0; ulint cost = 0;
...@@ -3107,31 +3108,50 @@ lock_deadlock_occurs( ...@@ -3107,31 +3108,50 @@ lock_deadlock_occurs(
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0); ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
if (ret == LOCK_VICTIM_IS_OTHER) { switch (ret) {
case LOCK_VICTIM_IS_OTHER:
/* We chose some other trx as a victim: retry if there still /* We chose some other trx as a victim: retry if there still
is a deadlock */ is a deadlock */
goto retry; goto retry;
}
if (ret == LOCK_VICTIM_IS_START) { case LOCK_EXCEED_MAX_DEPTH:
if (lock_get_type(lock) & LOCK_TABLE) { /* If the lock search exceeds the max step
table = lock->un_member.tab_lock.table; or the max depth, the current trx will be
index = NULL; the victim. Print its information. */
rewind(lock_latest_err_file);
ut_print_timestamp(lock_latest_err_file);
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
" FOLLOWING TRANSACTION \n",
lock_latest_err_file);
fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
trx_print(lock_latest_err_file, trx, 3000);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
lock_latest_err_file);
if (lock_get_type(lock) == LOCK_REC) {
lock_rec_print(lock_latest_err_file, lock);
} else { } else {
index = lock->index; lock_table_print(lock_latest_err_file, lock);
table = index->table;
} }
break;
lock_deadlock_found = TRUE; case LOCK_VICTIM_IS_START:
fputs("*** WE ROLL BACK TRANSACTION (2)\n", fputs("*** WE ROLL BACK TRANSACTION (2)\n",
lock_latest_err_file); lock_latest_err_file);
break;
return(TRUE); default:
/* No deadlock detected*/
return(FALSE);
} }
return(FALSE); lock_deadlock_found = TRUE;
return(TRUE);
} }
/************************************************************************ /************************************************************************
...@@ -3147,16 +3167,18 @@ lock_deadlock_recursive( ...@@ -3147,16 +3167,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a was found and we chose some other trx as a
victim: we must do the search again in this victim: we must do the search again in this
last case because there may be another last case because there may be another
deadlock! */ deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
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 ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_... far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */ we return LOCK_EXCEED_MAX_DEPTH */
ulint depth) /* in: recursion depth: if this exceeds ulint depth) /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */ return LOCK_EXCEED_MAX_DEPTH */
{ {
lock_t* lock; lock_t* lock;
ulint bit_no = ULINT_UNDEFINED; ulint bit_no = ULINT_UNDEFINED;
...@@ -3215,7 +3237,7 @@ lock_deadlock_recursive( ...@@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
lock_trx = lock->trx; lock_trx = lock->trx;
if (lock_trx == start || too_far) { if (lock_trx == start) {
/* We came back to the recursion starting /* We came back to the recursion starting
point: a deadlock detected; or we have point: a deadlock detected; or we have
...@@ -3262,19 +3284,10 @@ lock_deadlock_recursive( ...@@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (lock_print_waits) { if (lock_print_waits) {
fputs("Deadlock detected" fputs("Deadlock detected\n",
" or too long search\n",
stderr); stderr);
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
if (too_far) {
fputs("TOO DEEP OR LONG SEARCH"
" IN THE LOCK TABLE"
" WAITS-FOR GRAPH\n", ef);
return(LOCK_VICTIM_IS_START);
}
if (trx_weight_cmp(wait_lock->trx, if (trx_weight_cmp(wait_lock->trx,
start) >= 0) { start) >= 0) {
...@@ -3310,6 +3323,21 @@ lock_deadlock_recursive( ...@@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
return(LOCK_VICTIM_IS_OTHER); return(LOCK_VICTIM_IS_OTHER);
} }
if (too_far) {
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock search exceeds"
" max steps or depth.\n",
stderr);
}
#endif /* UNIV_DEBUG */
/* The information about transaction/lock
to be rolled back is available in the top
level. Do not print anything here. */
return(LOCK_EXCEED_MAX_DEPTH);
}
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) { if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
/* Another trx ahead has requested lock in an /* Another trx ahead has requested lock in an
......
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