mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 04:53:01 +01:00
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.
This commit is contained in:
parent
6d4e34cabb
commit
167888c6c3
1 changed files with 63 additions and 35 deletions
|
@ -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(
|
||||||
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(
|
||||||
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 @@ retry:
|
||||||
|
|
||||||
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. */
|
||||||
} else {
|
rewind(lock_latest_err_file);
|
||||||
index = lock->index;
|
ut_print_timestamp(lock_latest_err_file);
|
||||||
table = index->table;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_deadlock_found = TRUE;
|
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
|
||||||
|
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
|
||||||
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
|
" FOLLOWING TRANSACTION \n",
|
||||||
lock_latest_err_file);
|
lock_latest_err_file);
|
||||||
|
|
||||||
return(TRUE);
|
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 {
|
||||||
|
lock_table_print(lock_latest_err_file, lock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCK_VICTIM_IS_START:
|
||||||
|
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
|
||||||
|
lock_latest_err_file);
|
||||||
|
break;
|
||||||
|
|
||||||
|
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
|
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(
|
||||||
|
|
||||||
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(
|
||||||
}
|
}
|
||||||
#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(
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue