Commit 423747b5 authored by unknown's avatar unknown

Many files:

  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x


sql/ha_innodb.cc:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_class.cc:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_parse.cc:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_table.cc:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/ha_innodb.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/handler.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/lex.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/mysql_priv.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_class.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_lex.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
sql/sql_yacc.yy:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/ha/ha0ha.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/ha/hash0hash.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/buf/buf0buf.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/buf/buf0flu.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/buf/buf0lru.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/buf/buf0rea.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/btr/btr0btr.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/btr/btr0sea.c:
  Track crash in buf_LRU_block_remove_hashed_page + 1807 reported in MySQL-3.23.5x
innobase/fil/fil0fil.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/buf0buf.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/ha0ha.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/hash0hash.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/row0mysql.h:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/buf0buf.ic:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/ha0ha.ic:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/include/ibuf0ibuf.ic:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/page/page0page.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/row/row0mysql.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/row/row0purge.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/row/row0uins.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
innobase/row/row0umod.c:
  ALTER TABLE ... DISCARD/IMPORT TABLESPACE
parent 963d7bab
...@@ -426,7 +426,8 @@ btr_page_free_for_ibuf( ...@@ -426,7 +426,8 @@ btr_page_free_for_ibuf(
flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr); page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, mtr);
ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr)); ut_ad(flst_validate(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
mtr));
} }
/****************************************************************** /******************************************************************
......
...@@ -776,8 +776,8 @@ btr_search_guess_on_hash( ...@@ -776,8 +776,8 @@ btr_search_guess_on_hash(
goto failure; goto failure;
} }
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(page_rec_is_user_rec(rec)); ut_a(page_rec_is_user_rec(rec));
btr_cur_position(index, rec, cursor); btr_cur_position(index, rec, cursor);
......
...@@ -468,6 +468,11 @@ buf_block_init( ...@@ -468,6 +468,11 @@ buf_block_init(
block->check_index_page_at_flush = FALSE; block->check_index_page_at_flush = FALSE;
block->in_free_list = FALSE;
block->in_LRU_list = FALSE;
block->n_pointers = 0;
rw_lock_create(&(block->lock)); rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock))); ut_ad(rw_lock_validate(&(block->lock)));
...@@ -687,6 +692,7 @@ buf_pool_init( ...@@ -687,6 +692,7 @@ buf_pool_init(
} }
UT_LIST_ADD_LAST(free, buf_pool->free, block); UT_LIST_ADD_LAST(free, buf_pool->free, block);
block->in_free_list = TRUE;
} }
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
...@@ -830,7 +836,7 @@ buf_page_make_young( ...@@ -830,7 +836,7 @@ buf_page_make_young(
block = buf_block_align(frame); block = buf_block_align(frame);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
buf_LRU_make_block_young(block); buf_LRU_make_block_young(block);
...@@ -845,7 +851,7 @@ buf_block_free( ...@@ -845,7 +851,7 @@ buf_block_free(
/*===========*/ /*===========*/
buf_block_t* block) /* in, own: block to be freed */ buf_block_t* block) /* in, own: block to be freed */
{ {
ut_ad(block->state != BUF_BLOCK_FILE_PAGE); ut_a(block->state != BUF_BLOCK_FILE_PAGE);
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
...@@ -1109,6 +1115,8 @@ buf_page_get_gen( ...@@ -1109,6 +1115,8 @@ buf_page_get_gen(
goto loop; goto loop;
} }
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
must_read = FALSE; must_read = FALSE;
if (block->io_fix == BUF_IO_READ) { if (block->io_fix == BUF_IO_READ) {
...@@ -1407,6 +1415,8 @@ buf_page_get_known_nowait( ...@@ -1407,6 +1415,8 @@ buf_page_get_known_nowait(
return(FALSE); return(FALSE);
} }
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, file, line); buf_block_buf_fix_inc_debug(block, file, line);
#else #else
...@@ -1517,7 +1527,7 @@ buf_page_init( ...@@ -1517,7 +1527,7 @@ buf_page_init(
buf_block_t* block) /* in: block to init */ buf_block_t* block) /* in: block to init */
{ {
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block->state == BUF_BLOCK_READY_FOR_USE); ut_a(block->state != BUF_BLOCK_FILE_PAGE);
/* Set the state of the block */ /* Set the state of the block */
block->magic_n = BUF_BLOCK_MAGIC_N; block->magic_n = BUF_BLOCK_MAGIC_N;
...@@ -1533,6 +1543,18 @@ buf_page_init( ...@@ -1533,6 +1543,18 @@ buf_page_init(
/* Insert into the hash table of file pages */ /* Insert into the hash table of file pages */
if (buf_page_hash_get(space, offset)) {
fprintf(stderr,
"InnoDB: Error: page %lu %lu already found from the hash table\n", space,
offset);
buf_print();
buf_LRU_print();
buf_validate();
buf_LRU_validate();
ut_a(0);
}
HASH_INSERT(buf_block_t, hash, buf_pool->page_hash, HASH_INSERT(buf_block_t, hash, buf_pool->page_hash,
buf_page_address_fold(space, offset), block); buf_page_address_fold(space, offset), block);
...@@ -1605,7 +1627,7 @@ buf_page_init_for_read( ...@@ -1605,7 +1627,7 @@ buf_page_init_for_read(
block = buf_block_alloc(); block = buf_block_alloc();
ut_ad(block); ut_a(block);
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
...@@ -1769,6 +1791,8 @@ buf_page_io_complete( ...@@ -1769,6 +1791,8 @@ buf_page_io_complete(
ut_ad(block); ut_ad(block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
io_type = block->io_fix; io_type = block->io_fix;
if (io_type == BUF_IO_READ) { if (io_type == BUF_IO_READ) {
......
...@@ -50,6 +50,8 @@ buf_flush_insert_into_flush_list( ...@@ -50,6 +50,8 @@ buf_flush_insert_into_flush_list(
{ {
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
|| (ut_dulint_cmp( || (ut_dulint_cmp(
(UT_LIST_GET_FIRST(buf_pool->flush_list)) (UT_LIST_GET_FIRST(buf_pool->flush_list))
...@@ -131,7 +133,7 @@ buf_flush_ready_for_flush( ...@@ -131,7 +133,7 @@ buf_flush_ready_for_flush(
ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
{ {
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0) if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
&& (block->io_fix == 0)) { && (block->io_fix == 0)) {
...@@ -163,6 +165,8 @@ buf_flush_write_complete( ...@@ -163,6 +165,8 @@ buf_flush_write_complete(
ut_ad(block); ut_ad(block);
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
block->oldest_modification = ut_dulint_zero; block->oldest_modification = ut_dulint_zero;
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block); UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block);
...@@ -282,6 +286,8 @@ buf_flush_buffered_writes(void) ...@@ -282,6 +286,8 @@ buf_flush_buffered_writes(void)
for (i = 0; i < trx_doublewrite->first_free; i++) { for (i = 0; i < trx_doublewrite->first_free; i++) {
block = trx_doublewrite->buf_block_arr[i]; block = trx_doublewrite->buf_block_arr[i];
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
(void*)block->frame, (void*)block); (void*)block->frame, (void*)block);
...@@ -321,6 +327,8 @@ buf_flush_post_to_doublewrite_buf( ...@@ -321,6 +327,8 @@ buf_flush_post_to_doublewrite_buf(
try_again: try_again:
mutex_enter(&(trx_doublewrite->mutex)); mutex_enter(&(trx_doublewrite->mutex));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (trx_doublewrite->first_free if (trx_doublewrite->first_free
>= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
mutex_exit(&(trx_doublewrite->mutex)); mutex_exit(&(trx_doublewrite->mutex));
...@@ -395,6 +403,8 @@ buf_flush_write_block_low( ...@@ -395,6 +403,8 @@ buf_flush_write_block_low(
/*======================*/ /*======================*/
buf_block_t* block) /* in: buffer block to write */ buf_block_t* block) /* in: buffer block to write */
{ {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0); ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif #endif
...@@ -443,7 +453,7 @@ buf_flush_try_page( ...@@ -443,7 +453,7 @@ buf_flush_try_page(
block = buf_page_hash_get(space, offset); block = buf_page_hash_get(space, offset);
ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
if (flush_type == BUF_FLUSH_LIST if (flush_type == BUF_FLUSH_LIST
&& block && buf_flush_ready_for_flush(block, flush_type)) { && block && buf_flush_ready_for_flush(block, flush_type)) {
...@@ -635,6 +645,7 @@ buf_flush_try_neighbors( ...@@ -635,6 +645,7 @@ buf_flush_try_neighbors(
for (i = low; i < high; i++) { for (i = low; i < high; i++) {
block = buf_page_hash_get(space, i); block = buf_page_hash_get(space, i);
ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
if (block && flush_type == BUF_FLUSH_LRU && i != offset if (block && flush_type == BUF_FLUSH_LRU && i != offset
&& !block->old) { && !block->old) {
...@@ -703,10 +714,10 @@ buf_flush_batch( ...@@ -703,10 +714,10 @@ buf_flush_batch(
ulint offset; ulint offset;
ibool found; ibool found;
ut_ad((flush_type == BUF_FLUSH_LRU) || (flush_type == BUF_FLUSH_LIST)); ut_ad((flush_type == BUF_FLUSH_LRU)
ut_ad((flush_type != BUF_FLUSH_LIST) || || (flush_type == BUF_FLUSH_LIST));
sync_thread_levels_empty_gen(TRUE)); ut_ad((flush_type != BUF_FLUSH_LIST)
|| sync_thread_levels_empty_gen(TRUE));
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if ((buf_pool->n_flush[flush_type] > 0) if ((buf_pool->n_flush[flush_type] > 0)
...@@ -737,7 +748,6 @@ buf_flush_batch( ...@@ -737,7 +748,6 @@ buf_flush_batch(
ut_ad(flush_type == BUF_FLUSH_LIST); ut_ad(flush_type == BUF_FLUSH_LIST);
block = UT_LIST_GET_LAST(buf_pool->flush_list); block = UT_LIST_GET_LAST(buf_pool->flush_list);
if (!block if (!block
|| (ut_dulint_cmp(block->oldest_modification, || (ut_dulint_cmp(block->oldest_modification,
lsn_limit) >= 0)) { lsn_limit) >= 0)) {
...@@ -756,6 +766,7 @@ buf_flush_batch( ...@@ -756,6 +766,7 @@ buf_flush_batch(
function a pointer to a block in the list! */ function a pointer to a block in the list! */
while ((block != NULL) && !found) { while ((block != NULL) && !found) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (buf_flush_ready_for_flush(block, flush_type)) { if (buf_flush_ready_for_flush(block, flush_type)) {
...@@ -781,7 +792,6 @@ buf_flush_batch( ...@@ -781,7 +792,6 @@ buf_flush_batch(
} else if (flush_type == BUF_FLUSH_LRU) { } else if (flush_type == BUF_FLUSH_LRU) {
block = UT_LIST_GET_PREV(LRU, block); block = UT_LIST_GET_PREV(LRU, block);
} else { } else {
ut_ad(flush_type == BUF_FLUSH_LIST); ut_ad(flush_type == BUF_FLUSH_LIST);
......
...@@ -82,6 +82,8 @@ buf_LRU_invalidate_tablespace( ...@@ -82,6 +82,8 @@ buf_LRU_invalidate_tablespace(
block = UT_LIST_GET_LAST(buf_pool->LRU); block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) { while (block != NULL) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->space == id if (block->space == id
&& (block->buf_fix_count > 0 || block->io_fix != 0)) { && (block->buf_fix_count > 0 || block->io_fix != 0)) {
...@@ -199,19 +201,16 @@ buf_LRU_search_and_free_block( ...@@ -199,19 +201,16 @@ buf_LRU_search_and_free_block(
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
freed = FALSE; freed = FALSE;
block = UT_LIST_GET_LAST(buf_pool->LRU); block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) { while (block != NULL) {
ut_a(block->in_LRU_list);
if (buf_flush_ready_for_replace(block)) { if (buf_flush_ready_for_replace(block)) {
if (buf_debug_prints) { if (buf_debug_prints) {
printf( printf(
"Putting space %lu page %lu to free list\n", "Putting space %lu page %lu to free list\n",
block->space, block->offset); block->space, block->offset);
} }
buf_LRU_block_remove_hashed_page(block); buf_LRU_block_remove_hashed_page(block);
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
...@@ -223,25 +222,21 @@ buf_LRU_search_and_free_block( ...@@ -223,25 +222,21 @@ buf_LRU_search_and_free_block(
if (block->frame) { if (block->frame) {
btr_search_drop_page_hash_index(block->frame); btr_search_drop_page_hash_index(block->frame);
} }
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
ut_a(block->buf_fix_count == 0); ut_a(block->buf_fix_count == 0);
buf_LRU_block_free_hashed_page(block); buf_LRU_block_free_hashed_page(block);
freed = TRUE; freed = TRUE;
break; break;
} }
block = UT_LIST_GET_PREV(LRU, block); block = UT_LIST_GET_PREV(LRU, block);
distance++; distance++;
if (!freed && n_iterations <= 10 if (!freed && n_iterations <= 10
&& distance > 100 + (n_iterations * buf_pool->curr_size) && distance > 100 + (n_iterations * buf_pool->curr_size)
/ 10) { / 10) {
buf_pool->LRU_flush_ended = 0; buf_pool->LRU_flush_ended = 0;
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
...@@ -249,15 +244,12 @@ buf_LRU_search_and_free_block( ...@@ -249,15 +244,12 @@ buf_LRU_search_and_free_block(
return(FALSE); return(FALSE);
} }
} }
if (buf_pool->LRU_flush_ended > 0) { if (buf_pool->LRU_flush_ended > 0) {
buf_pool->LRU_flush_ended--; buf_pool->LRU_flush_ended--;
} }
if (!freed) {
if (!freed) {
buf_pool->LRU_flush_ended = 0; buf_pool->LRU_flush_ended = 0;
} }
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
return(freed); return(freed);
...@@ -355,7 +347,11 @@ buf_LRU_get_free_block(void) ...@@ -355,7 +347,11 @@ buf_LRU_get_free_block(void)
if (UT_LIST_GET_LEN(buf_pool->free) > 0) { if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
block = UT_LIST_GET_FIRST(buf_pool->free); block = UT_LIST_GET_FIRST(buf_pool->free);
ut_a(block->in_free_list);
UT_LIST_REMOVE(free, buf_pool->free, block); UT_LIST_REMOVE(free, buf_pool->free, block);
block->in_free_list = FALSE;
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
ut_a(!block->in_LRU_list);
if (srv_use_awe) { if (srv_use_awe) {
if (block->frame) { if (block->frame) {
...@@ -466,7 +462,7 @@ buf_LRU_old_adjust_len(void) ...@@ -466,7 +462,7 @@ buf_LRU_old_adjust_len(void)
ulint old_len; ulint old_len;
ulint new_len; ulint new_len;
ut_ad(buf_pool->LRU_old); ut_a(buf_pool->LRU_old);
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5); ut_ad(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5);
...@@ -474,6 +470,8 @@ buf_LRU_old_adjust_len(void) ...@@ -474,6 +470,8 @@ buf_LRU_old_adjust_len(void)
old_len = buf_pool->LRU_old_len; old_len = buf_pool->LRU_old_len;
new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8); new_len = 3 * (UT_LIST_GET_LEN(buf_pool->LRU) / 8);
ut_a(buf_pool->LRU_old->in_LRU_list);
/* Update the LRU_old pointer if necessary */ /* Update the LRU_old pointer if necessary */
if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) { if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) {
...@@ -490,7 +488,7 @@ buf_LRU_old_adjust_len(void) ...@@ -490,7 +488,7 @@ buf_LRU_old_adjust_len(void)
buf_pool->LRU_old); buf_pool->LRU_old);
buf_pool->LRU_old_len--; buf_pool->LRU_old_len--;
} else { } else {
ut_ad(buf_pool->LRU_old); /* Check that we did not ut_a(buf_pool->LRU_old); /* Check that we did not
fall out of the LRU list */ fall out of the LRU list */
return; return;
} }
...@@ -498,9 +496,8 @@ buf_LRU_old_adjust_len(void) ...@@ -498,9 +496,8 @@ buf_LRU_old_adjust_len(void)
} }
/*********************************************************************** /***********************************************************************
Initializes the old blocks pointer in the LRU list. Initializes the old blocks pointer in the LRU list. This function should be
This function should be called when the LRU list grows to called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */
BUF_LRU_OLD_MIN_LEN length. */
static static
void void
buf_LRU_old_init(void) buf_LRU_old_init(void)
...@@ -508,7 +505,7 @@ buf_LRU_old_init(void) ...@@ -508,7 +505,7 @@ buf_LRU_old_init(void)
{ {
buf_block_t* block; buf_block_t* block;
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN); ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
/* We first initialize all blocks in the LRU list as old and then use /* We first initialize all blocks in the LRU list as old and then use
the adjust function to move the LRU_old pointer to the right the adjust function to move the LRU_old pointer to the right
...@@ -517,6 +514,8 @@ buf_LRU_old_init(void) ...@@ -517,6 +514,8 @@ buf_LRU_old_init(void)
block = UT_LIST_GET_FIRST(buf_pool->LRU); block = UT_LIST_GET_FIRST(buf_pool->LRU);
while (block != NULL) { while (block != NULL) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->in_LRU_list);
block->old = TRUE; block->old = TRUE;
block = UT_LIST_GET_NEXT(LRU, block); block = UT_LIST_GET_NEXT(LRU, block);
} }
...@@ -539,6 +538,9 @@ buf_LRU_remove_block( ...@@ -539,6 +538,9 @@ buf_LRU_remove_block(
ut_ad(block); ut_ad(block);
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->in_LRU_list);
/* If the LRU_old pointer is defined and points to just this block, /* If the LRU_old pointer is defined and points to just this block,
move it backward one step */ move it backward one step */
...@@ -552,11 +554,12 @@ buf_LRU_remove_block( ...@@ -552,11 +554,12 @@ buf_LRU_remove_block(
(buf_pool->LRU_old)->old = TRUE; (buf_pool->LRU_old)->old = TRUE;
buf_pool->LRU_old_len++; buf_pool->LRU_old_len++;
ut_ad(buf_pool->LRU_old); ut_a(buf_pool->LRU_old);
} }
/* Remove the block from the LRU list */ /* Remove the block from the LRU list */
UT_LIST_REMOVE(LRU, buf_pool->LRU, block); UT_LIST_REMOVE(LRU, buf_pool->LRU, block);
block->in_LRU_list = FALSE;
if (srv_use_awe && block->frame) { if (srv_use_awe && block->frame) {
/* Remove from the list of mapped pages */ /* Remove from the list of mapped pages */
...@@ -599,6 +602,8 @@ buf_LRU_add_block_to_end_low( ...@@ -599,6 +602,8 @@ buf_LRU_add_block_to_end_low(
ut_ad(block); ut_ad(block);
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
block->old = TRUE; block->old = TRUE;
last_block = UT_LIST_GET_LAST(buf_pool->LRU); last_block = UT_LIST_GET_LAST(buf_pool->LRU);
...@@ -609,7 +614,9 @@ buf_LRU_add_block_to_end_low( ...@@ -609,7 +614,9 @@ buf_LRU_add_block_to_end_low(
block->LRU_position = buf_pool_clock_tic(); block->LRU_position = buf_pool_clock_tic();
} }
ut_a(!block->in_LRU_list);
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
block->in_LRU_list = TRUE;
if (srv_use_awe && block->frame) { if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */ /* Add to the list of mapped pages */
...@@ -658,6 +665,9 @@ buf_LRU_add_block_low( ...@@ -658,6 +665,9 @@ buf_LRU_add_block_low(
ut_ad(block); ut_ad(block);
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(!block->in_LRU_list);
block->old = old; block->old = old;
cl = buf_pool_clock_tic(); cl = buf_pool_clock_tic();
...@@ -687,6 +697,8 @@ buf_LRU_add_block_low( ...@@ -687,6 +697,8 @@ buf_LRU_add_block_low(
block->LRU_position = (buf_pool->LRU_old)->LRU_position; block->LRU_position = (buf_pool->LRU_old)->LRU_position;
} }
block->in_LRU_list = TRUE;
if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) { if (UT_LIST_GET_LEN(buf_pool->LRU) > BUF_LRU_OLD_MIN_LEN) {
ut_ad(buf_pool->LRU_old); ut_ad(buf_pool->LRU_old);
...@@ -755,9 +767,12 @@ buf_LRU_block_free_non_file_page( ...@@ -755,9 +767,12 @@ buf_LRU_block_free_non_file_page(
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block); ut_ad(block);
ut_ad((block->state == BUF_BLOCK_MEMORY) ut_a((block->state == BUF_BLOCK_MEMORY)
|| (block->state == BUF_BLOCK_READY_FOR_USE)); || (block->state == BUF_BLOCK_READY_FOR_USE));
ut_a(block->n_pointers == 0);
ut_a(!block->in_free_list);
block->state = BUF_BLOCK_NOT_USED; block->state = BUF_BLOCK_NOT_USED;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -765,6 +780,7 @@ buf_LRU_block_free_non_file_page( ...@@ -765,6 +780,7 @@ buf_LRU_block_free_non_file_page(
memset(block->frame, '\0', UNIV_PAGE_SIZE); memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif #endif
UT_LIST_ADD_FIRST(free, buf_pool->free, block); UT_LIST_ADD_FIRST(free, buf_pool->free, block);
block->in_free_list = TRUE;
if (srv_use_awe && block->frame) { if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */ /* Add to the list of mapped pages */
...@@ -788,8 +804,7 @@ buf_LRU_block_remove_hashed_page( ...@@ -788,8 +804,7 @@ buf_LRU_block_remove_hashed_page(
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block); ut_ad(block);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->io_fix == 0); ut_a(block->io_fix == 0);
ut_a(block->buf_fix_count == 0); ut_a(block->buf_fix_count == 0);
ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0); ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0);
...@@ -802,6 +817,28 @@ buf_LRU_block_remove_hashed_page( ...@@ -802,6 +817,28 @@ buf_LRU_block_remove_hashed_page(
buf_block_modify_clock_inc(block); buf_block_modify_clock_inc(block);
if (block != buf_page_hash_get(block->space, block->offset)) {
fprintf(stderr,
"InnoDB: Error: page %lu %lu not found from the hash table\n",
block->space,
block->offset);
if (buf_page_hash_get(block->space, block->offset)) {
fprintf(stderr,
"InnoDB: From hash table we find block %lx of %lu %lu which is not %lx\n",
(ulint)buf_page_hash_get(block->space, block->offset),
buf_page_hash_get(block->space, block->offset)->space,
buf_page_hash_get(block->space, block->offset)->offset,
(ulint)block);
}
buf_print();
buf_LRU_print();
buf_validate();
buf_LRU_validate();
ut_a(0);
}
HASH_DELETE(buf_block_t, hash, buf_pool->page_hash, HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
buf_page_address_fold(block->space, block->offset), buf_page_address_fold(block->space, block->offset),
block); block);
...@@ -819,7 +856,7 @@ buf_LRU_block_free_hashed_page( ...@@ -819,7 +856,7 @@ buf_LRU_block_free_hashed_page(
be in a state where it can be freed */ be in a state where it can be freed */
{ {
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block->state == BUF_BLOCK_REMOVE_HASH); ut_a(block->state == BUF_BLOCK_REMOVE_HASH);
block->state = BUF_BLOCK_MEMORY; block->state = BUF_BLOCK_MEMORY;
......
...@@ -129,6 +129,8 @@ buf_read_page_low( ...@@ -129,6 +129,8 @@ buf_read_page_low(
offset, sync); offset, sync);
} }
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
*err = fil_io(OS_FILE_READ | wake_later, *err = fil_io(OS_FILE_READ | wake_later,
sync, space, sync, space,
offset, 0, UNIV_PAGE_SIZE, offset, 0, UNIV_PAGE_SIZE,
...@@ -604,7 +606,6 @@ buf_read_ibuf_merge_pages( ...@@ -604,7 +606,6 @@ buf_read_ibuf_merge_pages(
} }
for (i = 0; i < n_stored; i++) { for (i = 0; i < n_stored; i++) {
if ((i + 1 == n_stored) && sync) { if ((i + 1 == n_stored) && sync) {
buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE,
space_ids[i], space_versions[i], page_nos[i]); space_ids[i], space_versions[i], page_nos[i]);
......
...@@ -1517,8 +1517,8 @@ fil_delete_tablespace( ...@@ -1517,8 +1517,8 @@ fil_delete_tablespace(
if (space == NULL) { if (space == NULL) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: cannot delete tablespace %lu because it is not found\n" " InnoDB: Error: cannot delete tablespace %lu\n"
"InnoDB: in the tablespace memory cache.\n", id); "InnoDB: because it is not found in the tablespace memory cache.\n", id);
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
...@@ -2426,19 +2426,24 @@ fil_space_for_table_exists_in_mem( ...@@ -2426,19 +2426,24 @@ fil_space_for_table_exists_in_mem(
if (namespace == NULL) { if (namespace == NULL) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" " InnoDB: Error: table %s\n"
"InnoDB: id %lu, but tablespace with that id or name does not exist. Have\n" "InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n", "InnoDB: but tablespace with that id or name does not exist. Have\n"
name, id, name); "InnoDB: you deleted or moved .ibd files?\n",
name, id);
} else { } else {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" " InnoDB: Error: table %s\n"
"InnoDB: id %lu, but tablespace with that id does not exist. There is\n" "InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
"InnoDB: but tablespace with that id does not exist. There is\n"
"InnoDB: a tablespace of name %s and id %lu, though. Have\n" "InnoDB: a tablespace of name %s and id %lu, though. Have\n"
"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n", "InnoDB: you deleted or moved .ibd files?\n",
name, id, namespace->name, namespace->id, name); name, id, namespace->name, namespace->id);
} }
fprintf(stderr,
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: how to resolve the issue.\n");
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
...@@ -2448,16 +2453,20 @@ fil_space_for_table_exists_in_mem( ...@@ -2448,16 +2453,20 @@ fil_space_for_table_exists_in_mem(
if (0 != strcmp(space->name, path)) { if (0 != strcmp(space->name, path)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" " InnoDB: Error: table %s\n"
"InnoDB: id %lu, but tablespace with that id has name %s. Have you\n" "InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
"InnoDB: deleted or moved .ibd files? We cannot open table %s now.\n", "InnoDB: but tablespace with that id has name %s.\n"
name, id, space->name, name); "InnoDB: Have you deleted or moved .ibd files?", name, id, space->name);
if (namespace != NULL) { if (namespace != NULL) {
fprintf(stderr, fprintf(stderr,
"InnoDB: There is a tablespace with the right name %s, but its id is %lu.\n", "InnoDB: There is a tablespace with the right name\n"
namespace->name, namespace->id); "InnoDB: %s, but its id is %lu.\n", namespace->name, namespace->id);
} }
fprintf(stderr,
"InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: how to resolve the issue.\n");
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
return(FALSE); return(FALSE);
......
...@@ -34,6 +34,12 @@ ha_create( ...@@ -34,6 +34,12 @@ ha_create(
table = hash_create(n); table = hash_create(n);
if (in_btr_search) {
table->adaptive = TRUE;
} else {
table->adaptive = FALSE;
}
if (n_mutexes == 0) { if (n_mutexes == 0) {
if (in_btr_search) { if (in_btr_search) {
table->heap = mem_heap_create_in_btr_search(4096); table->heap = mem_heap_create_in_btr_search(4096);
...@@ -106,6 +112,7 @@ ha_insert_for_fold( ...@@ -106,6 +112,7 @@ ha_insert_for_fold(
hash_cell_t* cell; hash_cell_t* cell;
ha_node_t* node; ha_node_t* node;
ha_node_t* prev_node; ha_node_t* prev_node;
buf_block_t* prev_block;
ulint hash; ulint hash;
ut_ad(table && data); ut_ad(table && data);
...@@ -119,6 +126,12 @@ ha_insert_for_fold( ...@@ -119,6 +126,12 @@ ha_insert_for_fold(
while (prev_node != NULL) { while (prev_node != NULL) {
if (prev_node->fold == fold) { if (prev_node->fold == fold) {
if (table->adaptive) {
prev_block = buf_block_align(prev_node->data);
ut_a(prev_block->n_pointers > 0);
prev_block->n_pointers--;
buf_block_align(data)->n_pointers++;
}
prev_node->data = data; prev_node->data = data;
...@@ -142,6 +155,11 @@ ha_insert_for_fold( ...@@ -142,6 +155,11 @@ ha_insert_for_fold(
} }
ha_node_set_data(node, data); ha_node_set_data(node, data);
if (table->adaptive) {
buf_block_align(data)->n_pointers++;
}
node->fold = fold; node->fold = fold;
node->next = NULL; node->next = NULL;
...@@ -174,6 +192,11 @@ ha_delete_hash_node( ...@@ -174,6 +192,11 @@ ha_delete_hash_node(
hash_table_t* table, /* in: hash table */ hash_table_t* table, /* in: hash table */
ha_node_t* del_node) /* in: node to be deleted */ ha_node_t* del_node) /* in: node to be deleted */
{ {
if (table->adaptive) {
ut_a(buf_block_align(del_node->data)->n_pointers > 0);
buf_block_align(del_node->data)->n_pointers--;
}
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node); HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
} }
...@@ -199,6 +222,35 @@ ha_delete( ...@@ -199,6 +222,35 @@ ha_delete(
ha_delete_hash_node(table, node); ha_delete_hash_node(table, node);
} }
/*************************************************************
Looks for an element when we know the pointer to the data, and updates
the pointer to data, if found. */
void
ha_search_and_update_if_found(
/*==========================*/
hash_table_t* table, /* in: hash table */
ulint fold, /* in: folded value of the searched data */
void* data, /* in: pointer to the data */
void* new_data)/* in: new pointer to the data */
{
ha_node_t* node;
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
node = ha_search_with_data(table, fold, data);
if (node) {
if (table->adaptive) {
ut_a(buf_block_align(node->data)->n_pointers > 0);
buf_block_align(node->data)->n_pointers--;
buf_block_align(new_data)->n_pointers++;
}
node->data = new_data;
}
}
/********************************************************************* /*********************************************************************
Removes from the chain determined by fold all nodes whose data pointer Removes from the chain determined by fold all nodes whose data pointer
points to the page given. */ points to the page given. */
...@@ -229,10 +281,10 @@ ha_remove_all_nodes_to_page( ...@@ -229,10 +281,10 @@ ha_remove_all_nodes_to_page(
node = ha_chain_get_first(table, fold); node = ha_chain_get_first(table, fold);
} else { } else {
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
} }
#ifdef UNIV_DEBUG
/* Check that all nodes really got deleted */ /* Check that all nodes really got deleted */
node = ha_chain_get_first(table, fold); node = ha_chain_get_first(table, fold);
...@@ -240,8 +292,9 @@ ha_remove_all_nodes_to_page( ...@@ -240,8 +292,9 @@ ha_remove_all_nodes_to_page(
while (node) { while (node) {
ut_a(buf_frame_align(ha_node_get_data(node)) != page); ut_a(buf_frame_align(ha_node_get_data(node)) != page);
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
#endif
} }
/***************************************************************** /*****************************************************************
...@@ -293,12 +346,10 @@ ha_print_info( ...@@ -293,12 +346,10 @@ ha_print_info(
hash_table_t* table) /* in: hash table */ hash_table_t* table) /* in: hash table */
{ {
hash_cell_t* cell; hash_cell_t* cell;
/* /* ha_node_t* node;
ha_node_t* node; ulint nodes = 0;
ulint len = 0; ulint len = 0;
ulint max_len = 0; ulint max_len = 0; */
ulint nodes = 0;
*/
ulint cells = 0; ulint cells = 0;
ulint n_bufs; ulint n_bufs;
ulint i; ulint i;
......
...@@ -91,6 +91,7 @@ hash_create( ...@@ -91,6 +91,7 @@ hash_create(
array = ut_malloc(sizeof(hash_cell_t) * prime); array = ut_malloc(sizeof(hash_cell_t) * prime);
table->adaptive = FALSE;
table->array = array; table->array = array;
table->n_cells = prime; table->n_cells = prime;
table->n_mutexes = 0; table->n_mutexes = 0;
......
...@@ -755,12 +755,16 @@ struct buf_block_struct{ ...@@ -755,12 +755,16 @@ struct buf_block_struct{
UT_LIST_NODE_T(buf_block_t) free; UT_LIST_NODE_T(buf_block_t) free;
/* node of the free block list */ /* node of the free block list */
ibool in_free_list; /* TRUE if in the free list; used in
debugging */
UT_LIST_NODE_T(buf_block_t) LRU; UT_LIST_NODE_T(buf_block_t) LRU;
/* node of the LRU list */ /* node of the LRU list */
UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped; UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped;
/* in the AWE version node in the /* in the AWE version node in the
list of free and LRU blocks which are list of free and LRU blocks which are
mapped to a frame */ mapped to a frame */
ibool in_LRU_list; /* TRUE of the page is in the LRU list;
used in debugging */
ulint LRU_position; /* value which monotonically ulint LRU_position; /* value which monotonically
decreases (or may stay constant if decreases (or may stay constant if
the block is in the old blocks) toward the block is in the old blocks) toward
...@@ -821,6 +825,9 @@ struct buf_block_struct{ ...@@ -821,6 +825,9 @@ struct buf_block_struct{
complete, though: there may have been complete, though: there may have been
hash collisions, record deletions, hash collisions, record deletions,
etc. */ etc. */
ulint n_pointers; /* used in debugging: the number of
pointers in the adaptive hash index
pointing to this frame */
ulint curr_n_fields; /* prefix length for hash indexing: ulint curr_n_fields; /* prefix length for hash indexing:
number of full fields */ number of full fields */
ulint curr_n_bytes; /* number of bytes in hash indexing */ ulint curr_n_bytes; /* number of bytes in hash indexing */
......
...@@ -28,7 +28,6 @@ buf_block_peek_if_too_old( ...@@ -28,7 +28,6 @@ buf_block_peek_if_too_old(
{ {
if (buf_pool->freed_page_clock >= block->freed_page_clock if (buf_pool->freed_page_clock >= block->freed_page_clock
+ 1 + (buf_pool->curr_size / 1024)) { + 1 + (buf_pool->curr_size / 1024)) {
return(TRUE); return(TRUE);
} }
...@@ -169,7 +168,7 @@ buf_block_get_space( ...@@ -169,7 +168,7 @@ buf_block_get_space(
ut_ad(block); ut_ad(block);
ut_ad(block >= buf_pool->blocks); ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->max_size); ut_ad(block < buf_pool->blocks + buf_pool->max_size);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0); ut_ad(block->buf_fix_count > 0);
return(block->space); return(block->space);
...@@ -187,7 +186,7 @@ buf_block_get_page_no( ...@@ -187,7 +186,7 @@ buf_block_get_page_no(
ut_ad(block); ut_ad(block);
ut_ad(block >= buf_pool->blocks); ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->max_size); ut_ad(block < buf_pool->blocks + buf_pool->max_size);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0); ut_ad(block->buf_fix_count > 0);
return(block->offset); return(block->offset);
...@@ -550,6 +549,8 @@ buf_page_hash_get( ...@@ -550,6 +549,8 @@ buf_page_hash_get(
HASH_SEARCH(hash, buf_pool->page_hash, fold, block, HASH_SEARCH(hash, buf_pool->page_hash, fold, block,
(block->space == space) && (block->offset == offset)); (block->space == space) && (block->offset == offset));
ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE);
return(block); return(block);
} }
...@@ -617,8 +618,8 @@ buf_page_release( ...@@ -617,8 +618,8 @@ buf_page_release(
mutex_enter_fast(&(buf_pool->mutex)); mutex_enter_fast(&(buf_pool->mutex));
ut_ad(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0); ut_a(block->buf_fix_count > 0);
if (rw_latch == RW_X_LATCH && mtr->modifications) { if (rw_latch == RW_X_LATCH && mtr->modifications) {
......
...@@ -28,7 +28,7 @@ ha_search_and_get_data( ...@@ -28,7 +28,7 @@ ha_search_and_get_data(
/************************************************************* /*************************************************************
Looks for an element when we know the pointer to the data and updates Looks for an element when we know the pointer to the data and updates
the pointer to data if found. */ the pointer to data if found. */
UNIV_INLINE
void void
ha_search_and_update_if_found( ha_search_and_update_if_found(
/*==========================*/ /*==========================*/
......
...@@ -49,7 +49,6 @@ ha_node_t* ...@@ -49,7 +49,6 @@ ha_node_t*
ha_chain_get_next( ha_chain_get_next(
/*==============*/ /*==============*/
/* out: next node, NULL if none */ /* out: next node, NULL if none */
hash_table_t* table __attribute__((unused)), /* in: hash table */
ha_node_t* node) /* in: hash chain node */ ha_node_t* node) /* in: hash chain node */
{ {
ut_ad(table); ut_ad(table);
...@@ -94,7 +93,7 @@ ha_search( ...@@ -94,7 +93,7 @@ ha_search(
return(node); return(node);
} }
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
return(NULL); return(NULL);
...@@ -124,7 +123,7 @@ ha_search_and_get_data( ...@@ -124,7 +123,7 @@ ha_search_and_get_data(
return(node->data); return(node->data);
} }
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
return(NULL); return(NULL);
...@@ -139,7 +138,6 @@ ha_next( ...@@ -139,7 +138,6 @@ ha_next(
/* out: pointer to the next hash table node /* out: pointer to the next hash table node
in chain with the fold value, NULL if not in chain with the fold value, NULL if not
found */ found */
hash_table_t* table, /* in: hash table */
ha_node_t* node) /* in: hash table node */ ha_node_t* node) /* in: hash table node */
{ {
ulint fold; ulint fold;
...@@ -148,7 +146,7 @@ ha_next( ...@@ -148,7 +146,7 @@ ha_next(
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold))); ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
while (node) { while (node) {
if (node->fold == fold) { if (node->fold == fold) {
...@@ -156,7 +154,7 @@ ha_next( ...@@ -156,7 +154,7 @@ ha_next(
return(node); return(node);
} }
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
return(NULL); return(NULL);
...@@ -186,35 +184,12 @@ ha_search_with_data( ...@@ -186,35 +184,12 @@ ha_search_with_data(
return(node); return(node);
} }
node = ha_chain_get_next(table, node); node = ha_chain_get_next(node);
} }
return(NULL); return(NULL);
} }
/*************************************************************
Looks for an element when we know the pointer to the data, and updates
the pointer to data, if found. */
UNIV_INLINE
void
ha_search_and_update_if_found(
/*==========================*/
hash_table_t* table, /* in: hash table */
ulint fold, /* in: folded value of the searched data */
void* data, /* in: pointer to the data */
void* new_data)/* in: new pointer to the data */
{
ha_node_t* node;
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
node = ha_search_with_data(table, fold, data);
if (node) {
node->data = new_data;
}
}
/************************************************************* /*************************************************************
Looks for an element when we know the pointer to the data, and deletes Looks for an element when we know the pointer to the data, and deletes
it from the hash table, if found. */ it from the hash table, if found. */
......
...@@ -100,7 +100,7 @@ Deletes a struct from a hash table. */ ...@@ -100,7 +100,7 @@ Deletes a struct from a hash table. */
\ \
while (struct3333->NAME != DATA) {\ while (struct3333->NAME != DATA) {\
\ \
ut_ad(struct3333)\ ut_a(struct3333)\
struct3333 = struct3333->NAME;\ struct3333 = struct3333->NAME;\
}\ }\
\ \
...@@ -322,6 +322,8 @@ struct hash_cell_struct{ ...@@ -322,6 +322,8 @@ struct hash_cell_struct{
/* The hash table structure */ /* The hash table structure */
struct hash_table_struct { struct hash_table_struct {
ibool adaptive;/* TRUE if this is the hash table of the
adaptive hash index */
ulint n_cells;/* number of cells in the hash table */ ulint n_cells;/* number of cells in the hash table */
hash_cell_t* array; /* pointer to cell array */ hash_cell_t* array; /* pointer to cell array */
ulint n_mutexes;/* if mutexes != NULL, then the number of ulint n_mutexes;/* if mutexes != NULL, then the number of
......
...@@ -218,7 +218,7 @@ ibuf_update_free_bits_if_full( ...@@ -218,7 +218,7 @@ ibuf_update_free_bits_if_full(
} }
if (after == 0) { if (after == 0) {
/* We move the page to front of the buffer pool LRU list: /* We move the page to the front of the buffer pool LRU list:
the purpose of this is to prevent those pages to which we the purpose of this is to prevent those pages to which we
cannot make inserts using the insert buffer from slipping cannot make inserts using the insert buffer from slipping
out of the buffer pool */ out of the buffer pool */
......
...@@ -339,6 +339,45 @@ row_drop_table_for_mysql( ...@@ -339,6 +339,45 @@ row_drop_table_for_mysql(
char* name, /* in: table name */ char* name, /* in: table name */
trx_t* trx); /* in: transaction handle */ trx_t* trx); /* in: transaction handle */
/************************************************************************* /*************************************************************************
Discards the tablespace of a table which stored in an .ibd file. Discarding
means that this function deletes the .ibd file and assigns a new table id for
the table. Also the flag table->ibd_file_missing is set TRUE.
How do we prevent crashes caused by ongoing operations on the table? Old
operations could try to access non-existent pages.
1) SQL queries, INSERT, SELECT, ...: we must get an exclusive MySQL table lock
on the table before we can do DISCARD TABLESPACE. Then there are no running
queries on the table.
2) Purge and rollback: we assign a new table id for the table. Since purge and
rollback look for the table based on the table id, they see the table as
'dropped' and discard their operations.
3) Insert buffer: we remove all entries for the tablespace in the insert
buffer tree; as long as the tablespace mem object does not exist, ongoing
insert buffer page merges are discarded in buf0rea.c. If we recreate the
tablespace mem object with IMPORT TABLESPACE later, then the tablespace will
have the same id, but the tablespace_version field in the mem object is
different, and ongoing old insert buffer page merges get discarded.
4) Linear readahead and random readahead: we use the same method as in 3) to
discard ongoing operations. */
int
row_discard_tablespace_for_mysql(
/*=============================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
trx_t* trx); /* in: transaction handle */
/*********************************************************************
Imports a tablespace. The space id in the .ibd file must match the space id
of the table in the data dictionary. */
int
row_import_tablespace_for_mysql(
/*============================*/
/* out: error code or DB_SUCCESS */
char* name, /* in: table name */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
Drops a database for MySQL. */ Drops a database for MySQL. */
int int
......
...@@ -582,7 +582,8 @@ byte* ...@@ -582,7 +582,8 @@ byte*
page_parse_delete_rec_list( page_parse_delete_rec_list(
/*=======================*/ /*=======================*/
/* out: end of log record or NULL */ /* out: end of log record or NULL */
byte type, /* in: MLOG_LIST_END_DELETE or MLOG_LIST_START_DELETE */ byte type, /* in: MLOG_LIST_END_DELETE or
MLOG_LIST_START_DELETE */
byte* ptr, /* in: buffer */ byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */ byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */ page_t* page, /* in: page or NULL */
......
...@@ -2007,9 +2007,6 @@ row_import_tablespace_for_mysql( ...@@ -2007,9 +2007,6 @@ row_import_tablespace_for_mysql(
success = fil_open_single_table_tablespace(table->space, table->name); success = fil_open_single_table_tablespace(table->space, table->name);
printf(
"Remember to stop purge + undo if table->ibd_file_is_missing!!!\n");
if (success) { if (success) {
table->ibd_file_missing = FALSE; table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE; table->tablespace_discarded = FALSE;
......
...@@ -529,6 +529,14 @@ row_purge_parse_undo_rec( ...@@ -529,6 +529,14 @@ row_purge_parse_undo_rec(
return(FALSE); return(FALSE);
} }
if (node->table->ibd_file_missing) {
/* We skip purge of missing .ibd files */
node->table = NULL;
return;
}
clust_index = dict_table_get_first_index(node->table); clust_index = dict_table_get_first_index(node->table);
if (clust_index == NULL) { if (clust_index == NULL) {
......
...@@ -258,6 +258,13 @@ row_undo_ins_parse_undo_rec( ...@@ -258,6 +258,13 @@ row_undo_ins_parse_undo_rec(
return; return;
} }
if (node->table->ibd_file_missing) {
/* We skip undo operations to missing .ibd files */
node->table = NULL;
return;
}
clust_index = dict_table_get_first_index(node->table); clust_index = dict_table_get_first_index(node->table);
ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
......
...@@ -620,6 +620,13 @@ row_undo_mod_parse_undo_rec( ...@@ -620,6 +620,13 @@ row_undo_mod_parse_undo_rec(
return; return;
} }
if (node->table->ibd_file_missing) {
/* We skip undo operations to missing .ibd files */
node->table = NULL;
return;
}
clust_index = dict_table_get_first_index(node->table); clust_index = dict_table_get_first_index(node->table);
ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr,
......
...@@ -1451,7 +1451,7 @@ ha_innobase::open( ...@@ -1451,7 +1451,7 @@ ha_innobase::open(
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (ib_table->ibd_file_missing) { if (ib_table->ibd_file_missing && !current_thd->tablespace_op) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB error:\n" fprintf(stderr, " InnoDB error:\n"
"MySQL is trying to open a table handle but the .ibd file for\n" "MySQL is trying to open a table handle but the .ibd file for\n"
...@@ -3628,6 +3628,42 @@ ha_innobase::create( ...@@ -3628,6 +3628,42 @@ ha_innobase::create(
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*********************************************************************
Discards or imports an InnoDB tablespace. */
int
ha_innobase::discard_or_import_tablespace(
/*======================================*/
/* out: 0 == success, -1 == error */
my_bool discard) /* in: TRUE if discard, else import */
{
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
dict_table_t* table;
trx_t* trx;
int err;
DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
table = prebuilt->table;
trx = prebuilt->trx;
if (discard) {
err = row_discard_tablespace_for_mysql(table->name, trx);
} else {
err = row_import_tablespace_for_mysql(table->name, trx);
}
if (err == DB_SUCCESS) {
DBUG_RETURN(0);
}
DBUG_RETURN(-1);
}
/********************************************************************* /*********************************************************************
Drops a table from an InnoDB database. Before calling this function, Drops a table from an InnoDB database. Before calling this function,
MySQL calls innobase_commit to commit the transaction of the current user. MySQL calls innobase_commit to commit the transaction of the current user.
...@@ -3647,7 +3683,7 @@ ha_innobase::delete_table( ...@@ -3647,7 +3683,7 @@ ha_innobase::delete_table(
trx_t* trx; trx_t* trx;
char norm_name[1000]; char norm_name[1000];
DBUG_ENTER("ha_innobase::delete_table"); DBUG_ENTER("ha_innobase::delete_table");
/* Get the transaction associated with the current thd, or create one /* Get the transaction associated with the current thd, or create one
if not yet created */ if not yet created */
...@@ -4536,7 +4572,8 @@ ha_innobase::external_lock( ...@@ -4536,7 +4572,8 @@ ha_innobase::external_lock(
update_thd(thd); update_thd(thd);
if (lock_type != F_UNLCK && prebuilt->table->ibd_file_missing) { if (lock_type != F_UNLCK && prebuilt->table->ibd_file_missing
&& !current_thd->tablespace_op) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB error:\n" fprintf(stderr, " InnoDB error:\n"
"MySQL is trying to use a table handle but the .ibd file for\n" "MySQL is trying to use a table handle but the .ibd file for\n"
...@@ -4546,6 +4583,7 @@ ha_innobase::external_lock( ...@@ -4546,6 +4583,7 @@ ha_innobase::external_lock(
"Look from section 15.1 of http://www.innodb.com/ibman.html\n" "Look from section 15.1 of http://www.innodb.com/ibman.html\n"
"how you can resolve the problem.\n", "how you can resolve the problem.\n",
prebuilt->table->name); prebuilt->table->name);
DBUG_RETURN(HA_ERR_CRASHED);
} }
trx = prebuilt->trx; trx = prebuilt->trx;
...@@ -4793,11 +4831,12 @@ ha_innobase::store_lock( ...@@ -4793,11 +4831,12 @@ ha_innobase::store_lock(
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
/* If we are not doing a LOCK TABLE, then allow multiple /* If we are not doing a LOCK TABLE or DISCARD/IMPORT
writers */ TABLESPACE, then allow multiple writers */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
lock_type <= TL_WRITE) && !thd->in_lock_tables) { lock_type <= TL_WRITE) && !thd->in_lock_tables
&& !thd->tablespace_op) {
lock_type = TL_WRITE_ALLOW_WRITE; lock_type = TL_WRITE_ALLOW_WRITE;
} }
......
...@@ -160,6 +160,7 @@ class ha_innobase: public handler ...@@ -160,6 +160,7 @@ class ha_innobase: public handler
void info(uint); void info(uint);
int analyze(THD* thd,HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int optimize(THD* thd,HA_CHECK_OPT* check_opt); int optimize(THD* thd,HA_CHECK_OPT* check_opt);
int discard_or_import_tablespace(my_bool discard);
int extra(enum ha_extra_function operation); int extra(enum ha_extra_function operation);
int reset(void); int reset(void);
int external_lock(THD *thd, int lock_type); int external_lock(THD *thd, int lock_type);
......
...@@ -317,6 +317,7 @@ class handler :public Sql_alloc ...@@ -317,6 +317,7 @@ class handler :public Sql_alloc
virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; } virtual int dump(THD* thd, int fd = -1) { return ER_DUMP_NOT_IMPLEMENTED; }
virtual void deactivate_non_unique_index(ha_rows rows) {} virtual void deactivate_non_unique_index(ha_rows rows) {}
virtual bool activate_all_index(THD *thd) {return 0;} virtual bool activate_all_index(THD *thd) {return 0;}
virtual int discard_or_import_tablespace(my_bool discard) {return -1;}
// not implemented by default // not implemented by default
virtual int net_read_dump(NET* net) virtual int net_read_dump(NET* net)
{ return ER_DUMP_NOT_IMPLEMENTED; } { return ER_DUMP_NOT_IMPLEMENTED; }
......
...@@ -130,6 +130,7 @@ static SYMBOL symbols[] = { ...@@ -130,6 +130,7 @@ static SYMBOL symbols[] = {
{ "DESCRIBE", SYM(DESCRIBE),0,0}, { "DESCRIBE", SYM(DESCRIBE),0,0},
{ "DIRECTORY", SYM(DIRECTORY_SYM),0,0}, { "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
{ "DISABLE", SYM(DISABLE_SYM),0,0}, { "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISCARD", SYM(DISCARD),0,0},
{ "DISTINCT", SYM(DISTINCT),0,0}, { "DISTINCT", SYM(DISTINCT),0,0},
{ "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */ { "DISTINCTROW", SYM(DISTINCT),0,0}, /* Access likes this */
{ "DIV", SYM(DIV_SYM),0,0}, { "DIV", SYM(DIV_SYM),0,0},
...@@ -200,6 +201,7 @@ static SYMBOL symbols[] = { ...@@ -200,6 +201,7 @@ static SYMBOL symbols[] = {
{ "INNER", SYM(INNER_SYM),0,0}, { "INNER", SYM(INNER_SYM),0,0},
{ "INNOBASE", SYM(INNOBASE_SYM),0,0}, { "INNOBASE", SYM(INNOBASE_SYM),0,0},
{ "INNODB", SYM(INNOBASE_SYM),0,0}, { "INNODB", SYM(INNOBASE_SYM),0,0},
{ "IMPORT", SYM(IMPORT),0,0},
{ "INSERT", SYM(INSERT),0,0}, { "INSERT", SYM(INSERT),0,0},
{ "INSERT_METHOD", SYM(INSERT_METHOD),0,0}, { "INSERT_METHOD", SYM(INSERT_METHOD),0,0},
{ "INT", SYM(INT_SYM),0,0}, { "INT", SYM(INT_SYM),0,0},
...@@ -387,6 +389,7 @@ static SYMBOL symbols[] = { ...@@ -387,6 +389,7 @@ static SYMBOL symbols[] = {
{ "SUPER", SYM(SUPER_SYM),0,0}, { "SUPER", SYM(SUPER_SYM),0,0},
{ "TABLE", SYM(TABLE_SYM),0,0}, { "TABLE", SYM(TABLE_SYM),0,0},
{ "TABLES", SYM(TABLES),0,0}, { "TABLES", SYM(TABLES),0,0},
{ "TABLESPACE", SYM(TABLESPACE),0,0},
{ "TEMPORARY", SYM(TEMPORARY),0,0}, { "TEMPORARY", SYM(TEMPORARY),0,0},
{ "TERMINATED", SYM(TERMINATED),0,0}, { "TERMINATED", SYM(TERMINATED),0,0},
{ "TEXT", SYM(TEXT_SYM),0,0}, { "TEXT", SYM(TEXT_SYM),0,0},
......
...@@ -486,6 +486,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, ...@@ -486,6 +486,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
enum tablespace_op_type tablespace_op=NO_TABLESPACE_OP,
bool simple_alter=0); bool simple_alter=0);
int mysql_create_like_table(THD *thd, TABLE_LIST *table, int mysql_create_like_table(THD *thd, TABLE_LIST *table,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
......
...@@ -173,6 +173,7 @@ THD::THD():user_time(0), is_fatal_error(0), ...@@ -173,6 +173,7 @@ THD::THD():user_time(0), is_fatal_error(0),
protocol_simple.init(this); protocol_simple.init(this);
protocol_prep.init(this); protocol_prep.init(this);
tablespace_op=FALSE;
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction)); bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions) if (opt_using_transactions)
......
...@@ -502,6 +502,7 @@ class THD :public ilink ...@@ -502,6 +502,7 @@ class THD :public ilink
time_t connect_time,thr_create_time; // track down slow pthread_create time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default; thr_lock_type update_lock_default;
delayed_insert *di; delayed_insert *di;
my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
struct st_transactions { struct st_transactions {
IO_CACHE trans_log; IO_CACHE trans_log;
THD_TRANS all; // Trans since BEGIN WORK THD_TRANS all; // Trans since BEGIN WORK
......
...@@ -110,6 +110,11 @@ enum olap_type ...@@ -110,6 +110,11 @@ enum olap_type
UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE UNSPECIFIED_OLAP_TYPE, CUBE_TYPE, ROLLUP_TYPE
}; };
enum tablespace_op_type
{
NO_TABLESPACE_OP, DISCARD_TABLESPACE, IMPORT_TABLESPACE
};
/* /*
The state of the lex parsing for selects The state of the lex parsing for selects
...@@ -530,6 +535,7 @@ typedef struct st_lex ...@@ -530,6 +535,7 @@ typedef struct st_lex
enum ha_rkey_function ha_rkey_mode; enum ha_rkey_function ha_rkey_mode;
enum enum_enable_or_disable alter_keys_onoff; enum enum_enable_or_disable alter_keys_onoff;
enum enum_var_type option_type; enum enum_var_type option_type;
enum tablespace_op_type tablespace_op;
uint uint_geom_type; uint uint_geom_type;
uint grant, grant_tot_col, which_columns; uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option; uint fk_delete_opt, fk_update_opt, fk_match_option;
......
...@@ -2207,7 +2207,9 @@ mysql_execute_command(THD *thd) ...@@ -2207,7 +2207,9 @@ mysql_execute_command(THD *thd)
select_lex->order_list.elements, select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates, lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter); lex->alter_keys_onoff,
lex->tablespace_op,
lex->simple_alter);
} }
break; break;
} }
......
...@@ -1748,6 +1748,70 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt) ...@@ -1748,6 +1748,70 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
&handler::check)); &handler::check));
} }
/* table_list should contain just one table */
int mysql_discard_or_import_tablespace(THD *thd,
TABLE_LIST *table_list,
enum tablespace_op_type tablespace_op)
{
TABLE *table;
my_bool discard;
int error;
DBUG_ENTER("mysql_discard_or_import_tablespace");
/* Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
ALTER TABLE */
thd->proc_info="discard_or_import_tablespace";
if (tablespace_op == DISCARD_TABLESPACE)
discard = TRUE;
else
discard = FALSE;
thd->tablespace_op=TRUE; /* we set this flag so that ha_innobase::open
and ::external_lock() do not complain when we
lock the table */
mysql_ha_closeall(thd, table_list);
if (!(table=open_ltable(thd,table_list,TL_WRITE)))
{
thd->tablespace_op=FALSE;
DBUG_RETURN(-1);
}
thd->tablespace_op=FALSE;
error=table->file->discard_or_import_tablespace(discard);
thd->proc_info="end";
if (error)
goto err;
/* The 0 in the call below means 'not in a transaction', which means
immediate invalidation; that is probably what we wish here */
query_cache_invalidate3(thd, table_list, 0);
/* The ALTER TABLE is always in its own transaction */
error = ha_commit_stmt(thd);
if (ha_commit(thd))
error=1;
if (error)
goto err;
mysql_update_log.write(thd, thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
mysql_bin_log.write(&qinfo);
}
err:
close_thread_tables(thd);
if (error == 0) {
send_ok(thd);
DBUG_RETURN(0);
}
DBUG_RETURN(error);
}
int mysql_alter_table(THD *thd,char *new_db, char *new_name, int mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info, HA_CREATE_INFO *create_info,
...@@ -1759,6 +1823,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1759,6 +1823,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
enum tablespace_op_type tablespace_op,
bool simple_alter) bool simple_alter)
{ {
TABLE *table,*new_table; TABLE *table,*new_table;
...@@ -1771,6 +1836,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1771,6 +1836,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
ulonglong next_insert_id; ulonglong next_insert_id;
uint save_time_stamp,db_create_options, used_fields; uint save_time_stamp,db_create_options, used_fields;
enum db_type old_db_type,new_db_type; enum db_type old_db_type,new_db_type;
thr_lock_type lock_type;
DBUG_ENTER("mysql_alter_table"); DBUG_ENTER("mysql_alter_table");
thd->proc_info="init"; thd->proc_info="init";
...@@ -1781,6 +1847,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1781,6 +1847,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
used_fields=create_info->used_fields; used_fields=create_info->used_fields;
mysql_ha_closeall(thd, table_list); mysql_ha_closeall(thd, table_list);
if (tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ))) if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -1834,8 +1904,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1834,8 +1904,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->row_type == ROW_TYPE_NOT_USED) if (create_info->row_type == ROW_TYPE_NOT_USED)
create_info->row_type=table->row_type; create_info->row_type=table->row_type;
/* In some simple cases we need not to recreate the table */
thd->proc_info="setup"; thd->proc_info="setup";
if (simple_alter && !table->tmp_table) if (simple_alter && !table->tmp_table)
{ {
...@@ -1860,6 +1928,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1860,6 +1928,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
} }
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
} }
if (!error) if (!error)
{ {
switch (keys_onoff) { switch (keys_onoff) {
...@@ -2395,8 +2464,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2395,8 +2464,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err; goto err;
} }
} }
/* The ALTER TABLE is always in its own transaction */
/* The ALTER TABLE is always in it's own transaction */
error = ha_commit_stmt(thd); error = ha_commit_stmt(thd);
if (ha_commit(thd)) if (ha_commit(thd))
error=1; error=1;
...@@ -2695,4 +2763,3 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt) ...@@ -2695,4 +2763,3 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
table->table=0; table->table=0;
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -211,6 +211,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -211,6 +211,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DESCRIBE %token DESCRIBE
%token DES_KEY_FILE %token DES_KEY_FILE
%token DISABLE_SYM %token DISABLE_SYM
%token DISCARD
%token DISTINCT %token DISTINCT
%token DUPLICATE_SYM %token DUPLICATE_SYM
%token DYNAMIC_SYM %token DYNAMIC_SYM
...@@ -244,6 +245,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -244,6 +245,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token HOSTS_SYM %token HOSTS_SYM
%token IDENT %token IDENT
%token IGNORE_SYM %token IGNORE_SYM
%token IMPORT
%token INDEX %token INDEX
%token INDEXES %token INDEXES
%token INFILE %token INFILE
...@@ -360,6 +362,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -360,6 +362,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SUBJECT_SYM %token SUBJECT_SYM
%token TABLES %token TABLES
%token TABLE_SYM %token TABLE_SYM
%token TABLESPACE
%token TEMPORARY %token TEMPORARY
%token TERMINATED %token TERMINATED
%token TEXT_STRING %token TEXT_STRING
...@@ -1635,6 +1638,7 @@ alter: ...@@ -1635,6 +1638,7 @@ alter:
lex->create_info.table_charset= thd->variables.collation_database; lex->create_info.table_charset= thd->variables.collation_database;
lex->create_info.row_type= ROW_TYPE_NOT_USED; lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_keys_onoff=LEAVE_AS_IS; lex->alter_keys_onoff=LEAVE_AS_IS;
lex->tablespace_op=NO_TABLESPACE_OP;
lex->simple_alter=1; lex->simple_alter=1;
} }
alter_list alter_list
...@@ -1648,6 +1652,8 @@ alter: ...@@ -1648,6 +1652,8 @@ alter:
alter_list: alter_list:
| DISCARD TABLESPACE { Lex->tablespace_op=DISCARD_TABLESPACE; }
| IMPORT TABLESPACE { Lex->tablespace_op=IMPORT_TABLESPACE; }
| alter_list_item | alter_list_item
| alter_list ',' alter_list_item; | alter_list ',' alter_list_item;
......
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