diff options
author | unknown <heikki@hundin.mysql.fi> | 2003-10-13 11:20:19 +0300 |
---|---|---|
committer | unknown <heikki@hundin.mysql.fi> | 2003-10-13 11:20:19 +0300 |
commit | 423747b570b5f01b4d2dd06da991f6a8ce15101f (patch) | |
tree | 5d5b7191e57ae4eafdff3f6a259ba37729217404 /innobase | |
parent | 963d7baba7a1c37bd2154f04303df8e469f15049 (diff) | |
download | mariadb-git-423747b570b5f01b4d2dd06da991f6a8ce15101f.tar.gz |
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
Diffstat (limited to 'innobase')
-rw-r--r-- | innobase/btr/btr0btr.c | 3 | ||||
-rw-r--r-- | innobase/btr/btr0sea.c | 4 | ||||
-rw-r--r-- | innobase/buf/buf0buf.c | 32 | ||||
-rw-r--r-- | innobase/buf/buf0flu.c | 26 | ||||
-rw-r--r-- | innobase/buf/buf0lru.c | 83 | ||||
-rw-r--r-- | innobase/buf/buf0rea.c | 3 | ||||
-rw-r--r-- | innobase/fil/fil0fil.c | 41 | ||||
-rw-r--r-- | innobase/ha/ha0ha.c | 69 | ||||
-rw-r--r-- | innobase/ha/hash0hash.c | 1 | ||||
-rw-r--r-- | innobase/include/buf0buf.h | 7 | ||||
-rw-r--r-- | innobase/include/buf0buf.ic | 11 | ||||
-rw-r--r-- | innobase/include/ha0ha.h | 2 | ||||
-rw-r--r-- | innobase/include/ha0ha.ic | 35 | ||||
-rw-r--r-- | innobase/include/hash0hash.h | 4 | ||||
-rw-r--r-- | innobase/include/ibuf0ibuf.ic | 2 | ||||
-rw-r--r-- | innobase/include/row0mysql.h | 39 | ||||
-rw-r--r-- | innobase/page/page0page.c | 3 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 3 | ||||
-rw-r--r-- | innobase/row/row0purge.c | 8 | ||||
-rw-r--r-- | innobase/row/row0uins.c | 7 | ||||
-rw-r--r-- | innobase/row/row0umod.c | 7 |
21 files changed, 284 insertions, 106 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 1af9336ce72..3d11cbe1748 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -426,7 +426,8 @@ btr_page_free_for_ibuf( flst_add_first(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, 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)); } /****************************************************************** diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 8dbffd82a20..e49ee15f5ea 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -776,8 +776,8 @@ btr_search_guess_on_hash( goto failure; } - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); - ut_ad(page_rec_is_user_rec(rec)); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(page_rec_is_user_rec(rec)); btr_cur_position(index, rec, cursor); diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 1e1c6b25c1d..b403cc4df0d 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -468,6 +468,11 @@ buf_block_init( 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)); ut_ad(rw_lock_validate(&(block->lock))); @@ -687,6 +692,7 @@ buf_pool_init( } UT_LIST_ADD_LAST(free, buf_pool->free, block); + block->in_free_list = TRUE; } mutex_exit(&(buf_pool->mutex)); @@ -830,7 +836,7 @@ buf_page_make_young( 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); @@ -845,7 +851,7 @@ buf_block_free( /*===========*/ 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)); @@ -1109,6 +1115,8 @@ loop: goto loop; } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + must_read = FALSE; if (block->io_fix == BUF_IO_READ) { @@ -1407,6 +1415,8 @@ buf_page_get_known_nowait( return(FALSE); } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line); #else @@ -1517,7 +1527,7 @@ buf_page_init( buf_block_t* block) /* in: block to init */ { 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 */ block->magic_n = BUF_BLOCK_MAGIC_N; @@ -1533,6 +1543,18 @@ buf_page_init( /* 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, buf_page_address_fold(space, offset), block); @@ -1605,7 +1627,7 @@ buf_page_init_for_read( block = buf_block_alloc(); - ut_ad(block); + ut_a(block); mutex_enter(&(buf_pool->mutex)); @@ -1769,6 +1791,8 @@ buf_page_io_complete( ut_ad(block); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + io_type = block->io_fix; if (io_type == BUF_IO_READ) { diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c index 3f8022f36bc..27a1829942d 100644 --- a/innobase/buf/buf0flu.c +++ b/innobase/buf/buf0flu.c @@ -50,6 +50,8 @@ buf_flush_insert_into_flush_list( { 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_dulint_cmp( (UT_LIST_GET_FIRST(buf_pool->flush_list)) @@ -131,7 +133,7 @@ buf_flush_ready_for_flush( ulint flush_type)/* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */ { 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) && (block->io_fix == 0)) { @@ -163,6 +165,8 @@ buf_flush_write_complete( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + block->oldest_modification = ut_dulint_zero; UT_LIST_REMOVE(flush_list, buf_pool->flush_list, block); @@ -282,6 +286,8 @@ buf_flush_buffered_writes(void) for (i = 0; i < trx_doublewrite->first_free; 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, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); @@ -321,6 +327,8 @@ buf_flush_post_to_doublewrite_buf( try_again: mutex_enter(&(trx_doublewrite->mutex)); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (trx_doublewrite->first_free >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { mutex_exit(&(trx_doublewrite->mutex)); @@ -395,6 +403,8 @@ buf_flush_write_block_low( /*======================*/ buf_block_t* block) /* in: buffer block to write */ { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif @@ -443,7 +453,7 @@ buf_flush_try_page( 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 && block && buf_flush_ready_for_flush(block, flush_type)) { @@ -635,6 +645,7 @@ buf_flush_try_neighbors( for (i = low; i < high; 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 && !block->old) { @@ -703,10 +714,10 @@ buf_flush_batch( ulint offset; ibool found; - ut_ad((flush_type == BUF_FLUSH_LRU) || (flush_type == BUF_FLUSH_LIST)); - ut_ad((flush_type != BUF_FLUSH_LIST) || - sync_thread_levels_empty_gen(TRUE)); - + ut_ad((flush_type == BUF_FLUSH_LRU) + || (flush_type == BUF_FLUSH_LIST)); + ut_ad((flush_type != BUF_FLUSH_LIST) + || sync_thread_levels_empty_gen(TRUE)); mutex_enter(&(buf_pool->mutex)); if ((buf_pool->n_flush[flush_type] > 0) @@ -737,7 +748,6 @@ buf_flush_batch( ut_ad(flush_type == BUF_FLUSH_LIST); block = UT_LIST_GET_LAST(buf_pool->flush_list); - if (!block || (ut_dulint_cmp(block->oldest_modification, lsn_limit) >= 0)) { @@ -756,6 +766,7 @@ buf_flush_batch( function a pointer to a block in the list! */ while ((block != NULL) && !found) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (buf_flush_ready_for_flush(block, flush_type)) { @@ -781,7 +792,6 @@ buf_flush_batch( } else if (flush_type == BUF_FLUSH_LRU) { block = UT_LIST_GET_PREV(LRU, block); - } else { ut_ad(flush_type == BUF_FLUSH_LIST); diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 5d48d460745..55a5ecbeba5 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -82,6 +82,8 @@ scan_again: block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + if (block->space == id && (block->buf_fix_count > 0 || block->io_fix != 0)) { @@ -199,19 +201,16 @@ buf_LRU_search_and_free_block( mutex_enter(&(buf_pool->mutex)); freed = FALSE; - block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { - + ut_a(block->in_LRU_list); if (buf_flush_ready_for_replace(block)) { - if (buf_debug_prints) { printf( "Putting space %lu page %lu to free list\n", block->space, block->offset); } - buf_LRU_block_remove_hashed_page(block); mutex_exit(&(buf_pool->mutex)); @@ -223,25 +222,21 @@ buf_LRU_search_and_free_block( if (block->frame) { btr_search_drop_page_hash_index(block->frame); } - mutex_enter(&(buf_pool->mutex)); ut_a(block->buf_fix_count == 0); buf_LRU_block_free_hashed_page(block); - freed = TRUE; break; } - block = UT_LIST_GET_PREV(LRU, block); distance++; if (!freed && n_iterations <= 10 && distance > 100 + (n_iterations * buf_pool->curr_size) / 10) { - buf_pool->LRU_flush_ended = 0; mutex_exit(&(buf_pool->mutex)); @@ -249,15 +244,12 @@ buf_LRU_search_and_free_block( return(FALSE); } } - if (buf_pool->LRU_flush_ended > 0) { buf_pool->LRU_flush_ended--; } - - if (!freed) { + if (!freed) { buf_pool->LRU_flush_ended = 0; } - mutex_exit(&(buf_pool->mutex)); return(freed); @@ -355,7 +347,11 @@ loop: if (UT_LIST_GET_LEN(buf_pool->free) > 0) { block = UT_LIST_GET_FIRST(buf_pool->free); + ut_a(block->in_free_list); 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 (block->frame) { @@ -466,7 +462,7 @@ buf_LRU_old_adjust_len(void) ulint old_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(3 * (BUF_LRU_OLD_MIN_LEN / 8) > BUF_LRU_OLD_TOLERANCE + 5); @@ -474,6 +470,8 @@ buf_LRU_old_adjust_len(void) old_len = buf_pool->LRU_old_len; 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 */ if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) { @@ -490,7 +488,7 @@ buf_LRU_old_adjust_len(void) buf_pool->LRU_old); buf_pool->LRU_old_len--; } 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 */ return; } @@ -498,9 +496,8 @@ buf_LRU_old_adjust_len(void) } /*********************************************************************** -Initializes the old blocks pointer in the LRU list. -This function should be called when the LRU list grows to -BUF_LRU_OLD_MIN_LEN length. */ +Initializes the old blocks pointer in the LRU list. This function should be +called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */ static void buf_LRU_old_init(void) @@ -508,7 +505,7 @@ buf_LRU_old_init(void) { 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 the adjust function to move the LRU_old pointer to the right @@ -517,6 +514,8 @@ buf_LRU_old_init(void) block = UT_LIST_GET_FIRST(buf_pool->LRU); while (block != NULL) { + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->in_LRU_list); block->old = TRUE; block = UT_LIST_GET_NEXT(LRU, block); } @@ -539,6 +538,9 @@ buf_LRU_remove_block( ut_ad(block); 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, move it backward one step */ @@ -552,11 +554,12 @@ buf_LRU_remove_block( (buf_pool->LRU_old)->old = TRUE; buf_pool->LRU_old_len++; - ut_ad(buf_pool->LRU_old); + ut_a(buf_pool->LRU_old); } /* Remove the block from the LRU list */ UT_LIST_REMOVE(LRU, buf_pool->LRU, block); + block->in_LRU_list = FALSE; if (srv_use_awe && block->frame) { /* Remove from the list of mapped pages */ @@ -599,6 +602,8 @@ buf_LRU_add_block_to_end_low( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + block->old = TRUE; last_block = UT_LIST_GET_LAST(buf_pool->LRU); @@ -609,7 +614,9 @@ buf_LRU_add_block_to_end_low( block->LRU_position = buf_pool_clock_tic(); } + ut_a(!block->in_LRU_list); UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block); + block->in_LRU_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ @@ -658,6 +665,9 @@ buf_LRU_add_block_low( ut_ad(block); ut_ad(mutex_own(&(buf_pool->mutex))); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(!block->in_LRU_list); + block->old = old; cl = buf_pool_clock_tic(); @@ -687,6 +697,8 @@ buf_LRU_add_block_low( 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) { ut_ad(buf_pool->LRU_old); @@ -755,9 +767,12 @@ buf_LRU_block_free_non_file_page( ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(block); - ut_ad((block->state == BUF_BLOCK_MEMORY) + ut_a((block->state == BUF_BLOCK_MEMORY) || (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; #ifdef UNIV_DEBUG @@ -765,6 +780,7 @@ buf_LRU_block_free_non_file_page( memset(block->frame, '\0', UNIV_PAGE_SIZE); #endif UT_LIST_ADD_FIRST(free, buf_pool->free, block); + block->in_free_list = TRUE; if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ @@ -788,8 +804,7 @@ buf_LRU_block_remove_hashed_page( ut_ad(mutex_own(&(buf_pool->mutex))); 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->buf_fix_count == 0); ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0); @@ -802,6 +817,28 @@ buf_LRU_block_remove_hashed_page( 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, buf_page_address_fold(block->space, block->offset), block); @@ -819,7 +856,7 @@ buf_LRU_block_free_hashed_page( be in a state where it can be freed */ { 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; diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c index 8cc379e75d8..0fa6912ba1d 100644 --- a/innobase/buf/buf0rea.c +++ b/innobase/buf/buf0rea.c @@ -129,6 +129,8 @@ buf_read_page_low( offset, sync); } + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + *err = fil_io(OS_FILE_READ | wake_later, sync, space, offset, 0, UNIV_PAGE_SIZE, @@ -604,7 +606,6 @@ buf_read_ibuf_merge_pages( } for (i = 0; i < n_stored; i++) { - if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space_ids[i], space_versions[i], page_nos[i]); diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index 2b0138ccb5a..f96d98c7b2d 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -1517,8 +1517,8 @@ try_again: if (space == NULL) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: cannot delete tablespace %lu because it is not found\n" -"InnoDB: in the tablespace memory cache.\n", id); +" InnoDB: Error: cannot delete tablespace %lu\n" +"InnoDB: because it is not found in the tablespace memory cache.\n", id); mutex_exit(&(system->mutex)); @@ -2426,19 +2426,24 @@ fil_space_for_table_exists_in_mem( if (namespace == NULL) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id or name does not exist. Have\n" -"InnoDB: you deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, name); +" InnoDB: Error: table %s\n" +"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" +"InnoDB: but tablespace with that id or name does not exist. Have\n" +"InnoDB: you deleted or moved .ibd files?\n", + name, id); } else { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id does not exist. There is\n" +" InnoDB: Error: table %s\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: you deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, namespace->name, namespace->id, name); +"InnoDB: you deleted or moved .ibd files?\n", + 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)); @@ -2448,16 +2453,20 @@ fil_space_for_table_exists_in_mem( if (0 != strcmp(space->name, path)) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: table %s in InnoDB data dictionary has tablespace\n" -"InnoDB: id %lu, but tablespace with that id has name %s. Have you\n" -"InnoDB: deleted or moved .ibd files? We cannot open table %s now.\n", - name, id, space->name, name); +" InnoDB: Error: table %s\n" +"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n" +"InnoDB: but tablespace with that id has name %s.\n" +"InnoDB: Have you deleted or moved .ibd files?", name, id, space->name); if (namespace != NULL) { fprintf(stderr, -"InnoDB: There is a tablespace with the right name %s, but its id is %lu.\n", - namespace->name, namespace->id); +"InnoDB: There is a tablespace with the right name\n" +"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)); return(FALSE); diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c index c7e23d0be1e..87c32bf5dbd 100644 --- a/innobase/ha/ha0ha.c +++ b/innobase/ha/ha0ha.c @@ -34,6 +34,12 @@ ha_create( table = hash_create(n); + if (in_btr_search) { + table->adaptive = TRUE; + } else { + table->adaptive = FALSE; + } + if (n_mutexes == 0) { if (in_btr_search) { table->heap = mem_heap_create_in_btr_search(4096); @@ -106,6 +112,7 @@ ha_insert_for_fold( hash_cell_t* cell; ha_node_t* node; ha_node_t* prev_node; + buf_block_t* prev_block; ulint hash; ut_ad(table && data); @@ -119,6 +126,12 @@ ha_insert_for_fold( while (prev_node != NULL) { 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; @@ -142,6 +155,11 @@ ha_insert_for_fold( } ha_node_set_data(node, data); + + if (table->adaptive) { + buf_block_align(data)->n_pointers++; + } + node->fold = fold; node->next = NULL; @@ -174,6 +192,11 @@ ha_delete_hash_node( hash_table_t* table, /* in: hash table */ 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); } @@ -199,6 +222,35 @@ ha_delete( 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 points to the page given. */ @@ -229,10 +281,10 @@ ha_remove_all_nodes_to_page( node = ha_chain_get_first(table, fold); } else { - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } } - +#ifdef UNIV_DEBUG /* Check that all nodes really got deleted */ node = ha_chain_get_first(table, fold); @@ -240,8 +292,9 @@ ha_remove_all_nodes_to_page( while (node) { 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( hash_table_t* table) /* in: hash table */ { hash_cell_t* cell; -/* - ha_node_t* node; - ulint len = 0; - ulint max_len = 0; - ulint nodes = 0; -*/ +/* ha_node_t* node; + ulint nodes = 0; + ulint len = 0; + ulint max_len = 0; */ ulint cells = 0; ulint n_bufs; ulint i; diff --git a/innobase/ha/hash0hash.c b/innobase/ha/hash0hash.c index 1f7edf9d7d2..facdea66198 100644 --- a/innobase/ha/hash0hash.c +++ b/innobase/ha/hash0hash.c @@ -91,6 +91,7 @@ hash_create( array = ut_malloc(sizeof(hash_cell_t) * prime); + table->adaptive = FALSE; table->array = array; table->n_cells = prime; table->n_mutexes = 0; diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 0457da60534..3f2fd5bbbe0 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -755,12 +755,16 @@ struct buf_block_struct{ UT_LIST_NODE_T(buf_block_t) free; /* 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; /* node of the LRU list */ UT_LIST_NODE_T(buf_block_t) awe_LRU_free_mapped; /* in the AWE version node in the list of free and LRU blocks which are 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 decreases (or may stay constant if the block is in the old blocks) toward @@ -821,6 +825,9 @@ struct buf_block_struct{ complete, though: there may have been hash collisions, record deletions, 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: number of full fields */ ulint curr_n_bytes; /* number of bytes in hash indexing */ diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic index d4e7122f3f9..281bb1ea527 100644 --- a/innobase/include/buf0buf.ic +++ b/innobase/include/buf0buf.ic @@ -28,7 +28,6 @@ buf_block_peek_if_too_old( { if (buf_pool->freed_page_clock >= block->freed_page_clock + 1 + (buf_pool->curr_size / 1024)) { - return(TRUE); } @@ -169,7 +168,7 @@ buf_block_get_space( ut_ad(block); ut_ad(block >= buf_pool->blocks); 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); return(block->space); @@ -187,7 +186,7 @@ buf_block_get_page_no( ut_ad(block); ut_ad(block >= buf_pool->blocks); 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); return(block->offset); @@ -550,6 +549,8 @@ buf_page_hash_get( HASH_SEARCH(hash, buf_pool->page_hash, fold, block, (block->space == space) && (block->offset == offset)); + ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE); + return(block); } @@ -617,8 +618,8 @@ buf_page_release( mutex_enter_fast(&(buf_pool->mutex)); - ut_ad(block->state == BUF_BLOCK_FILE_PAGE); - ut_ad(block->buf_fix_count > 0); + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + ut_a(block->buf_fix_count > 0); if (rw_latch == RW_X_LATCH && mtr->modifications) { diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h index 0beac928b7e..c3fc04b47bb 100644 --- a/innobase/include/ha0ha.h +++ b/innobase/include/ha0ha.h @@ -28,7 +28,7 @@ ha_search_and_get_data( /************************************************************* 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( /*==========================*/ diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic index 761bc3b20de..22da7107659 100644 --- a/innobase/include/ha0ha.ic +++ b/innobase/include/ha0ha.ic @@ -49,7 +49,6 @@ ha_node_t* ha_chain_get_next( /*==============*/ /* out: next node, NULL if none */ - hash_table_t* table __attribute__((unused)), /* in: hash table */ ha_node_t* node) /* in: hash chain node */ { ut_ad(table); @@ -94,7 +93,7 @@ ha_search( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -124,7 +123,7 @@ ha_search_and_get_data( return(node->data); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -139,7 +138,6 @@ ha_next( /* out: pointer to the next hash table node in chain with the fold value, NULL if not found */ - hash_table_t* table, /* in: hash table */ ha_node_t* node) /* in: hash table node */ { ulint fold; @@ -148,7 +146,7 @@ ha_next( 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) { if (node->fold == fold) { @@ -156,7 +154,7 @@ ha_next( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } return(NULL); @@ -186,36 +184,13 @@ ha_search_with_data( return(node); } - node = ha_chain_get_next(table, node); + node = ha_chain_get_next(node); } 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 it from the hash table, if found. */ UNIV_INLINE diff --git a/innobase/include/hash0hash.h b/innobase/include/hash0hash.h index 378925a5bea..2e9ab498116 100644 --- a/innobase/include/hash0hash.h +++ b/innobase/include/hash0hash.h @@ -100,7 +100,7 @@ Deletes a struct from a hash table. */ \ while (struct3333->NAME != DATA) {\ \ - ut_ad(struct3333)\ + ut_a(struct3333)\ struct3333 = struct3333->NAME;\ }\ \ @@ -322,6 +322,8 @@ struct hash_cell_struct{ /* The hash table structure */ 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 */ hash_cell_t* array; /* pointer to cell array */ ulint n_mutexes;/* if mutexes != NULL, then the number of diff --git a/innobase/include/ibuf0ibuf.ic b/innobase/include/ibuf0ibuf.ic index 0886c8c02cc..68f7ce9c1d0 100644 --- a/innobase/include/ibuf0ibuf.ic +++ b/innobase/include/ibuf0ibuf.ic @@ -218,7 +218,7 @@ ibuf_update_free_bits_if_full( } 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 cannot make inserts using the insert buffer from slipping out of the buffer pool */ diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 1964f53dabb..fade3709631 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -339,6 +339,45 @@ row_drop_table_for_mysql( char* name, /* in: table name */ 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. */ int diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index e087941a970..2422f0ff87e 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -582,7 +582,8 @@ byte* page_parse_delete_rec_list( /*=======================*/ /* 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* end_ptr,/* in: buffer end */ page_t* page, /* in: page or NULL */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 497b74fd320..5d5985d16af 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -2007,9 +2007,6 @@ row_import_tablespace_for_mysql( 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) { table->ibd_file_missing = FALSE; table->tablespace_discarded = FALSE; diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c index 104d71eda2d..99332dc275d 100644 --- a/innobase/row/row0purge.c +++ b/innobase/row/row0purge.c @@ -529,6 +529,14 @@ row_purge_parse_undo_rec( 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); if (clust_index == NULL) { diff --git a/innobase/row/row0uins.c b/innobase/row/row0uins.c index fff67dcd627..08f0e29c839 100644 --- a/innobase/row/row0uins.c +++ b/innobase/row/row0uins.c @@ -258,6 +258,13 @@ row_undo_ins_parse_undo_rec( 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); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c index b22e494f891..0a050e0a1b6 100644 --- a/innobase/row/row0umod.c +++ b/innobase/row/row0umod.c @@ -620,6 +620,13 @@ row_undo_mod_parse_undo_rec( 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); ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, |