Commit 167888c6 authored by Sergey Vojtovich's avatar Sergey Vojtovich

Applying InnoDB snapshot, fixes BUG#49001

Detailed revision comments:

r6545 | jyang | 2010-02-03 03:57:32 +0200 (Wed, 03 Feb 2010) | 8 lines
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 6d4e34ca
......@@ -306,6 +306,7 @@ FILE* lock_latest_err_file;
/* Flags for recursive deadlock search */
#define LOCK_VICTIM_IS_START 1
#define LOCK_VICTIM_IS_OTHER 2
#define LOCK_EXCEED_MAX_DEPTH 3
/************************************************************************
Checks if a lock request results in a deadlock. */
......@@ -332,16 +333,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a
victim: we must do the search again in this
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* trx, /* in: a transaction waiting for a lock */
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 LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth); /* in: recursion depth: if this exceeds
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. */
......@@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx) /* in: transaction */
{
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx;
ulint ret;
ulint cost = 0;
......@@ -3107,31 +3108,50 @@ lock_deadlock_occurs(
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
is a deadlock */
goto retry;
}
if (ret == LOCK_VICTIM_IS_START) {
if (lock_get_type(lock) & LOCK_TABLE) {
table = lock->un_member.tab_lock.table;
index = NULL;
case LOCK_EXCEED_MAX_DEPTH:
/* If the lock search exceeds the max step
or the max depth, the current trx will be
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 {
index = lock->index;
table = index->table;
lock_table_print(lock_latest_err_file, lock);
}
break;
lock_deadlock_found = TRUE;
case LOCK_VICTIM_IS_START:
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
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(
was found and we chose some other trx as a
victim: we must do the search again in this
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* trx, /* in: a transaction waiting for a lock */
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 LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth) /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
return LOCK_EXCEED_MAX_DEPTH */
{
lock_t* lock;
ulint bit_no = ULINT_UNDEFINED;
......@@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
lock_trx = lock->trx;
if (lock_trx == start || too_far) {
if (lock_trx == start) {
/* We came back to the recursion starting
point: a deadlock detected; or we have
......@@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
}
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock detected"
" or too long search\n",
fputs("Deadlock detected\n",
stderr);
}
#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,
start) >= 0) {
......@@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
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) {
/* 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