Commit 021d7d72 authored by Timothy Smith's avatar Timothy Smith

Cherry-pick InnoDB fixes for Bug#34286, Bug#35352, and Bug#36600 from snapshot

innodb-5.0-ss2475.

Bug #34286  Assertion failure in thread 2816 in file .\row\row0sel.c line 3500
Since autoinc init performs a MySQL SELECT query to determine the auto-inc
value, set prebuilt->sql_stat_start = TRUE so that it is performed like any
normal SELECT, regardless of the context in which it was invoked.


Bug #35352  If InnoDB crashes with UNDO slots full error the error persists on restart
We've added a heuristic that checks the size of the UNDO slots cache lists
(insert and upate). If either of cached lists has more than 500 entries then we
add any UNDO slots that are freed, to the common free list instead of the cache
list, this is to avoid the case where all the free slots end up in only one of
the lists on startup after a crash.

Tested with test case for 26590 and passes all mysql-test(s).

Bug #36600  SHOW STATUS takes a lot of CPU in buf_get_latched_pages_number
Fixed by removing the Innodb_buffer_pool_pages_latched variable from SHOW
STATUS output in non-UNIV_DEBUG compilation.
parent a0768d32
...@@ -2260,6 +2260,7 @@ buf_print(void) ...@@ -2260,6 +2260,7 @@ buf_print(void)
ut_a(buf_validate()); ut_a(buf_validate());
} }
#ifdef UNIV_DEBUG
/************************************************************************* /*************************************************************************
Returns the number of latched pages in the buffer pool. */ Returns the number of latched pages in the buffer pool. */
...@@ -2290,6 +2291,7 @@ buf_get_latched_pages_number(void) ...@@ -2290,6 +2291,7 @@ buf_get_latched_pages_number(void)
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
return fixed_pages_number; return fixed_pages_number;
} }
#endif /* UNIV_DEBUG */
/************************************************************************* /*************************************************************************
Returns the number of pending buf pool ios. */ Returns the number of pending buf pool ios. */
......
...@@ -495,7 +495,15 @@ Prints info of the buffer pool data structure. */ ...@@ -495,7 +495,15 @@ Prints info of the buffer pool data structure. */
void void
buf_print(void); buf_print(void);
/*============*/ /*============*/
/*************************************************************************
Returns the number of latched pages in the buffer pool. */
ulint
buf_get_latched_pages_number(void);
/*==============================*/
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/************************************************************************ /************************************************************************
Prints a page to stderr. */ Prints a page to stderr. */
...@@ -503,12 +511,7 @@ void ...@@ -503,12 +511,7 @@ void
buf_page_print( buf_page_print(
/*===========*/ /*===========*/
byte* read_buf); /* in: a database page */ byte* read_buf); /* in: a database page */
/*************************************************************************
Returns the number of latched pages in the buffer pool. */
ulint
buf_get_latched_pages_number(void);
/*==============================*/
/************************************************************************* /*************************************************************************
Returns the number of pending buf pool ios. */ Returns the number of pending buf pool ios. */
......
...@@ -531,7 +531,9 @@ struct export_var_struct{ ...@@ -531,7 +531,9 @@ struct export_var_struct{
ulint innodb_buffer_pool_pages_dirty; ulint innodb_buffer_pool_pages_dirty;
ulint innodb_buffer_pool_pages_misc; ulint innodb_buffer_pool_pages_misc;
ulint innodb_buffer_pool_pages_free; ulint innodb_buffer_pool_pages_free;
#ifdef UNIV_DEBUG
ulint innodb_buffer_pool_pages_latched; ulint innodb_buffer_pool_pages_latched;
#endif /* UNIV_DEBUG */
ulint innodb_buffer_pool_read_requests; ulint innodb_buffer_pool_read_requests;
ulint innodb_buffer_pool_reads; ulint innodb_buffer_pool_reads;
ulint innodb_buffer_pool_wait_free; ulint innodb_buffer_pool_wait_free;
......
...@@ -237,6 +237,7 @@ trx_undo_set_state_at_finish( ...@@ -237,6 +237,7 @@ trx_undo_set_state_at_finish(
/*=========================*/ /*=========================*/
/* out: undo log segment header page, /* out: undo log segment header page,
x-latched */ x-latched */
trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */ trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
......
...@@ -1803,7 +1803,9 @@ srv_export_innodb_status(void) ...@@ -1803,7 +1803,9 @@ srv_export_innodb_status(void)
export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU); export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU);
export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list); export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list);
export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free); export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free);
#ifdef UNIV_DEBUG
export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number(); export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number();
#endif /* UNIV_DEBUG */
export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size; export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size;
export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size - export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size -
UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free);
......
...@@ -761,8 +761,8 @@ trx_commit_off_kernel( ...@@ -761,8 +761,8 @@ trx_commit_off_kernel(
mutex_enter(&(rseg->mutex)); mutex_enter(&(rseg->mutex));
if (trx->insert_undo != NULL) { if (trx->insert_undo != NULL) {
trx_undo_set_state_at_finish(trx, trx->insert_undo, trx_undo_set_state_at_finish(
&mtr); rseg, trx, trx->insert_undo, &mtr);
} }
undo = trx->update_undo; undo = trx->update_undo;
...@@ -777,8 +777,8 @@ trx_commit_off_kernel( ...@@ -777,8 +777,8 @@ trx_commit_off_kernel(
because only a single OS thread is allowed to do the because only a single OS thread is allowed to do the
transaction commit for this transaction. */ transaction commit for this transaction. */
update_hdr_page = trx_undo_set_state_at_finish(trx, update_hdr_page = trx_undo_set_state_at_finish(
undo, &mtr); rseg, trx, undo, &mtr);
/* We have to do the cleanup for the update log while /* We have to do the cleanup for the update log while
holding the rseg mutex because update log headers holding the rseg mutex because update log headers
......
...@@ -1724,6 +1724,7 @@ trx_undo_set_state_at_finish( ...@@ -1724,6 +1724,7 @@ trx_undo_set_state_at_finish(
/*=========================*/ /*=========================*/
/* out: undo log segment header page, /* out: undo log segment header page,
x-latched */ x-latched */
trx_rseg_t* rseg, /* in: rollback segment memory object */
trx_t* trx __attribute__((unused)), /* in: transaction */ trx_t* trx __attribute__((unused)), /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */ trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr) /* in: mtr */ mtr_t* mtr) /* in: mtr */
...@@ -1732,8 +1733,10 @@ trx_undo_set_state_at_finish( ...@@ -1732,8 +1733,10 @@ trx_undo_set_state_at_finish(
trx_upagef_t* page_hdr; trx_upagef_t* page_hdr;
page_t* undo_page; page_t* undo_page;
ulint state; ulint state;
ut_ad(trx && undo && mtr); ut_ad(trx);
ut_ad(undo);
ut_ad(mtr);
if (undo->id >= TRX_RSEG_N_SLOTS) { if (undo->id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
...@@ -1747,9 +1750,23 @@ trx_undo_set_state_at_finish( ...@@ -1747,9 +1750,23 @@ trx_undo_set_state_at_finish(
seg_hdr = undo_page + TRX_UNDO_SEG_HDR; seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
page_hdr = undo_page + TRX_UNDO_PAGE_HDR; page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) if (undo->size == 1
< TRX_UNDO_PAGE_REUSE_LIMIT) { && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE)
state = TRX_UNDO_CACHED; < TRX_UNDO_PAGE_REUSE_LIMIT) {
/* This is a heuristic to avoid the problem of all UNDO
slots ending up in one of the UNDO lists. Previously if
the server crashed with all the slots in one of the lists,
transactions that required the slots of a different type
would fail for lack of slots. */
if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500
&& UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) {
state = TRX_UNDO_CACHED;
} else {
state = TRX_UNDO_TO_FREE;
}
} else if (undo->type == TRX_UNDO_INSERT) { } else if (undo->type == TRX_UNDO_INSERT) {
...@@ -1759,7 +1776,7 @@ trx_undo_set_state_at_finish( ...@@ -1759,7 +1776,7 @@ trx_undo_set_state_at_finish(
} }
undo->state = state; undo->state = state;
mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr); mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr);
return(undo_page); return(undo_page);
......
drop table if exists t1;
create table t1(a int not null auto_increment primary key) engine=innodb;
insert into t1 set a = -1;
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK
-- source include/have_innodb.inc
# embedded server ignores 'delayed', so skip this
-- source include/not_embedded.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Bug 34286
#
create table t1(a int not null auto_increment primary key) engine=innodb;
insert into t1 set a = -1;
# NOTE: The database needs to be shutdown and restarted (here) for
# the test to work. It's included for reference only.
optimize table t1;
...@@ -244,8 +244,10 @@ struct show_var_st innodb_status_variables[]= { ...@@ -244,8 +244,10 @@ struct show_var_st innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG}, (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
{"buffer_pool_pages_free", {"buffer_pool_pages_free",
(char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG}, (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
#ifdef UNIV_DEBUG
{"buffer_pool_pages_latched", {"buffer_pool_pages_latched",
(char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG}, (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
#endif /* UNIV_DEBUG */
{"buffer_pool_pages_misc", {"buffer_pool_pages_misc",
(char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
{"buffer_pool_pages_total", {"buffer_pool_pages_total",
...@@ -4250,7 +4252,7 @@ ha_innobase::rnd_pos( ...@@ -4250,7 +4252,7 @@ ha_innobase::rnd_pos(
int error; int error;
uint keynr = active_index; uint keynr = active_index;
DBUG_ENTER("rnd_pos"); DBUG_ENTER("rnd_pos");
DBUG_DUMP("key", (uchar *)pos, ref_length); DBUG_DUMP("key", (uchar*) pos, ref_length);
statistic_increment(current_thd->status_var.ha_read_rnd_count, statistic_increment(current_thd->status_var.ha_read_rnd_count,
&LOCK_status); &LOCK_status);
...@@ -6882,6 +6884,12 @@ ha_innobase::innobase_read_and_init_auto_inc( ...@@ -6882,6 +6884,12 @@ ha_innobase::innobase_read_and_init_auto_inc(
from a table when no table has been locked in ::external_lock(). */ from a table when no table has been locked in ::external_lock(). */
prebuilt->trx->n_mysql_tables_in_use++; prebuilt->trx->n_mysql_tables_in_use++;
/* Since we will perform a MySQL SELECT query to determine the
auto-inc value, set prebuilt->sql_stat_start = TRUE so that it
is performed like any normal SELECT, regardless of the context
we come here. */
prebuilt->sql_stat_start = TRUE;
error = index_last(table->record[1]); error = index_last(table->record[1]);
prebuilt->trx->n_mysql_tables_in_use--; prebuilt->trx->n_mysql_tables_in_use--;
......
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