Commit 286dc23a authored by Sergey Vojtovich's avatar Sergey Vojtovich

Applying InnoDB snapshot

Detailed revision comments:

r6633 | marko | 2010-02-10 10:40:55 +0200 (Wed, 10 Feb 2010) | 31 lines
branches/zip: Merge revisions 6538:6613 from branches/5.1:

  ------------------------------------------------------------------------
  r6545 | jyang | 2010-02-03 03:57:32 +0200 (Wed, 03 Feb 2010) | 8 lines
  Changed paths:
     M /branches/5.1/lock/lock0lock.c

  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.
  ------------------------------------------------------------------------
  r6613 | inaam | 2010-02-09 20:23:09 +0200 (Tue, 09 Feb 2010) | 11 lines
  Changed paths:
     M /branches/5.1/buf/buf0buf.c
     M /branches/5.1/buf/buf0rea.c
     M /branches/5.1/include/buf0rea.h

  branches/5.1: Fix Bug #38901
  InnoDB logs error repeatedly when trying to load page into buffer pool

  In buf_page_get_gen() if we are unable to read a page (because of
  corruption or some other reason) we keep on retrying. This fills up
  error log with millions of entries in no time and we'd eventually run
  out of disk space. This patch limits the number of attempts that we
  make (currently set to 100) and after that we abort with a message.

  rb://241 Approved by: Heikki
  ------------------------------------------------------------------------
parent 14a3a2b4
2010-02-09 The InnoDB Team
* buf/buf0buf.c:
Fix Bug #38901 InnoDB logs error repeatedly when trying to load
page into buffer pool
2010-02-09 The InnoDB Team 2010-02-09 The InnoDB Team
* srv/srv0srv.c: * srv/srv0srv.c:
...@@ -13,6 +19,12 @@ ...@@ -13,6 +19,12 @@
b-tree cursor functions to the buffer pool requests, in order b-tree cursor functions to the buffer pool requests, in order
to make the latch diagnostics more accurate. to make the latch diagnostics more accurate.
2010-02-03 The InnoDB Team
* lock/lock0lock.c:
Fix Bug#49001 SHOW INNODB STATUS deadlock info incorrect
when deadlock detection aborts
2010-02-03 The InnoDB Team 2010-02-03 The InnoDB Team
* buf/buf0lru.c: * buf/buf0lru.c:
......
...@@ -242,6 +242,8 @@ the read requests for the whole area. ...@@ -242,6 +242,8 @@ the read requests for the whole area.
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/** Value in microseconds */ /** Value in microseconds */
static const int WAIT_FOR_READ = 5000; static const int WAIT_FOR_READ = 5000;
/** Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
/** The buffer buf_pool of the database */ /** The buffer buf_pool of the database */
UNIV_INTERN buf_pool_t* buf_pool = NULL; UNIV_INTERN buf_pool_t* buf_pool = NULL;
...@@ -2036,6 +2038,7 @@ buf_page_get_gen( ...@@ -2036,6 +2038,7 @@ buf_page_get_gen(
unsigned access_time; unsigned access_time;
ulint fix_type; ulint fix_type;
ibool must_read; ibool must_read;
ulint retries = 0;
ut_ad(mtr); ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) ut_ad((rw_latch == RW_S_LATCH)
...@@ -2090,7 +2093,29 @@ loop2: ...@@ -2090,7 +2093,29 @@ loop2:
return(NULL); return(NULL);
} }
buf_read_page(space, zip_size, offset); if (buf_read_page(space, zip_size, offset)) {
retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
} else {
fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
"InnoDB: The most probable cause"
" of this error may be that the"
" table has been corrupted.\n"
"InnoDB: You can try to fix this"
" problem by using"
" innodb_force_recovery.\n"
"InnoDB: Please see reference manual"
" for more details.\n"
"InnoDB: Aborting...\n",
space, offset,
BUF_PAGE_READ_MAX_RETRIES);
ut_error;
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate()); ut_a(++buf_dbg_counter % 37 || buf_validate());
......
...@@ -376,6 +376,7 @@ UNIV_INTERN FILE* lock_latest_err_file; ...@@ -376,6 +376,7 @@ UNIV_INTERN 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.
...@@ -394,7 +395,8 @@ Looks recursively for a deadlock. ...@@ -394,7 +395,8 @@ Looks recursively for a deadlock.
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
deadlock was found and we chose some other trx as a victim: we must do deadlock 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 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 or max depth. */
static static
ulint ulint
lock_deadlock_recursive( lock_deadlock_recursive(
...@@ -404,10 +406,10 @@ lock_deadlock_recursive( ...@@ -404,10 +406,10 @@ lock_deadlock_recursive(
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */ lock_t* wait_lock, /*!< in: lock that 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.
...@@ -3261,8 +3263,6 @@ lock_deadlock_occurs( ...@@ -3261,8 +3263,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;
...@@ -3284,31 +3284,50 @@ retry: ...@@ -3284,31 +3284,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 (UNIV_UNLIKELY(ret == LOCK_VICTIM_IS_START)) { case LOCK_EXCEED_MAX_DEPTH:
if (lock_get_type_low(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);
} }
/********************************************************************//** /********************************************************************//**
...@@ -3317,7 +3336,8 @@ Looks recursively for a deadlock. ...@@ -3317,7 +3336,8 @@ Looks recursively for a deadlock.
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
deadlock was found and we chose some other trx as a victim: we must do deadlock 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 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 or max depth. */
static static
ulint ulint
lock_deadlock_recursive( lock_deadlock_recursive(
...@@ -3327,10 +3347,10 @@ lock_deadlock_recursive( ...@@ -3327,10 +3347,10 @@ lock_deadlock_recursive(
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */ lock_t* wait_lock, /*!< in: lock that 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 */
{ {
ulint ret; ulint ret;
lock_t* lock; lock_t* lock;
...@@ -3406,7 +3426,7 @@ lock_deadlock_recursive( ...@@ -3406,7 +3426,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
...@@ -3453,19 +3473,10 @@ lock_deadlock_recursive( ...@@ -3453,19 +3473,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) {
...@@ -3501,6 +3512,21 @@ lock_deadlock_recursive( ...@@ -3501,6 +3512,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