diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-02-23 23:05:12 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-03-03 16:55:50 +0200 |
commit | 27b9989d316163d00177bfee8fceb10995c2ba9b (patch) | |
tree | b30f3170e4ab4b70019bb89e8172d1c46b2b2210 /storage/innobase | |
parent | 545f49dac361aa80aea26625233f9856ef4e16f5 (diff) | |
download | mariadb-git-27b9989d316163d00177bfee8fceb10995c2ba9b.tar.gz |
MDEV-12121 Introduce build option WITH_INNODB_AHI to disable innodb_adaptive_hash_index
The InnoDB adaptive hash index is sometimes degrading the performance of
InnoDB, and it is sometimes disabled to get more consistent performance.
We should have a compile-time option to disable the adaptive hash index.
Let us introduce two options:
OPTION(WITH_INNODB_AHI "Include innodb_adaptive_hash_index" ON)
OPTION(WITH_INNODB_ROOT_GUESS "Cache index root block descriptors" ON)
where WITH_INNODB_AHI always implies WITH_INNODB_ROOT_GUESS.
As part of this change, the misleadingly named function
trx_search_latch_release_if_reserved(trx) will be replaced with the macro
trx_assert_no_search_latch(trx) that will be empty unless
BTR_CUR_HASH_ADAPT is defined (cmake -DWITH_INNODB_AHI=ON).
We will also remove the unused column
INFORMATION_SCHEMA.INNODB_TRX.TRX_ADAPTIVE_HASH_TIMEOUT.
In MariaDB Server 10.1, it used to reflect the value of
trx_t::search_latch_timeout which could be adjusted during
row_search_for_mysql(). In 10.2, there is no such field.
Other than the removal of the unused column TRX_ADAPTIVE_HASH_TIMEOUT,
this is an almost non-functional change to the server when using the
default build options.
Some tests are adjusted so that they will work with both
-DWITH_INNODB_AHI=ON and -DWITH_INNODB_AHI=OFF. The test
innodb.innodb_monitor has been renamed to innodb.monitor
in order to track MySQL 5.7, and the duplicate tests
sys_vars.innodb_monitor_* are removed.
Diffstat (limited to 'storage/innobase')
41 files changed, 508 insertions, 390 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index bdf3bd2eca7..0abc930c11d 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -105,22 +105,24 @@ throughput clearly from about 100000. */ #define BTR_CUR_FINE_HISTORY_LENGTH 100000 /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */ -ulint btr_cur_n_non_sea = 0; -/** Number of successful adaptive hash index lookups in -btr_cur_search_to_nth_level(). */ -ulint btr_cur_n_sea = 0; +ulint btr_cur_n_non_sea; /** Old value of btr_cur_n_non_sea. Copied by srv_refresh_innodb_monitor_stats(). Referenced by srv_printf_innodb_monitor(). */ -ulint btr_cur_n_non_sea_old = 0; +ulint btr_cur_n_non_sea_old; +#ifdef BTR_CUR_HASH_ADAPT +/** Number of successful adaptive hash index lookups in +btr_cur_search_to_nth_level(). */ +ulint btr_cur_n_sea; /** Old value of btr_cur_n_sea. Copied by srv_refresh_innodb_monitor_stats(). Referenced by srv_printf_innodb_monitor(). */ -ulint btr_cur_n_sea_old = 0; +ulint btr_cur_n_sea_old; +#endif /* BTR_CUR_HASH_ADAPT */ #ifdef UNIV_DEBUG /* Flag to limit optimistic insert records */ -uint btr_cur_limit_optimistic_insert_debug = 0; +uint btr_cur_limit_optimistic_insert_debug; #endif /* UNIV_DEBUG */ /** In the optimistic insert, if the insert does not fit, but this much space @@ -953,7 +955,7 @@ btr_cur_search_to_nth_level( if (has_search_latch) { /* Release possible search latch to obey latching order */ - rw_lock_s_unlock(btr_get_search_latch(index)); + btr_search_s_unlock(index); } /* Store the position of the tree latch we push to mtr so that we @@ -1477,6 +1479,7 @@ retry_page_get: cursor->low_match = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1; } +#ifdef BTR_CUR_HASH_ADAPT } else if (height == 0 && btr_search_enabled && !dict_index_is_spatial(index)) { /* The adaptive hash index is only used when searching @@ -1486,6 +1489,7 @@ retry_page_get: page_cur_search_with_match_bytes( block, index, tuple, page_mode, &up_match, &up_bytes, &low_match, &low_bytes, page_cursor); +#endif /* BTR_CUR_HASH_ADAPT */ } else { /* Search for complete index fields. */ up_bytes = low_bytes = 0; @@ -1966,7 +1970,7 @@ need_opposite_intention: index, autoinc, mtr, false); } -#ifdef BTR_CUR_ADAPT +#ifdef BTR_CUR_HASH_ADAPT /* We do a dirty read of btr_search_enabled here. We will properly check btr_search_enabled again in btr_search_build_page_hash_index() before building a @@ -1978,7 +1982,7 @@ need_opposite_intention: ) { btr_search_info_update(index, cursor); } -#endif +#endif /* BTR_CUR_HASH_ADAPT */ ut_ad(cursor->up_match != ULINT_UNDEFINED || mode != PAGE_CUR_GE); ut_ad(cursor->up_match != ULINT_UNDEFINED @@ -2014,8 +2018,7 @@ func_exit: } if (has_search_latch) { - - rw_lock_s_lock(btr_get_search_latch(index)); + btr_search_s_lock(index); } if (mbr_adj) { @@ -3271,12 +3274,12 @@ btr_cur_pessimistic_insert( } } -#ifdef BTR_CUR_ADAPT +#ifdef BTR_CUR_HASH_ADAPT # ifdef MYSQL_INDEX_DISABLE_AHI if (index->disable_ahi); else # endif btr_search_update_hash_on_insert(cursor); -#endif +#endif /* BTR_CUR_HASH_ADAPT */ if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) { lock_update_insert(btr_cur_get_block(cursor), *rec); @@ -3609,7 +3612,6 @@ btr_cur_update_in_place( rec_t* rec; roll_ptr_t roll_ptr = 0; ulint was_delete_marked; - ibool is_hashed; rec = btr_cur_get_rec(cursor); index = cursor->index; @@ -3668,9 +3670,8 @@ btr_cur_update_in_place( was_delete_marked = rec_get_deleted_flag( rec, page_is_comp(buf_block_get_frame(block))); - is_hashed = (block->index != NULL); - - if (is_hashed) { +#ifdef BTR_CUR_HASH_ADAPT + if (block->index) { /* TO DO: Can we skip this if none of the fields index->search_info->curr_n_fields are being updated? */ @@ -3687,14 +3688,17 @@ btr_cur_update_in_place( btr_search_update_hash_on_delete(cursor); } - rw_lock_x_lock(btr_get_search_latch(index)); + btr_search_x_lock(index); } +#endif /* BTR_CUR_HASH_ADAPT */ row_upd_rec_in_place(rec, index, offsets, update, page_zip); - if (is_hashed) { - rw_lock_x_unlock(btr_get_search_latch(index)); +#ifdef BTR_CUR_HASH_ADAPT + if (block->index) { + btr_search_x_unlock(index); } +#endif /* BTR_CUR_HASH_ADAPT */ btr_cur_update_in_place_log(flags, rec, index, update, trx_id, roll_ptr, mtr); diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 0af2a8b637c..d777e2abc4d 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -31,6 +31,7 @@ Created 2/17/1996 Heikki Tuuri *************************************************************************/ #include "btr0sea.h" +#ifdef BTR_CUR_HASH_ADAPT #ifdef UNIV_NONINL #include "btr0sea.ic" #endif /* UNIV_NOINL */ @@ -375,43 +376,6 @@ btr_search_enable() btr_search_x_unlock_all(); } -/** Creates and initializes a search info struct. -@param[in] heap heap where created. -@return own: search info struct */ -btr_search_t* -btr_search_info_create(mem_heap_t* heap) -{ - btr_search_t* info; - - info = (btr_search_t*) mem_heap_alloc(heap, sizeof(btr_search_t)); - - ut_d(info->magic_n = BTR_SEARCH_MAGIC_N); - - info->ref_count = 0; - info->root_guess = NULL; - info->withdraw_clock = 0; - - info->hash_analysis = 0; - info->n_hash_potential = 0; - - info->last_hash_succ = FALSE; - -#ifdef UNIV_SEARCH_PERF_STAT - info->n_hash_succ = 0; - info->n_hash_fail = 0; - info->n_patt_succ = 0; - info->n_searches = 0; -#endif /* UNIV_SEARCH_PERF_STAT */ - - /* Set some sensible values */ - info->n_fields = 1; - info->n_bytes = 0; - - info->left_side = TRUE; - - return(info); -} - /** Returns the value of ref_count. The value is protected by latch. @param[in] info search info @param[in] index index identifier @@ -2177,3 +2141,4 @@ btr_search_validate() } #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index b9968f39a81..b3c11c62929 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1536,7 +1536,9 @@ buf_block_init( ut_d(block->page.file_page_was_freed = FALSE); +#ifdef BTR_CUR_HASH_ADAPT block->index = NULL; +#endif /* BTR_CUR_HASH_ADAPT */ block->skip_flush_check = false; ut_d(block->page.in_page_hash = FALSE); @@ -1547,9 +1549,11 @@ buf_block_init( ut_d(block->in_unzip_LRU_list = FALSE); ut_d(block->in_withdraw_list = FALSE); -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG block->n_pointers = 0; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ page_zip_des_init(&block->page.zip); mutex_create(LATCH_ID_BUF_BLOCK_MUTEX, &block->mutex); @@ -2260,11 +2264,13 @@ buf_page_realloc( /* set other flags of buf_block_t */ +#ifdef BTR_CUR_HASH_ADAPT ut_ad(!block->index); new_block->index = NULL; new_block->n_hash_helps = 0; new_block->n_fields = 1; new_block->left_side = TRUE; +#endif /* BTR_CUR_HASH_ADAPT */ new_block->lock_hash_val = block->lock_hash_val; ut_ad(new_block->lock_hash_val == lock_rec_hash( @@ -2726,7 +2732,7 @@ buf_pool_resize() buf_pool_mutex_exit(buf_pool); } - +#ifdef BTR_CUR_HASH_ADAPT /* disable AHI if needed */ bool btr_search_disabled = false; @@ -2745,6 +2751,7 @@ buf_pool_resize() if (btr_search_disabled) { ib::info() << "disabled adaptive hash index."; } +#endif /* BTR_CUR_HASH_ADAPT */ /* set withdraw target */ for (ulint i = 0; i < srv_buf_pool_instances; i++) { @@ -3116,7 +3123,10 @@ calc_buf_pool_size: dict_resize(); ib::info() << "Resized hash tables at lock_sys," - " adaptive hash index, dictionary."; +#ifdef BTR_CUR_HASH_ADAPT + " adaptive hash index," +#endif /* BTR_CUR_HASH_ADAPT */ + " dictionary."; } /* normalize ibuf->max_size */ @@ -3130,11 +3140,13 @@ calc_buf_pool_size: srv_buf_pool_old_size = srv_buf_pool_size; } +#ifdef BTR_CUR_HASH_ADAPT /* enable AHI if needed */ if (btr_search_disabled) { btr_search_enable(); ib::info() << "Re-enabled adaptive hash index."; } +#endif /* BTR_CUR_HASH_ADAPT */ char now[32]; @@ -3196,11 +3208,10 @@ DECLARE_THREAD(buf_resize_thread)(void*) OS_THREAD_DUMMY_RETURN; } -/********************************************************************//** -Clears the adaptive hash index on all pages in the buffer pool. */ +#ifdef BTR_CUR_HASH_ADAPT +/** Clear the adaptive hash index on all pages in the buffer pool. */ void -buf_pool_clear_hash_index(void) -/*===========================*/ +buf_pool_clear_hash_index() { ulint p; @@ -3237,6 +3248,7 @@ buf_pool_clear_hash_index(void) } } } +#endif /* BTR_CUR_HASH_ADAPT */ /********************************************************************//** Relocate a buffer control block. Relocates the block on the LRU list @@ -3920,13 +3932,15 @@ buf_block_init_low( /*===============*/ buf_block_t* block) /*!< in: block to init */ { - block->index = NULL; block->skip_flush_check = false; +#ifdef BTR_CUR_HASH_ADAPT + block->index = NULL; block->n_hash_helps = 0; block->n_fields = 1; block->n_bytes = 0; block->left_side = TRUE; +#endif /* BTR_CUR_HASH_ADAPT */ } /********************************************************************//** @@ -3998,6 +4012,7 @@ buf_zip_decompress( return(FALSE); } +#ifdef BTR_CUR_HASH_ADAPT /** Get a buffer block from an adaptive hash index pointer. This function does not return if the block is not identified. @param[in] ptr pointer to within a page frame @@ -4040,6 +4055,7 @@ buf_block_from_ahi(const byte* ptr) ut_ad(state == BUF_BLOCK_FILE_PAGE || state == BUF_BLOCK_REMOVE_HASH); return(block); } +#endif /* BTR_CUR_HASH_ADAPT */ /********************************************************************//** Find out if a pointer belongs to a buf_block_t. It can be a pointer to diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 0169a63e972..ef8c2177b2c 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -219,6 +219,7 @@ buf_LRU_evict_from_unzip_LRU( return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR); } +#ifdef BTR_CUR_HASH_ADAPT /** Attempts to drop page hash index on a batch of pages belonging to a particular space id. @param[in] space_id space id @@ -364,6 +365,7 @@ next_page: buf_LRU_drop_page_hash_batch(id, page_size, page_arr, num_entries); ut_free(page_arr); } +#endif /* BTR_CUR_HASH_ADAPT */ /******************************************************************//** While flushing (or removing dirty) pages from a tablespace we don't @@ -788,7 +790,7 @@ scan_again: bpage->id.space(), bpage->id.page_no(), bpage->state)); - +#ifdef BTR_CUR_HASH_ADAPT if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { /* Do nothing, because the adaptive hash index covers uncompressed pages only. */ @@ -810,6 +812,7 @@ scan_again: goto scan_again; } +#endif /* BTR_CUR_HASH_ADAPT */ if (bpage->oldest_modification != 0) { @@ -911,7 +914,7 @@ buf_LRU_flush_or_remove_pages( buf_pool_t* buf_pool; buf_pool = buf_pool_from_array(i); - +#ifdef BTR_CUR_HASH_ADAPT switch (buf_remove) { case BUF_REMOVE_ALL_NO_WRITE: buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); @@ -927,7 +930,7 @@ buf_LRU_flush_or_remove_pages( table, there is no need to drop the AHI entries. */ break; } - +#endif /* BTR_CUR_HASH_ADAPT */ buf_LRU_remove_pages(buf_pool, id, buf_remove, trx); } } @@ -1206,15 +1209,15 @@ buf_LRU_check_size_of_non_data_objects( + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) { ib::fatal() << "Over 95 percent of the buffer pool is" - " occupied by lock heaps or the adaptive hash index!" + " occupied by lock heaps" +#ifdef BTR_CUR_HASH_ADAPT + " or the adaptive hash index!" +#endif /* BTR_CUR_HASH_ADAPT */ " Check that your transactions do not set too many" - " row locks. Your buffer pool size is " - << (buf_pool->curr_size - / (1024 * 1024 / UNIV_PAGE_SIZE)) << " MB." - " Maybe you should make the buffer pool bigger?" - " We intentionally generate a seg fault to print" - " a stack trace on Linux!"; - + " row locks, or review if" + " innodb_buffer_pool_size=" + << (buf_pool->curr_size >> (20 - UNIV_PAGE_SIZE_SHIFT)) + << "M could be bigger."; } else if (!recv_recovery_is_on() && buf_pool->curr_size == buf_pool->old_size && (UT_LIST_GET_LEN(buf_pool->free) @@ -1228,16 +1231,17 @@ buf_LRU_check_size_of_non_data_objects( leak! */ ib::warn() << "Over 67 percent of the buffer pool is" - " occupied by lock heaps or the adaptive hash" - " index! Check that your transactions do not" - " set too many row locks. Your buffer pool" - " size is " - << (buf_pool->curr_size - / (1024 * 1024 / UNIV_PAGE_SIZE)) - << " MB. Maybe you should make the buffer pool" - " bigger?. Starting the InnoDB Monitor to print" - " diagnostics, including lock heap and hash" - " index sizes."; + " occupied by lock heaps" +#ifdef BTR_CUR_HASH_ADAPT + " or the adaptive hash index!" +#endif /* BTR_CUR_HASH_ADAPT */ + " Check that your transactions do not" + " set too many row locks." + " innodb_buffer_pool_size=" + << (buf_pool->curr_size >> + (20 - UNIV_PAGE_SIZE_SHIFT)) << "M." + " Starting the InnoDB Monitor to print" + " diagnostics."; buf_lru_switched_on_innodb_mon = true; srv_print_innodb_monitor = TRUE; @@ -2103,9 +2107,11 @@ buf_LRU_block_free_non_file_page( return; /* Continue */ } -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ut_a(block->n_pointers == 0); -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ ut_ad(!block->page.in_free_list); ut_ad(!block->page.in_flush_list); ut_ad(!block->page.in_LRU_list); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 943b79c3514..491f29067a8 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1407,8 +1407,6 @@ dict_table_can_be_evicted( ut_a(table->referenced_set.empty()); if (table->get_ref_count() == 0) { - dict_index_t* index; - /* The transaction commit and rollback are called from outside the handler interface. This means that there is a window where the table->n_ref_count can be zero but @@ -1418,7 +1416,8 @@ dict_table_can_be_evicted( return(FALSE); } - for (index = dict_table_get_first_index(table); +#ifdef BTR_CUR_HASH_ADAPT + for (dict_index_t* index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { @@ -1440,6 +1439,7 @@ dict_table_can_be_evicted( return(FALSE); } } +#endif /* BTR_CUR_HASH_ADAPT */ return(TRUE); } @@ -2611,7 +2611,9 @@ dict_index_add_to_cache_w_vcol( UT_LIST_ADD_LAST(table->indexes, new_index); new_index->table = table; new_index->table_name = table->name.m_name; +#ifdef BTR_CUR_ADAPT new_index->search_info = btr_search_info_create(new_index->heap); +#endif /* BTR_CUR_ADAPT */ new_index->page = page_no; rw_lock_create(index_tree_rw_lock_key, &new_index->lock, @@ -2636,8 +2638,6 @@ dict_index_remove_from_cache_low( to make room in the table LRU list */ { lint size; - ulint retries = 0; - btr_search_t* info; ut_ad(table && index); ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); @@ -2652,9 +2652,11 @@ dict_index_remove_from_cache_low( row_log_free(index->online_log); } +#ifdef BTR_CUR_HASH_ADAPT /* We always create search info whether or not adaptive hash index is enabled or not. */ - info = btr_search_get_info(index); + btr_search_t* info = btr_search_get_info(index); + ulint retries = 0; ut_ad(info); /* We are not allowed to free the in-memory index struct @@ -2688,10 +2690,9 @@ dict_index_remove_from_cache_low( /* To avoid a hang here we commit suicide if the ref_count doesn't drop to zero in 600 seconds. */ - if (retries >= 60000) { - ut_error; - } + ut_a(retries < 60000); } while (srv_shutdown_state == SRV_SHUTDOWN_NONE || !lru_evict); +#endif /* BTR_CUR_HASH_ADAPT */ rw_lock_free(&index->lock); diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 6886c5164f7..6128fe54ecc 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -3060,7 +3060,9 @@ fseg_free_page_low( fil_space_t* space, page_no_t offset, const page_size_t& page_size, +#ifdef BTR_CUR_HASH_ADAPT bool ahi, +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) { xdes_t* descr; @@ -3076,7 +3078,7 @@ fseg_free_page_low( == FSEG_MAGIC_N_VALUE); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); ut_d(fsp_space_modify_check(space, mtr)); - +#ifdef BTR_CUR_HASH_ADAPT /* Drop search system page hash index if the page is found in the pool and is hashed */ @@ -3084,6 +3086,7 @@ fseg_free_page_low( btr_search_drop_page_hash_when_freed( page_id_t(space->id, offset), page_size); } +#endif /* BTR_CUR_HASH_ADAPT */ descr = xdes_get_descriptor(space, offset, page_size, mtr); @@ -3168,16 +3171,22 @@ fseg_free_page_low( } } +#ifndef BTR_CUR_HASH_ADAPT +# define fseg_free_page_low(inode, space, offset, page_size, ahi, mtr) \ + fseg_free_page_low(inode, space, offset, page_size, mtr) +#endif /* !BTR_CUR_HASH_ADAPT */ + /**********************************************************************//** Frees a single page of a segment. */ void -fseg_free_page( -/*===========*/ +fseg_free_page_func( fseg_header_t* seg_header, /*!< in: segment header */ ulint space_id,/*!< in: space id */ ulint page, /*!< in: page offset */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { DBUG_ENTER("fseg_free_page"); @@ -3253,7 +3262,9 @@ fseg_free_extent( fil_space_t* space, const page_size_t& page_size, ulint page, +#ifdef BTR_CUR_HASH_ADAPT bool ahi, +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) { ulint first_page_in_extent; @@ -3274,6 +3285,7 @@ fseg_free_extent( first_page_in_extent = page - (page % FSP_EXTENT_SIZE); +#ifdef BTR_CUR_HASH_ADAPT if (ahi) { for (i = 0; i < FSP_EXTENT_SIZE; i++) { if (!xdes_mtr_get_bit(descr, XDES_FREE_BIT, i, mtr)) { @@ -3289,6 +3301,7 @@ fseg_free_extent( } } } +#endif /* BTR_CUR_HASH_ADAPT */ if (xdes_is_full(descr, mtr)) { flst_remove(seg_inode + FSEG_FULL, @@ -3321,6 +3334,11 @@ fseg_free_extent( #endif /* UNIV_DEBUG */ } +#ifndef BTR_CUR_HASH_ADAPT +# define fseg_free_extent(inode, space, page_size, page, ahi, mtr) \ + fseg_free_extent(inode, space, page_size, page, mtr) +#endif /* !BTR_CUR_HASH_ADAPT */ + /**********************************************************************//** Frees part of a segment. This function can be used to free a segment by repeatedly calling this function in different mini-transactions. Doing @@ -3328,14 +3346,15 @@ the freeing in a single mini-transaction might result in too big a mini-transaction. @return TRUE if freeing completed */ ibool -fseg_free_step( -/*===========*/ +fseg_free_step_func( fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header resides on the first page of the frag list of the segment, this pointer becomes obsolete after the last freeing step */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint n; @@ -3414,12 +3433,13 @@ Frees part of a segment. Differs from fseg_free_step because this function leaves the header page unfreed. @return TRUE if freeing completed, except the header page */ ibool -fseg_free_step_not_header( -/*======================*/ +fseg_free_step_not_header_func( fseg_header_t* header, /*!< in: segment header which must reside on the first fragment page of the segment */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint n; diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 0bc96199486..122d99dee8f 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1553,6 +1553,7 @@ rtr_copy_buf( /* Skip buf_block_t::lock */ matches->block.lock_hash_val = block->lock_hash_val; matches->block.modify_clock = block->modify_clock; +#ifdef BTR_CUR_HASH_ADAPT matches->block.n_hash_helps = block->n_hash_helps; matches->block.n_fields = block->n_fields; matches->block.left_side = block->left_side; @@ -1562,7 +1563,7 @@ rtr_copy_buf( matches->block.curr_n_fields = block->curr_n_fields; matches->block.curr_left_side = block->curr_left_side; matches->block.index = block->index; - +#endif /* BTR_CUR_HASH_ADAPT */ ut_d(matches->block.debug_latch = block->debug_latch); } diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc index cf92f22ac15..1f90738c75f 100644 --- a/storage/innobase/ha/ha0ha.cc +++ b/storage/innobase/ha/ha0ha.cc @@ -146,7 +146,9 @@ ha_clear( hash_table_t* table) /*!< in, own: hash table */ { ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); +#ifdef BTR_CUR_HASH_ADAPT ut_ad(!table->adaptive || btr_search_own_all(RW_LOCK_X)); +#endif /* BTR_CUR_HASH_ADAPT */ for (ulint i = 0; i < table->n_sync_obj; i++) { mem_heap_free(table->heaps[i]); @@ -189,6 +191,7 @@ ha_clear( } } +#ifdef BTR_CUR_HASH_ADAPT /*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node @@ -536,3 +539,4 @@ builds, see http://bugs.mysql.com/36941 */ (ulong) n_bufs); } } +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/ha/hash0hash.cc b/storage/innobase/ha/hash0hash.cc index 7c5798ae254..ef1339ff47b 100644 --- a/storage/innobase/ha/hash0hash.cc +++ b/storage/innobase/ha/hash0hash.cc @@ -273,9 +273,11 @@ hash_create( table->type = HASH_TABLE_SYNC_NONE; table->array = array; table->n_cells = prime; -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG table->adaptive = FALSE; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ table->n_sync_obj = 0; table->sync_obj.mutexes = NULL; table->heaps = NULL; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f4ddcf3dbb4..b9caea017ab 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1839,11 +1839,13 @@ innobase_srv_conc_exit_innodb( #endif /* WITH_WSREP */ trx_t* trx = prebuilt->trx; -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ /* This is to avoid making an unnecessary function call. */ if (trx->declared_to_be_inside_innodb @@ -1861,11 +1863,13 @@ innobase_srv_conc_force_exit_innodb( /*================================*/ trx_t* trx) /*!< in: transaction handle */ { -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ /* This is to avoid making an unnecessary function call. */ if (trx->declared_to_be_inside_innodb) { @@ -1943,12 +1947,13 @@ const char* thd_innodb_tmpdir( THD* thd) { - -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG trx_t* trx = thd_to_trx(thd); btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ const char* tmp_dir = THDVAR(thd, tmpdir); @@ -1999,7 +2004,7 @@ innobase_release_temporary_latches( if (!srv_was_started) { } else if (trx_t* trx = thd_to_trx(thd)) { - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); } return(0); @@ -3324,7 +3329,6 @@ innobase_query_caching_of_table_permitted( to the table */ ulonglong *unused) /*!< unused for this engine */ { - bool is_autocommit; char norm_name[1000]; trx_t* trx = check_trx_exists(thd); @@ -3334,29 +3338,14 @@ innobase_query_caching_of_table_permitted( /* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every plain SELECT if AUTOCOMMIT is not on. */ - return(static_cast<my_bool>(false)); - } - - if (trx->has_search_latch) { - sql_print_error("The calling thread is holding the adaptive" - " search, latch though calling" - " innobase_query_caching_of_table_permitted."); - trx_print(stderr, trx, 1024); + return(false); } - trx_search_latch_release_if_reserved(trx); - + trx_assert_no_search_latch(trx); innobase_srv_conc_force_exit_innodb(trx); - if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - - is_autocommit = true; - } else { - is_autocommit = false; - - } - - if (is_autocommit && trx->n_mysql_tables_in_use == 0) { + if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) + && trx->n_mysql_tables_in_use == 0) { /* We are going to retrieve the query result from the query cache. This cannot be a store operation to the query cache because then MySQL would have locks on tables already. @@ -3375,7 +3364,7 @@ innobase_query_caching_of_table_permitted( then trx2 would have already invalidated the cache. Thus we can trust the result in the cache is ok for this query. */ - return((my_bool)TRUE); + return(true); } /* Normalize the table name to InnoDB format */ @@ -3383,12 +3372,7 @@ innobase_query_caching_of_table_permitted( innobase_register_trx(innodb_hton_ptr, thd, trx); - if (row_search_check_if_query_cache_permitted(trx, norm_name)) { - - return(static_cast<my_bool>(true)); - } - - return(static_cast<my_bool>(false)); + return(row_search_check_if_query_cache_permitted(trx, norm_name)); } /*****************************************************************//** @@ -3640,7 +3624,7 @@ ha_innobase::init_table_handle_for_HANDLER(void) /* Initialize the m_prebuilt struct much like it would be inited in external_lock */ - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); innobase_srv_conc_force_exit_innodb(m_prebuilt->trx); @@ -4772,7 +4756,7 @@ innobase_commit_ordered( search system latch, or we will disobey the latching order. But we already released it in innobase_xa_prepare() (if not before), so just have an assert here.*/ - ut_ad(!trx->has_search_latch); + trx_assert_no_search_latch(trx); if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) { /* We cannot throw error here; instead we will catch this error @@ -4991,7 +4975,7 @@ innobase_rollback_trx( reserve the trx_sys->mutex, we have to release the search system latch first to obey the latching order. */ - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); innobase_srv_conc_force_exit_innodb(trx); @@ -13110,7 +13094,7 @@ create_table_info_t::initialize() /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); + trx_assert_no_search_latch(parent_trx); DBUG_RETURN(0); } @@ -13958,16 +13942,11 @@ innobase_drop_database( THD* thd = current_thd; - /* In the Windows plugin, thd = current_thd is always NULL */ - if (thd != NULL) { - trx_t* parent_trx = check_trx_exists(thd); - - /* In case MySQL calls this in the middle of a SELECT - query, release possible adaptive hash latch to avoid - deadlocks of threads */ + /* In case MySQL calls this in the middle of a SELECT + query, release possible adaptive hash latch to avoid + deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); - } + trx_assert_no_search_latch(check_trx_exists(thd)); ulint len = 0; char* ptr = strend(path) - 2; @@ -14817,7 +14796,7 @@ ha_innobase::info_low( m_prebuilt->trx->op_info = (char*)"returning various info to MariaDB"; - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); ib_table = m_prebuilt->table; DBUG_ASSERT(ib_table->n_ref_count > 0); @@ -15602,7 +15581,8 @@ ha_innobase::check( /* Restore the original isolation level */ m_prebuilt->trx->isolation_level = old_isolation_level; -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG /* We validate the whole adaptive hash index for all tables at every CHECK TABLE only when QUICK flag is not present. */ @@ -15612,7 +15592,8 @@ ha_innobase::check( "InnoDB: The adaptive hash index is corrupted."); is_ok = false; } -#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ +# endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ m_prebuilt->trx->op_info = ""; DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); @@ -15649,7 +15630,7 @@ ha_innobase::update_table_comment( /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); #define SSTR( x ) reinterpret_cast< std::ostringstream & >( \ ( std::ostringstream() << std::dec << x ) ).str() @@ -15711,7 +15692,7 @@ ha_innobase::get_foreign_key_create_info(void) release possible adaptive hash latch to avoid deadlocks of threads */ - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); @@ -16710,7 +16691,7 @@ innodb_show_status( trx_t* trx = check_trx_exists(thd); - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); innobase_srv_conc_force_exit_innodb(trx); @@ -18002,7 +17983,7 @@ innobase_xa_prepare( reserve the trx_sys->mutex, we have to release the search system latch first to obey the latching order. */ - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); innobase_srv_conc_force_exit_innodb(trx); @@ -18745,6 +18726,7 @@ innodb_internal_table_validate( return(ret); } +#ifdef BTR_CUR_HASH_ADAPT /****************************************************************//** Update the system variable innodb_adaptive_hash_index using the "saved" value. This function is registered as a callback with MySQL. */ @@ -18766,6 +18748,7 @@ innodb_adaptive_hash_index_update( btr_search_disable(true); } } +#endif /* BTR_CUR_HASH_ADAPT */ /****************************************************************//** Update the system variable innodb_cmp_per_index using the "saved" @@ -20994,6 +20977,7 @@ static MYSQL_SYSVAR_BOOL(stats_traditional, srv_stats_sample_traditional, "Enable traditional statistic calculation based on number of configured pages (default true)", NULL, NULL, TRUE); +#ifdef BTR_CUR_HASH_ADAPT static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled, PLUGIN_VAR_OPCMDARG, "Enable InnoDB adaptive hash index (enabled by default). " @@ -21005,8 +20989,9 @@ Each partition is protected by its own latch and so we have parts number of latches protecting complete search system. */ static MYSQL_SYSVAR_ULONG(adaptive_hash_index_parts, btr_ahi_parts, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, - "Number of InnoDB Adapative Hash Index Partitions. (default = 8). ", + "Number of InnoDB Adaptive Hash Index Partitions (default 8)", NULL, NULL, 8, 1, 512, 0); +#endif /* BTR_CUR_HASH_ADAPT */ static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG, @@ -21962,8 +21947,10 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(stats_auto_recalc), MYSQL_SYSVAR(stats_modified_counter), MYSQL_SYSVAR(stats_traditional), +#ifdef BTR_CUR_HASH_ADAPT MYSQL_SYSVAR(adaptive_hash_index), MYSQL_SYSVAR(adaptive_hash_index_parts), +#endif /* BTR_CUR_HASH_ADAPT */ MYSQL_SYSVAR(stats_method), MYSQL_SYSVAR(replication_delay), MYSQL_SYSVAR(status_file), diff --git a/storage/innobase/handler/ha_innopart.cc b/storage/innobase/handler/ha_innopart.cc index 6cdbd226b24..806a4079326 100644 --- a/storage/innobase/handler/ha_innopart.cc +++ b/storage/innobase/handler/ha_innopart.cc @@ -3070,7 +3070,7 @@ ha_innopart::records_in_range( /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads. */ - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); active_index = keynr; @@ -3209,7 +3209,7 @@ ha_innopart::estimate_rows_upper_bound() /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads. */ - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); for (uint i = m_part_info->get_first_used_partition(); i < m_tot_parts; @@ -3327,7 +3327,7 @@ ha_innopart::info_low( m_prebuilt->trx->op_info = (char*)"returning various info to MySQL"; - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); ut_ad(m_part_share->get_table_part(0)->n_ref_count > 0); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index d766dd6ada6..726f641ef5a 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -589,7 +589,7 @@ ha_innobase::check_if_supported_inplace_alter( } update_thd(); - trx_search_latch_release_if_reserved(m_prebuilt->trx); + trx_assert_no_search_latch(m_prebuilt->trx); /* Change on engine specific table options require rebuild of the table */ @@ -8802,11 +8802,12 @@ foreign_fail: DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1); trx_commit_for_mysql(m_prebuilt->trx); - +#ifdef BTR_CUR_HASH_ADAPT if (btr_search_enabled) { btr_search_disable(false); btr_search_enable(); } +#endif /* BTR_CUR_HASH_ADAPT */ char tb_name[FN_REFLEN]; ut_strcpy(tb_name, m_prebuilt->table->name.m_name); diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index a400ee54758..bc35f772af1 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -129,8 +129,10 @@ struct buf_page_info_t{ unsigned io_fix:2; /*!< type of pending I/O operation */ unsigned fix_count:19; /*!< Count of how manyfold this block is bufferfixed */ +#ifdef BTR_CUR_HASH_ADAPT unsigned hashed:1; /*!< Whether hash index has been built on this page */ +#endif /* BTR_CUR_HASH_ADAPT */ unsigned is_old:1; /*!< TRUE if the block is in the old blocks in buf_pool->LRU_old */ unsigned freed_page_clock:31; /*!< the value of @@ -339,6 +341,12 @@ field_store_ulint( return(ret); } +#ifdef BTR_CUR_HASH_ADAPT +# define I_S_AHI 1 /* Include the IS_HASHED column */ +#else +# define I_S_AHI 0 /* Omit the IS_HASHED column */ +#endif + /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */ static ST_FIELD_INFO innodb_trx_fields_info[] = { @@ -522,6 +530,7 @@ static ST_FIELD_INFO innodb_trx_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#ifdef BTR_CUR_HASH_ADAPT #define IDX_TRX_ADAPTIVE_HASH_LATCHED 20 {STRUCT_FLD(field_name, "trx_adaptive_hash_latched"), STRUCT_FLD(field_length, 1), @@ -530,17 +539,9 @@ static ST_FIELD_INFO innodb_trx_fields_info[] = STRUCT_FLD(field_flags, 0), STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#endif /* BTR_CUR_HASH_ADAPT */ -#define IDX_TRX_ADAPTIVE_HASH_TIMEOUT 21 - {STRUCT_FLD(field_name, "trx_adaptive_hash_timeout"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TRX_READ_ONLY 22 +#define IDX_TRX_READ_ONLY 20 + I_S_AHI {STRUCT_FLD(field_name, "trx_is_read_only"), STRUCT_FLD(field_length, 1), STRUCT_FLD(field_type, MYSQL_TYPE_LONG), @@ -549,7 +550,7 @@ static ST_FIELD_INFO innodb_trx_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_TRX_AUTOCOMMIT_NON_LOCKING 23 +#define IDX_TRX_AUTOCOMMIT_NON_LOCKING 21 + I_S_AHI {STRUCT_FLD(field_name, "trx_autocommit_non_locking"), STRUCT_FLD(field_length, 1), STRUCT_FLD(field_type, MYSQL_TYPE_LONG), @@ -696,9 +697,11 @@ fill_innodb_trx_from_cache( OK(field_store_string(fields[IDX_TRX_LAST_FOREIGN_KEY_ERROR], row->trx_foreign_key_error)); +#ifdef BTR_CUR_HASH_ADAPT /* trx_adaptive_hash_latched */ OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store( row->trx_has_search_latch, true)); +#endif /* BTR_CUR_HASH_ADAPT */ /* trx_is_read_only*/ OK(fields[IDX_TRX_READ_ONLY]->store( @@ -4710,6 +4713,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#ifdef BTR_CUR_HASH_ADAPT #define IDX_BUFFER_PAGE_HASHED 7 {STRUCT_FLD(field_name, "IS_HASHED"), STRUCT_FLD(field_length, 3), @@ -4718,8 +4722,9 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#endif /* BTR_CUR_HASH_ADAPT */ -#define IDX_BUFFER_PAGE_NEWEST_MOD 8 +#define IDX_BUFFER_PAGE_NEWEST_MOD 7 + I_S_AHI {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4728,7 +4733,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_OLDEST_MOD 9 +#define IDX_BUFFER_PAGE_OLDEST_MOD 8 + I_S_AHI {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4737,7 +4742,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_ACCESS_TIME 10 +#define IDX_BUFFER_PAGE_ACCESS_TIME 9 + I_S_AHI {STRUCT_FLD(field_name, "ACCESS_TIME"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4746,7 +4751,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_TABLE_NAME 11 +#define IDX_BUFFER_PAGE_TABLE_NAME 10 + I_S_AHI {STRUCT_FLD(field_name, "TABLE_NAME"), STRUCT_FLD(field_length, 1024), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -4755,7 +4760,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_INDEX_NAME 12 +#define IDX_BUFFER_PAGE_INDEX_NAME 11 + I_S_AHI {STRUCT_FLD(field_name, "INDEX_NAME"), STRUCT_FLD(field_length, 1024), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -4764,7 +4769,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_NUM_RECS 13 +#define IDX_BUFFER_PAGE_NUM_RECS 12 + I_S_AHI {STRUCT_FLD(field_name, "NUMBER_RECORDS"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4773,7 +4778,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_DATA_SIZE 14 +#define IDX_BUFFER_PAGE_DATA_SIZE 13 + I_S_AHI {STRUCT_FLD(field_name, "DATA_SIZE"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4782,7 +4787,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_ZIP_SIZE 15 +#define IDX_BUFFER_PAGE_ZIP_SIZE 14 + I_S_AHI {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4791,7 +4796,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_STATE 16 +#define IDX_BUFFER_PAGE_STATE 15 + I_S_AHI {STRUCT_FLD(field_name, "PAGE_STATE"), STRUCT_FLD(field_length, 64), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -4800,7 +4805,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_IO_FIX 17 +#define IDX_BUFFER_PAGE_IO_FIX 16 + I_S_AHI {STRUCT_FLD(field_name, "IO_FIX"), STRUCT_FLD(field_length, 64), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -4809,7 +4814,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_IS_OLD 18 +#define IDX_BUFFER_PAGE_IS_OLD 17 + I_S_AHI {STRUCT_FLD(field_name, "IS_OLD"), STRUCT_FLD(field_length, 3), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -4818,7 +4823,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUFFER_PAGE_FREE_CLOCK 19 +#define IDX_BUFFER_PAGE_FREE_CLOCK 18 + I_S_AHI {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -4888,13 +4893,11 @@ i_s_innodb_buffer_page_fill( OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( page_info->fix_count)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUFFER_PAGE_HASHED], "NO")); - } +#ifdef BTR_CUR_HASH_ADAPT + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); +#endif /* BTR_CUR_HASH_ADAPT */ OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( page_info->newest_mod, true)); @@ -5144,7 +5147,9 @@ i_s_innodb_buffer_page_get_info( block = reinterpret_cast<const buf_block_t*>(bpage); frame = block->frame; +#ifdef BTR_CUR_HASH_ADAPT page_info->hashed = (block->index != NULL); +#endif /* BTR_CUR_HASH_ADAPT */ } else { ut_ad(page_info->zip_ssize); frame = bpage->zip.data; @@ -5425,6 +5430,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#ifdef BTR_CUR_HASH_ADAPT #define IDX_BUF_LRU_PAGE_HASHED 7 {STRUCT_FLD(field_name, "IS_HASHED"), STRUCT_FLD(field_length, 3), @@ -5433,8 +5439,9 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, +#endif /* BTR_CUR_HASH_ADAPT */ -#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8 +#define IDX_BUF_LRU_PAGE_NEWEST_MOD 7 + I_S_AHI {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5443,7 +5450,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9 +#define IDX_BUF_LRU_PAGE_OLDEST_MOD 8 + I_S_AHI {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5452,7 +5459,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10 +#define IDX_BUF_LRU_PAGE_ACCESS_TIME 9 + I_S_AHI {STRUCT_FLD(field_name, "ACCESS_TIME"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5461,7 +5468,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_TABLE_NAME 11 +#define IDX_BUF_LRU_PAGE_TABLE_NAME 10 + I_S_AHI {STRUCT_FLD(field_name, "TABLE_NAME"), STRUCT_FLD(field_length, 1024), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -5470,7 +5477,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_INDEX_NAME 12 +#define IDX_BUF_LRU_PAGE_INDEX_NAME 11 + I_S_AHI {STRUCT_FLD(field_name, "INDEX_NAME"), STRUCT_FLD(field_length, 1024), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -5479,7 +5486,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_NUM_RECS 13 +#define IDX_BUF_LRU_PAGE_NUM_RECS 12 + I_S_AHI {STRUCT_FLD(field_name, "NUMBER_RECORDS"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5488,7 +5495,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_DATA_SIZE 14 +#define IDX_BUF_LRU_PAGE_DATA_SIZE 13 + I_S_AHI {STRUCT_FLD(field_name, "DATA_SIZE"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5497,7 +5504,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15 +#define IDX_BUF_LRU_PAGE_ZIP_SIZE 14 + I_S_AHI {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5506,7 +5513,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_STATE 16 +#define IDX_BUF_LRU_PAGE_STATE 15 + I_S_AHI {STRUCT_FLD(field_name, "COMPRESSED"), STRUCT_FLD(field_length, 3), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -5515,7 +5522,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_IO_FIX 17 +#define IDX_BUF_LRU_PAGE_IO_FIX 16 + I_S_AHI {STRUCT_FLD(field_name, "IO_FIX"), STRUCT_FLD(field_length, 64), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -5524,7 +5531,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_IS_OLD 18 +#define IDX_BUF_LRU_PAGE_IS_OLD 17 + I_S_AHI {STRUCT_FLD(field_name, "IS_OLD"), STRUCT_FLD(field_length, 3), STRUCT_FLD(field_type, MYSQL_TYPE_STRING), @@ -5533,7 +5540,7 @@ static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = STRUCT_FLD(old_name, ""), STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, -#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19 +#define IDX_BUF_LRU_PAGE_FREE_CLOCK 18 + I_S_AHI {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), @@ -5606,13 +5613,11 @@ i_s_innodb_buf_page_lru_fill( OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( page_info->fix_count, true)); - if (page_info->hashed) { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); - } else { - OK(field_store_string( - fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); - } +#ifdef BTR_CUR_HASH_ADAPT + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], + page_info->hashed ? "YES" : "NO")); +#endif /* BTR_CUR_HASH_ADAPT */ OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( page_info->newest_mod, true)); diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index e6c36b425e6..cf3ce487607 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -571,7 +571,9 @@ ibuf_init_at_db_start(void) ibuf->index->n_uniq = REC_MAX_N_FIELDS; rw_lock_create(index_tree_rw_lock_key, &ibuf->index->lock, SYNC_IBUF_INDEX_TREE); +#ifdef BTR_CUR_ADAPT ibuf->index->search_info = btr_search_info_create(ibuf->index->heap); +#endif /* BTR_CUR_ADAPT */ ibuf->index->page = FSP_IBUF_TREE_ROOT_PAGE_NO; ut_d(ibuf->index->cached = TRUE); return (error); @@ -3954,7 +3956,9 @@ ibuf_insert_to_index_page( ut_ad(!dict_index_is_online_ddl(index));// this is an ibuf_dummy index ut_ad(ibuf_inside(mtr)); ut_ad(dtuple_check_typed(entry)); +#ifdef BTR_CUR_HASH_ADAPT ut_ad(!block->index); +#endif /* BTR_CUR_HASH_ADAPT */ ut_ad(mtr->is_named_space(block->page.id.space())); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index a1e37ec46d0..275c4dc51b0 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -64,9 +64,6 @@ struct btr_latch_leaves_t { #include "row0types.h" #include "ha0ha.h" -#define BTR_CUR_ADAPT -#define BTR_CUR_HASH_ADAPT - #ifdef UNIV_DEBUG /*********************************************************//** Returns the page cursor component of a tree cursor. @@ -980,17 +977,19 @@ inherited external field. */ /** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */ extern ulint btr_cur_n_non_sea; -/** Number of successful adaptive hash index lookups in -btr_cur_search_to_nth_level(). */ -extern ulint btr_cur_n_sea; /** Old value of btr_cur_n_non_sea. Copied by srv_refresh_innodb_monitor_stats(). Referenced by srv_printf_innodb_monitor(). */ extern ulint btr_cur_n_non_sea_old; +#ifdef BTR_CUR_HASH_ADAPT +/** Number of successful adaptive hash index lookups in +btr_cur_search_to_nth_level(). */ +extern ulint btr_cur_n_sea; /** Old value of btr_cur_n_sea. Copied by srv_refresh_innodb_monitor_stats(). Referenced by srv_printf_innodb_monitor(). */ extern ulint btr_cur_n_sea_old; +#endif /* BTR_CUR_HASH_ADAPT */ #ifdef UNIV_DEBUG /* Flag to limit optimistic insert records */ diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 12659037904..8ff411cffd0 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -32,6 +32,7 @@ Created 2/17/1996 Heikki Tuuri #include "dict0dict.h" #include "btr0types.h" #include "mtr0mtr.h" +#ifdef BTR_CUR_HASH_ADAPT #include "ha0ha.h" /** Creates and initializes the adaptive search system at a database start. @@ -57,22 +58,6 @@ btr_search_disable( void btr_search_enable(); -/********************************************************************//** -Returns search info for an index. -@return search info; search mutex reserved */ -UNIV_INLINE -btr_search_t* -btr_search_get_info( -/*================*/ - dict_index_t* index) /*!< in: index */ - MY_ATTRIBUTE((nonnull)); - -/** Creates and initializes a search info struct. -@param[in] heap heap where created. -@return own: search info struct */ -btr_search_t* -btr_search_info_create(mem_heap_t* heap); - /** Returns the value of ref_count. The value is protected by latch. @param[in] info search info @param[in] index index identifier @@ -257,16 +242,40 @@ A table is selected from an array of tables using pair of index-id, space-id. UNIV_INLINE hash_table_t* btr_get_search_table(const dict_index_t* index); +#else /* BTR_CUR_HASH_ADAPT */ +# define btr_search_sys_create(size) +# define btr_search_drop_page_hash_index(block) +# define btr_search_s_lock(index) +# define btr_search_s_unlock(index) +# define btr_search_x_lock(index) +# define btr_search_x_unlock(index) +# define btr_search_info_update(index, cursor) +# define btr_search_move_or_delete_hash_entries(new_block, block, index) +# define btr_search_update_hash_on_insert(cursor) +# define btr_search_update_hash_on_delete(cursor) +# define btr_search_sys_resize(hash_size) +#endif /* BTR_CUR_HASH_ADAPT */ + +#ifdef BTR_CUR_ADAPT +/** Create and initialize search info. +@param[in,out] heap heap where created +@return own: search info struct */ +UNIV_INLINE +btr_search_t* +btr_search_info_create(mem_heap_t* heap) + MY_ATTRIBUTE((nonnull, warn_unused_result)); + +/** @return the search info of an index */ +UNIV_INLINE +btr_search_t* +btr_search_get_info(dict_index_t* index) +{ + return(index->search_info); +} +#endif /* BTR_CUR_ADAPT */ /** The search info struct in an index */ struct btr_search_t{ - ulint ref_count; /*!< Number of blocks in this index tree - that have search index built - i.e. block->index points to this index. - Protected by search latch except - when during initialization in - btr_search_info_create(). */ - /* @{ The following fields are not protected by any latch. Unfortunately, this means that they must be aligned to the machine word, i.e., they cannot be turned into bit-fields. */ @@ -274,6 +283,7 @@ struct btr_search_t{ fetched, or NULL */ ulint withdraw_clock; /*!< the withdraw clock value of the buffer pool when root_guess was stored */ +#ifdef BTR_CUR_HASH_ADAPT ulint hash_analysis; /*!< when this exceeds BTR_SEARCH_HASH_ANALYSIS, the hash analysis starts; this is reset if no @@ -289,6 +299,13 @@ struct btr_search_t{ using the hash index; the range is 0 .. BTR_SEARCH_BUILD_LIMIT + 5 */ /* @} */ + ulint ref_count; /*!< Number of blocks in this index tree + that have search index built + i.e. block->index points to this index. + Protected by search latch except + when during initialization in + btr_search_info_create(). */ + /*---------------------- @{ */ ulint n_fields; /*!< recommended prefix length for hash search: number of full fields */ @@ -308,6 +325,7 @@ struct btr_search_t{ far */ ulint n_searches; /*!< number of searches */ #endif /* UNIV_SEARCH_PERF_STAT */ +#endif /* BTR_CUR_HASH_ADAPT */ #ifdef UNIV_DEBUG ulint magic_n; /*!< magic number @see BTR_SEARCH_MAGIC_N */ /** value of btr_search_t::magic_n, used in assertions */ @@ -315,6 +333,7 @@ struct btr_search_t{ #endif /* UNIV_DEBUG */ }; +#ifdef BTR_CUR_HASH_ADAPT /** The hash index system */ struct btr_search_sys_t{ hash_table_t** hash_tables; /*!< the adaptive hash tables, @@ -352,6 +371,7 @@ the hash index */ over calls from MySQL. If we notice someone waiting for the latch, we again set this much timeout. This is to reduce contention. */ #define BTR_SEA_TIMEOUT 10000 +#endif /* BTR_CUR_HASH_ADAPT */ #ifndef UNIV_NONINL #include "btr0sea.ic" diff --git a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic index 5f7c39ba500..b5a7536a2b4 100644 --- a/storage/innobase/include/btr0sea.ic +++ b/storage/innobase/include/btr0sea.ic @@ -27,6 +27,24 @@ Created 2/17/1996 Heikki Tuuri #include "btr0cur.h" #include "buf0buf.h" +/** Create and initialize search info. +@param[in,out] heap heap where created +@return own: search info struct */ +UNIV_INLINE +btr_search_t* +btr_search_info_create(mem_heap_t* heap) +{ + btr_search_t* info = static_cast<btr_search_t*>( + mem_heap_zalloc(heap, sizeof(btr_search_t))); + ut_d(info->magic_n = BTR_SEARCH_MAGIC_N); +#ifdef BTR_CUR_HASH_ADAPT + info->n_fields = 1; + info->left_side = TRUE; +#endif /* BTR_CUR_HASH_ADAPT */ + return(info); +} + +#ifdef BTR_CUR_HASH_ADAPT /*********************************************************************//** Updates the search info. */ void @@ -35,18 +53,6 @@ btr_search_info_update_slow( btr_search_t* info, /*!< in/out: search info */ btr_cur_t* cursor);/*!< in: cursor which was just positioned */ -/********************************************************************//** -Returns search info for an index. -@return search info; search mutex reserved */ -UNIV_INLINE -btr_search_t* -btr_search_get_info( -/*================*/ - dict_index_t* index) /*!< in: index */ -{ - return(index->search_info); -} - /*********************************************************************//** Updates the search info. */ UNIV_INLINE @@ -221,3 +227,4 @@ btr_get_search_table(const dict_index_t* index) return(btr_search_sys->hash_tables[ifold % btr_ahi_parts]); } +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h index 19c21982011..77d1b286fbb 100644 --- a/storage/innobase/include/btr0types.h +++ b/storage/innobase/include/btr0types.h @@ -40,12 +40,14 @@ struct btr_cur_t; /** B-tree search information for the adaptive hash index */ struct btr_search_t; +#ifdef BTR_CUR_HASH_ADAPT /** Is search system enabled. Search system is protected by array of latches. */ extern char btr_search_enabled; /** Number of adaptive hash index partition. */ extern ulong btr_ahi_parts; +#endif /* BTR_CUR_HASH_ADAPT */ /** The size of a reference to data stored on a different page. The reference is stored at the end of the prefix of the field diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index ce2a8e385fc..0279887b226 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -395,11 +395,11 @@ extern "C" os_thread_ret_t DECLARE_THREAD(buf_resize_thread)(void*); -/********************************************************************//** -Clears the adaptive hash index on all pages in the buffer pool. */ +#ifdef BTR_CUR_HASH_ADAPT +/** Clear the adaptive hash index on all pages in the buffer pool. */ void -buf_pool_clear_hash_index(void); -/*===========================*/ +buf_pool_clear_hash_index(); +#endif /* BTR_CUR_HASH_ADAPT */ /*********************************************************************//** Gets the current size of buffer buf_pool in bytes. @@ -1210,12 +1210,14 @@ if applicable. */ #define buf_block_get_page_zip(block) \ ((block)->page.zip.data ? &(block)->page.zip : NULL) +#ifdef BTR_CUR_HASH_ADAPT /** Get a buffer block from an adaptive hash index pointer. This function does not return if the block is not identified. @param[in] ptr pointer to within a page frame @return pointer to block, never NULL */ buf_block_t* buf_block_from_ahi(const byte* ptr); +#endif /* BTR_CUR_HASH_ADAPT */ /********************************************************************//** Find out if a pointer belongs to a buf_block_t. It can be a pointer to @@ -1799,6 +1801,7 @@ struct buf_block_t{ bufferfixed, or (2) the thread has an x-latch on the block */ /* @} */ +#ifdef BTR_CUR_HASH_ADAPT /** @name Hash search fields (unprotected) NOTE that these fields are NOT protected by any semaphore! */ /* @{ */ @@ -1830,11 +1833,11 @@ struct buf_block_t{ /* @{ */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ulint n_pointers; /*!< used in debugging: the number of pointers in the adaptive hash index pointing to this frame */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ unsigned curr_n_fields:10;/*!< prefix length for hash indexing: number of full fields */ unsigned curr_n_bytes:15;/*!< number of bytes in hash @@ -1849,6 +1852,7 @@ struct buf_block_t{ complete, though: there may have been hash collisions, record deletions, etc. */ +#endif /* BTR_CUR_HASH_ADAPT */ bool skip_flush_check; /*!< Skip check in buf_dblwr_check_block during bulk load, protected by lock.*/ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 4a084c347d6..a458054c225 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -878,6 +878,7 @@ struct dict_index_t{ representation we add more columns */ unsigned nulls_equal:1; /*!< if true, SQL NULL == SQL NULL */ +#ifdef BTR_CUR_HASH_ADAPT #ifdef MYSQL_INDEX_DISABLE_AHI unsigned disable_ahi:1; /*!< whether to disable the @@ -885,6 +886,7 @@ struct dict_index_t{ Maybe this could be disabled for temporary tables? */ #endif +#endif /* BTR_CUR_HASH_ADAPT */ unsigned n_uniq:10;/*!< number of fields from the beginning which are enough to determine an index entry uniquely */ @@ -923,8 +925,10 @@ struct dict_index_t{ column in ALTER */ UT_LIST_NODE_T(dict_index_t) indexes;/*!< list of indexes of the table */ +#ifdef BTR_CUR_ADAPT btr_search_t* search_info; /*!< info used in optimistic searches */ +#endif /* BTR_CUR_ADAPT */ row_log_t* online_log; /*!< the log of modifications during online index creation; diff --git a/storage/innobase/include/dict0mem.ic b/storage/innobase/include/dict0mem.ic index 933f233aae6..e7d68dd4b9d 100644 --- a/storage/innobase/include/dict0mem.ic +++ b/storage/innobase/include/dict0mem.ic @@ -68,11 +68,10 @@ dict_mem_fill_index_struct( /* The '1 +' above prevents allocation of an empty mem block */ index->nulls_equal = false; +#ifdef BTR_CUR_HASH_ADAPT #ifdef MYSQL_INDEX_DISABLE_AHI index->disable_ahi = false; #endif - -#ifdef UNIV_DEBUG - index->magic_n = DICT_INDEX_MAGIC_N; -#endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ + ut_d(index->magic_n = DICT_INDEX_MAGIC_N); } diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index fa8d5b76960..892e6d1035e 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -579,14 +579,22 @@ fsp_get_available_space_in_free_extents( /**********************************************************************//** Frees a single page of a segment. */ void -fseg_free_page( -/*===========*/ +fseg_free_page_func( fseg_header_t* seg_header, /*!< in: segment header */ ulint space_id, /*!< in: space id */ ulint page, /*!< in: page offset */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr); /*!< in/out: mini-transaction */ +#ifdef BTR_CUR_HASH_ADAPT +# define fseg_free_page(header, space_id, page, ahi, mtr) \ + fseg_free_page_func(header, space_id, page, ahi, mtr) +#else /* BTR_CUR_HASH_ADAPT */ +# define fseg_free_page(header, space_id, page, ahi, mtr) \ + fseg_free_page_func(header, space_id, page, mtr) +#endif /* BTR_CUR_HASH_ADAPT */ /**********************************************************************//** Checks if a single page of a segment is free. @return true if free */ @@ -604,29 +612,43 @@ Doing the freeing in a single mini-transaction might result in too big a mini-transaction. @return TRUE if freeing completed */ ibool -fseg_free_step( -/*===========*/ +fseg_free_step_func( fseg_header_t* header, /*!< in, own: segment header; NOTE: if the header resides on the first page of the frag list of the segment, this pointer becomes obsolete after the last freeing step */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((warn_unused_result)); +#ifdef BTR_CUR_HASH_ADAPT +# define fseg_free_step(header, ahi, mtr) fseg_free_step_func(header, ahi, mtr) +#else /* BTR_CUR_HASH_ADAPT */ +# define fseg_free_step(header, ahi, mtr) fseg_free_step_func(header, mtr) +#endif /* BTR_CUR_HASH_ADAPT */ /**********************************************************************//** Frees part of a segment. Differs from fseg_free_step because this function leaves the header page unfreed. @return TRUE if freeing completed, except the header page */ ibool -fseg_free_step_not_header( -/*======================*/ +fseg_free_step_not_header_func( fseg_header_t* header, /*!< in: segment header which must reside on the first fragment page of the segment */ +#ifdef BTR_CUR_HASH_ADAPT bool ahi, /*!< in: whether we may need to drop the adaptive hash index */ +#endif /* BTR_CUR_HASH_ADAPT */ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((warn_unused_result)); +#ifdef BTR_CUR_HASH_ADAPT +# define fseg_free_step_not_header(header, ahi, mtr) \ + fseg_free_step_not_header_func(header, ahi, mtr) +#else /* BTR_CUR_HASH_ADAPT */ +# define fseg_free_step_not_header(header, ahi, mtr) \ + fseg_free_step_not_header_func(header, mtr) +#endif /* BTR_CUR_HASH_ADAPT */ /** Checks if a page address is an extent descriptor page address. @param[in] page_id page id diff --git a/storage/innobase/include/ha0ha.h b/storage/innobase/include/ha0ha.h index 6857670a01b..7ddcaf82aa8 100644 --- a/storage/innobase/include/ha0ha.h +++ b/storage/innobase/include/ha0ha.h @@ -33,6 +33,7 @@ Created 8/18/1994 Heikki Tuuri #include "buf0types.h" #include "rem0types.h" +#ifdef BTR_CUR_HASH_ADAPT /*************************************************************//** Looks for an element in a hash table. @return pointer to the data of the first hash table node in chain @@ -79,6 +80,7 @@ updates the pointer to data if found. # define ha_search_and_update_if_found(table,fold,data,new_block,new_data) \ ha_search_and_update_if_found_func(table,fold,data,new_data) #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ /*************************************************************//** Creates a hash table with at least n array cells. The actual number @@ -115,6 +117,7 @@ ha_clear( /*=====*/ hash_table_t* table); /*!< in, own: hash table */ +#ifdef BTR_CUR_HASH_ADAPT /*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node @@ -212,6 +215,7 @@ struct ha_node_t { #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ const rec_t* data; /*!< pointer to the data */ }; +#endif /* BTR_CUR_HASH_ADAPT */ #ifdef UNIV_DEBUG /********************************************************************//** diff --git a/storage/innobase/include/ha0ha.ic b/storage/innobase/include/ha0ha.ic index 854ff9bc046..1513df209ad 100644 --- a/storage/innobase/include/ha0ha.ic +++ b/storage/innobase/include/ha0ha.ic @@ -23,18 +23,11 @@ The hash table with external chains Created 8/18/1994 Heikki Tuuri *************************************************************************/ +#ifdef BTR_CUR_HASH_ADAPT #include "ut0rnd.h" #include "mem0mem.h" #include "btr0types.h" -/***********************************************************//** -Deletes a hash node. */ -void -ha_delete_hash_node( -/*================*/ - hash_table_t* table, /*!< in: hash table */ - ha_node_t* del_node); /*!< in: node to be deleted */ - /******************************************************************//** Gets a hash node data. @return pointer to the data */ @@ -213,6 +206,14 @@ ha_search_with_data( return(NULL); } +/***********************************************************//** +Deletes a hash node. */ +void +ha_delete_hash_node( +/*================*/ + hash_table_t* table, /*!< in: hash table */ + ha_node_t* del_node); /*!< in: node to be deleted */ + /*********************************************************//** Looks for an element when we know the pointer to the data, and deletes it from the hash table, if found. @@ -240,3 +241,4 @@ ha_search_and_delete_if_found( return(FALSE); } +#endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 2922d424d37..738fa813ddd 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -536,11 +536,13 @@ struct hash_cell_t{ /* The hash table structure */ struct hash_table_t { enum hash_table_sync_t type; /*<! type of hash_table. */ -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG ibool adaptive;/* TRUE if this is the hash table of the adaptive hash index */ -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ ulint n_cells;/* number of cells in the hash table */ hash_cell_t* array; /*!< pointer to cell array */ diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index 2bb922cc829..731817e740a 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -36,8 +36,6 @@ Created 10/4/1994 Heikki Tuuri #include "gis0type.h" -#define PAGE_CUR_ADAPT - #ifdef UNIV_DEBUG /*********************************************************//** Gets pointer to the page frame where the cursor is positioned. @@ -297,6 +295,7 @@ page_cur_search_with_match( fields in lower limit record */ page_cur_t* cursor, /*!< out: page cursor */ rtr_info_t* rtr_info);/*!< in/out: rtree search stack */ +#ifdef BTR_CUR_HASH_ADAPT /** Search the right position for a page cursor. @param[in] block buffer block @param[in] index index tree @@ -322,6 +321,7 @@ page_cur_search_with_match_bytes( ulint* ilow_matched_fields, ulint* ilow_matched_bytes, page_cur_t* cursor); +#endif /* BTR_CUR_HASH_ADAPT */ /***********************************************************//** Positions a page cursor on a randomly chosen user record on a page. If there are no user records, sets the cursor on the infimum record. */ diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 5c19e735806..3697604425c 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -361,16 +361,20 @@ enum monitor_id_t { MONITOR_INDEX_REORG_SUCCESSFUL, MONITOR_INDEX_DISCARD, +#ifdef BTR_CUR_HASH_ADAPT /* Adaptive Hash Index related counters */ MONITOR_MODULE_ADAPTIVE_HASH, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH, +#endif /* BTR_CUR_HASH_ADAPT */ MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE, +#ifdef BTR_CUR_HASH_ADAPT MONITOR_ADAPTIVE_HASH_PAGE_ADDED, MONITOR_ADAPTIVE_HASH_PAGE_REMOVED, MONITOR_ADAPTIVE_HASH_ROW_ADDED, MONITOR_ADAPTIVE_HASH_ROW_REMOVED, MONITOR_ADAPTIVE_HASH_ROW_REMOVE_NOT_FOUND, MONITOR_ADAPTIVE_HASH_ROW_UPDATED, +#endif /* BTR_CUR_HASH_ADAPT */ /* Tablespace related counters */ MONITOR_MODULE_FIL_SYSTEM, diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index 68b6a44dc25..efc516fbad1 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -1070,6 +1070,7 @@ struct sync_check_functor_t { virtual bool result() const = 0; }; +#ifdef BTR_CUR_HASH_ADAPT /** Functor to check whether the calling thread owns the btr search mutex. */ struct btrsea_sync_check : public sync_check_functor_t { @@ -1116,6 +1117,7 @@ private: /** If the caller owns the search latch */ const bool m_has_search_latch; }; +#endif /* BTR_CUR_HASH_ADAPT */ /** Functor to check for dictionay latching constraints. */ struct dict_sync_check : public sync_check_functor_t { diff --git a/storage/innobase/include/trx0i_s.h b/storage/innobase/include/trx0i_s.h index f588d820743..17a297527af 100644 --- a/storage/innobase/include/trx0i_s.h +++ b/storage/innobase/include/trx0i_s.h @@ -162,8 +162,10 @@ struct i_s_trx_row_t { /*!< check_foreigns in trx_t */ const char* trx_foreign_key_error; /*!< detailed_error in trx_t */ +#ifdef BTR_CUR_HASH_ADAPT ibool trx_has_search_latch; /*!< has_search_latch in trx_t */ +#endif /* BTR_CUR_HASH_ADAPT */ ulint trx_is_read_only; /*!< trx_t::read_only */ ulint trx_is_autocommit_non_locking; diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index d652c2162dc..062cac2b9ab 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -58,12 +58,14 @@ class FlushObserver; /** Dummy session used currently in MySQL interface */ extern sess_t* trx_dummy_sess; -/** -Releases the search latch if trx has reserved it. -@param[in,out] trx Transaction that may own the AHI latch */ -UNIV_INLINE -void -trx_search_latch_release_if_reserved(trx_t* trx); +#ifdef BTR_CUR_HASH_ADAPT +/** Assert that the transaction is not holding the adaptive hash index latch. +@param[in] trx transaction */ +# define trx_assert_no_search_latch(trx) \ + ut_ad(!trx->has_search_latch) +#else /* BTR_CUR_HASH_ADAPT */ +# define trx_assert_no_search_latch(trx) +#endif /** Set flush observer for the transaction @param[in/out] trx transaction struct @@ -1075,9 +1077,11 @@ struct trx_t { flush the log in trx_commit_complete_for_mysql() */ ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */ +#ifdef BTR_CUR_HASH_ADAPT bool has_search_latch; /*!< TRUE if this trx has latched the search system latch in S-mode */ +#endif /* BTR_CUR_HASH_ADAPT */ trx_dict_op_t dict_operation; /**< @see enum trx_dict_op_t */ /* Fields protected by the srv_conc_mutex. */ @@ -1478,7 +1482,7 @@ private: /* Only the owning thread should release the latch. */ - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); trx_mutex_enter(trx); @@ -1531,7 +1535,7 @@ private: /* Only the owning thread should release the latch. */ - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); trx_mutex_enter(trx); diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic index f0ed9b61c5a..14d519351e4 100644 --- a/storage/innobase/include/trx0trx.ic +++ b/storage/innobase/include/trx0trx.ic @@ -213,16 +213,6 @@ ok: trx->dict_operation = op; } -/** -Releases the search latch if trx has reserved it. -@param[in,out] trx Transaction that may own the AHI latch */ -UNIV_INLINE -void -trx_search_latch_release_if_reserved(trx_t* trx) -{ - ut_a(!trx->has_search_latch); -} - /********************************************************************//** Check if redo rseg is modified for insert/update. */ UNIV_INLINE diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 9cc6e434f38..880389edbf1 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -110,6 +110,17 @@ ENDIF() # Enable InnoDB's UNIV_DEBUG in debug builds SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DUNIV_DEBUG -DUNIV_SYNC_DEBUG") +OPTION(WITH_INNODB_AHI "Include innodb_adaptive_hash_index" ON) +OPTION(WITH_INNODB_ROOT_GUESS "Cache index root block descriptors" ON) +IF(WITH_INNODB_AHI) + ADD_DEFINITIONS(-DBTR_CUR_HASH_ADAPT -DBTR_CUR_ADAPT) + IF(NOT WITH_INNODB_ROOT_GUESS) + MESSAGE(WARNING "WITH_INNODB_AHI implies WITH_INNODB_ROOT_GUESS") + ENDIF() +ELSEIF(WITH_INNODB_ROOT_GUESS) + ADD_DEFINITIONS(-DBTR_CUR_ADAPT) +ENDIF() + OPTION(WITH_INNODB_EXTRA_DEBUG "Enable extra InnoDB debug checks" OFF) IF(WITH_INNODB_EXTRA_DEBUG) IF(NOT WITH_DEBUG) @@ -117,7 +128,9 @@ IF(WITH_INNODB_EXTRA_DEBUG) ENDIF() SET(EXTRA_DEBUG_FLAGS "") - SET(EXTRA_DEBUG_FLAGS "${EXTRA_DEBUG_FLAGS} -DUNIV_AHI_DEBUG") + IF(WITH_INNODB_AHI) + SET(EXTRA_DEBUG_FLAGS "${EXTRA_DEBUG_FLAGS} -DUNIV_AHI_DEBUG") + ENDIF() SET(EXTRA_DEBUG_FLAGS "${EXTRA_DEBUG_FLAGS} -DUNIV_DDL_DEBUG") SET(EXTRA_DEBUG_FLAGS "${EXTRA_DEBUG_FLAGS} -DUNIV_DEBUG_FILE_ACCESSES") SET(EXTRA_DEBUG_FLAGS "${EXTRA_DEBUG_FLAGS} -DUNIV_ZIP_DEBUG") @@ -189,7 +202,6 @@ ENDIF() ENDIF(NOT MSVC) -CHECK_FUNCTION_EXISTS(asprintf HAVE_ASPRINTF) CHECK_FUNCTION_EXISTS(vasprintf HAVE_VASPRINTF) CHECK_CXX_SOURCE_COMPILES("struct t1{ int a; char *b; }; struct t1 c= { .a=1, .b=0 }; main() { }" HAVE_C99_INITIALIZERS) @@ -197,18 +209,6 @@ IF(HAVE_C99_INITIALIZERS) ADD_DEFINITIONS(-DHAVE_C99_INITIALIZERS) ENDIF() -IF(UNIX) -# this is needed to know which one of atomic_cas_32() or atomic_cas_64() -# to use in the source -SET(CMAKE_EXTRA_INCLUDE_FILES pthread.h) -CHECK_TYPE_SIZE(pthread_t SIZEOF_PTHREAD_T) -SET(CMAKE_EXTRA_INCLUDE_FILES) -ENDIF() - -IF(SIZEOF_PTHREAD_T) - ADD_DEFINITIONS(-DSIZEOF_PTHREAD_T=${SIZEOF_PTHREAD_T}) -ENDIF() - SET(MUTEXTYPE "event" CACHE STRING "Mutex type: event, sys or futex") IF(MUTEXTYPE MATCHES "event") @@ -218,7 +218,7 @@ ELSEIF(MUTEXTYPE MATCHES "futex" AND DEFINED HAVE_IB_LINUX_FUTEX) ELSE() ADD_DEFINITIONS(-DMUTEX_SYS) ENDIF() - + # Include directories under innobase INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include ${CMAKE_SOURCE_DIR}/storage/innobase/handler) diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index b32e8deb6e6..16bdf602e81 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -40,11 +40,6 @@ Created 10/4/1994 Heikki Tuuri #include <algorithm> -#ifdef PAGE_CUR_ADAPT -# ifdef UNIV_SEARCH_PERF_STAT -static ulint page_cur_short_succ = 0; -# endif /* UNIV_SEARCH_PERF_STAT */ - /*******************************************************************//** This is a linear congruential generator PRNG. Returns a pseudo random number between 0 and 2^64-1 inclusive. The formula and the constants @@ -79,6 +74,11 @@ page_cur_lcg_prng(void) return(lcg_current); } +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_SEARCH_PERF_STAT +static ulint page_cur_short_succ; +# endif /* UNIV_SEARCH_PERF_STAT */ + /** Try a search shortcut based on the last insert. @param[in] block index page @param[in] index index tree @@ -246,7 +246,7 @@ exit_func: } return(success); } -#endif +#endif /* BTR_CUR_HASH_ADAPT */ #ifdef PAGE_CUR_LE_OR_EXTENDS /****************************************************************//** @@ -359,7 +359,7 @@ page_cur_search_with_match( ut_d(page_check_dir(page)); -#ifdef PAGE_CUR_ADAPT +#ifdef BTR_CUR_HASH_ADAPT if (page_is_leaf(page) && (mode == PAGE_CUR_LE) && !dict_index_is_spatial(index) @@ -380,7 +380,7 @@ page_cur_search_with_match( mode = PAGE_CUR_LE; } # endif -#endif +#endif /* BTR_CUR_HASH_ADAPT */ /* If the mode is for R-tree indexes, use the special MBR related compare functions */ @@ -552,6 +552,7 @@ up_rec_match: } } +#ifdef BTR_CUR_HASH_ADAPT /** Search the right position for a page cursor. @param[in] block buffer block @param[in] index index tree @@ -619,7 +620,7 @@ page_cur_search_with_match_bytes( ut_d(page_check_dir(page)); -#ifdef PAGE_CUR_ADAPT +#ifdef BTR_CUR_HASH_ADAPT if (page_is_leaf(page) && (mode == PAGE_CUR_LE) && (page_header_get_field(page, PAGE_N_DIRECTION) > 3) @@ -639,7 +640,7 @@ page_cur_search_with_match_bytes( mode = PAGE_CUR_LE; } # endif -#endif +#endif /* BTR_CUR_HASH_ADAPT */ /* The following flag does not work for non-latin1 char sets because cmp_full_field does not tell how many bytes matched */ @@ -805,6 +806,7 @@ up_rec_match: mem_heap_free(heap); } } +#endif /* BTR_CUR_HASH_ADAPT */ /***********************************************************//** Positions a page cursor on a randomly chosen user record on a page. If there diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 4cd7a443d79..e3d61531728 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1456,6 +1456,7 @@ plan_reset_cursor( plan->n_rows_prefetched = 0; } +#ifdef BTR_CUR_HASH_ADAPT /*********************************************************************//** Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). @@ -1485,11 +1486,8 @@ row_sel_try_search_shortcut( ut_ad(node->read_view); ut_ad(plan->unique_search); ut_ad(!plan->must_get_clust); -#ifdef UNIV_DEBUG - if (search_latch_locked) { - ut_ad(rw_lock_own(btr_get_search_latch(index), RW_LOCK_S)); - } -#endif /* UNIV_DEBUG */ + ut_ad(!search_latch_locked + || rw_lock_own(btr_get_search_latch(index), RW_LOCK_S)); row_sel_open_pcur(plan, search_latch_locked, mtr); @@ -1564,6 +1562,7 @@ func_exit: } return(ret); } +#endif /* BTR_CUR_HASH_ADAPT */ /*********************************************************************//** Performs a select step. @@ -1582,7 +1581,6 @@ row_sel( rec_t* rec; rec_t* old_vers; rec_t* clust_rec; - ibool search_latch_locked; ibool consistent_read; /* The following flag becomes TRUE when we are doing a @@ -1601,7 +1599,6 @@ row_sel( contains a clustered index latch, and &mtr must be committed before we move to the next non-clustered record */ - ulint found_flag; dberr_t err; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -1610,7 +1607,11 @@ row_sel( ut_ad(thr->run_node == node); - search_latch_locked = FALSE; +#ifdef BTR_CUR_HASH_ADAPT + ibool search_latch_locked = FALSE; +#else /* BTR_CUR_HASH_ADAPT */ +# define search_latch_locked false +#endif /* BTR_CUR_HASH_ADAPT */ if (node->read_view) { /* In consistent reads, we try to do with the hash index and @@ -1657,11 +1658,12 @@ table_loop: mtr_start(&mtr); +#ifdef BTR_CUR_HASH_ADAPT if (consistent_read && plan->unique_search && !plan->pcur_is_open && !plan->must_get_clust && !plan->table->big_rows) { if (!search_latch_locked) { - rw_lock_s_lock(btr_get_search_latch(index)); + btr_search_s_lock(index); search_latch_locked = TRUE; } else if (rw_lock_get_writer(btr_get_search_latch(index)) @@ -1674,25 +1676,23 @@ table_loop: from acquiring an s-latch for a long time, lowering performance significantly in multiprocessors. */ - rw_lock_s_unlock(btr_get_search_latch(index)); - rw_lock_s_lock(btr_get_search_latch(index)); + btr_search_s_unlock(index); + btr_search_s_lock(index); } - found_flag = row_sel_try_search_shortcut(node, plan, - search_latch_locked, - &mtr); - - if (found_flag == SEL_FOUND) { - + switch (row_sel_try_search_shortcut(node, plan, + search_latch_locked, + &mtr)) { + case SEL_FOUND: goto next_table; - - } else if (found_flag == SEL_EXHAUSTED) { - + case SEL_EXHAUSTED: goto table_exhausted; + default: + ut_ad(0); + case SEL_RETRY: + break; } - ut_ad(found_flag == SEL_RETRY); - plan_reset_cursor(plan); mtr_commit(&mtr); @@ -1700,10 +1700,11 @@ table_loop: } if (search_latch_locked) { - rw_lock_s_unlock(btr_get_search_latch(index)); + btr_search_s_unlock(index); search_latch_locked = FALSE; } +#endif /* BTR_CUR_HASH_ADAPT */ if (!plan->pcur_is_open) { /* Evaluate the expressions to build the search tuple and @@ -2236,13 +2237,15 @@ stop_for_a_while: mtr_commit(&mtr); -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(true); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ err = DB_SUCCESS; goto func_exit; @@ -2291,9 +2294,11 @@ lock_wait_or_error: #endif /* UNIV_DEBUG */ func_exit: +#ifdef BTR_CUR_HASH_ADAPT if (search_latch_locked) { - rw_lock_s_unlock(btr_get_search_latch(index)); + btr_search_s_unlock(index); } +#endif /* BTR_CUR_HASH_ADAPT */ if (heap != NULL) { mem_heap_free(heap); @@ -3077,7 +3082,7 @@ row_sel_store_mysql_field_func( mem_heap_t* heap; /* Copy an externally stored field to a temporary heap */ - ut_a(!prebuilt->trx->has_search_latch); + trx_assert_no_search_latch(prebuilt->trx); ut_ad(field_no == templ->clust_rec_field_no); ut_ad(templ->type != DATA_POINT); @@ -3929,6 +3934,7 @@ row_sel_enqueue_cache_row_for_mysql( ++prebuilt->n_fetch_cached; } +#ifdef BTR_CUR_HASH_ADAPT /*********************************************************************//** Tries to do a shortcut to fetch a clustered index record with a unique key, using the hash index if possible (not always). We assume that the search @@ -3997,6 +4003,7 @@ row_sel_try_search_shortcut_for_mysql( return(SEL_FOUND); } +#endif /* BTR_CUR_HASH_ADAPT */ /*********************************************************************//** Check a pushed-down index condition. @@ -4215,12 +4222,14 @@ row_search_mvcc( DBUG_RETURN(DB_END_OF_INDEX); } -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ if (dict_table_is_discarded(prebuilt->table)) { @@ -4248,19 +4257,7 @@ row_search_mvcc( && (prebuilt->read_just_key || prebuilt->m_read_virtual_key); - /*-------------------------------------------------------------*/ - /* PHASE 0: Release a possible s-latch we are holding on the - adaptive hash index latch if there is someone waiting behind */ - - if (trx->has_search_latch) { - - /* There is an x-latch request on the adaptive hash index: - release the s-latch to reduce starvation and wait for - BTR_SEA_TIMEOUT rounds before trying to keep it again over - calls from MySQL */ - - trx_search_latch_release_if_reserved(trx); - } + trx_assert_no_search_latch(trx); /* Reset the new record lock info if srv_locks_unsafe_for_binlog is set or session is using a READ COMMITED isolation level. Then @@ -4379,6 +4376,7 @@ row_search_mvcc( mtr_start(&mtr); +#ifdef BTR_CUR_HASH_ADAPT /*-------------------------------------------------------------*/ /* PHASE 2: Try fast adaptive hash index search if possible */ @@ -4415,7 +4413,7 @@ row_search_mvcc( and if we try that, we can deadlock on the adaptive hash index semaphore! */ - ut_a(!trx->has_search_latch); + trx_assert_no_search_latch(trx); rw_lock_s_lock(btr_get_search_latch(index)); trx->has_search_latch = true; @@ -4503,11 +4501,12 @@ row_search_mvcc( trx->has_search_latch = false; } } +#endif /* BTR_CUR_HASH_ADAPT */ /*-------------------------------------------------------------*/ /* PHASE 3: Open or restore index cursor position */ - trx_search_latch_release_if_reserved(trx); + trx_assert_no_search_latch(trx); spatial_search = dict_index_is_spatial(index) && mode >= PAGE_CUR_CONTAIN; @@ -5813,13 +5812,15 @@ func_exit: } } -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ DEBUG_SYNC_C("innodb_row_search_for_mysql_exit"); diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 018866451f6..bf8a326a633 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -200,9 +200,7 @@ srv_conc_enter_innodb_with_atomics( /* Release possible search system latch this thread has */ - if (trx->has_search_latch) { - trx_search_latch_release_if_reserved(trx); - } + trx_assert_no_search_latch(trx); thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); @@ -259,13 +257,15 @@ srv_conc_enter_innodb( { trx_t* trx = prebuilt->trx; -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ srv_conc_enter_innodb_with_atomics(trx); } @@ -279,13 +279,15 @@ srv_conc_force_enter_innodb( trx_t* trx) /*!< in: transaction object associated with the thread */ { -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ if (!srv_thread_concurrency) { @@ -318,13 +320,15 @@ srv_conc_force_exit_innodb( srv_conc_exit_innodb_with_atomics(trx); -#ifdef UNIV_DEBUG +#ifdef BTR_CUR_HASH_ADAPT +# ifdef UNIV_DEBUG { btrsea_sync_check check(trx->has_search_latch); ut_ad(!sync_check_iterate(check)); } -#endif /* UNIV_DEBUG */ +# endif /* UNIV_DEBUG */ +#endif /* BTR_CUR_HASH_ADAPT */ } /*********************************************************************//** diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index b2722c2a9bf..f42e640f4f3 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -1052,8 +1052,9 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_INDEX_DISCARD}, +#ifdef BTR_CUR_HASH_ADAPT /* ========== Counters for Adaptive Hash Index ========== */ - {"module_adaptive_hash", "adaptive_hash_index", "Adpative Hash Index", + {"module_adaptive_hash", "adaptive_hash_index", "Adaptive Hash Index", MONITOR_MODULE, MONITOR_DEFAULT_START, MONITOR_MODULE_ADAPTIVE_HASH}, @@ -1062,6 +1063,7 @@ static monitor_info_t innodb_counter_info[] = static_cast<monitor_type_t>( MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH}, +#endif /* BTR_CUR_HASH_ADAPT */ {"adaptive_hash_searches_btree", "adaptive_hash_index", "Number of searches using B-tree on an index search", @@ -1069,6 +1071,7 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE}, +#ifdef BTR_CUR_HASH_ADAPT {"adaptive_hash_pages_added", "adaptive_hash_index", "Number of index pages on which the Adaptive Hash Index is built", MONITOR_NONE, @@ -1100,6 +1103,7 @@ static monitor_info_t innodb_counter_info[] = "Number of Adaptive Hash Index rows updated", MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_ADAPTIVE_HASH_ROW_UPDATED}, +#endif /* BTR_CUR_HASH_ADAPT */ /* ========== Counters for tablespace ========== */ {"module_file", "file_system", "Tablespace and File System Manager", @@ -2022,9 +2026,11 @@ srv_mon_process_existing_counter( value = log_sys->max_modified_age_sync; break; +#ifdef BTR_CUR_HASH_ADAPT case MONITOR_OVLD_ADAPTIVE_HASH_SEARCH: value = btr_cur_n_sea; break; +#endif /* BTR_CUR_HASH_ADAPT */ case MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE: value = btr_cur_n_non_sea; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 0d249dfd824..e8c6c7a332c 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1219,7 +1219,9 @@ srv_refresh_innodb_monitor_stats(void) os_aio_refresh_stats(); +#ifdef BTR_CUR_HASH_ADAPT btr_cur_n_sea_old = btr_cur_n_sea; +#endif /* BTR_CUR_HASH_ADAPT */ btr_cur_n_non_sea_old = btr_cur_n_non_sea; log_refresh_stats(); @@ -1350,6 +1352,7 @@ srv_printf_innodb_monitor( "-------------------------------------\n", file); ibuf_print(file); +#ifdef BTR_CUR_HASH_ADAPT for (ulint i = 0; i < btr_ahi_parts; ++i) { rw_lock_s_lock(btr_search_latches[i]); ha_print_info(file, btr_search_sys->hash_tables[i]); @@ -1363,6 +1366,12 @@ srv_printf_innodb_monitor( (btr_cur_n_non_sea - btr_cur_n_non_sea_old) / time_elapsed); btr_cur_n_sea_old = btr_cur_n_sea; +#else /* BTR_CUR_HASH_ADAPT */ + fprintf(file, + "%.2f non-hash searches/s\n", + (btr_cur_n_non_sea - btr_cur_n_non_sea_old) + / time_elapsed); +#endif /* BTR_CUR_HASH_ADAPT */ btr_cur_n_non_sea_old = btr_cur_n_non_sea; fputs("---\n" diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 8afa90502d0..65991a711a3 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2843,7 +2843,9 @@ innodb_shutdown() ut_ad(buf_dblwr || !srv_was_started || srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); ut_ad(lock_sys || !srv_was_started); +#ifdef BTR_CUR_HASH_ADAPT ut_ad(btr_search_sys || !srv_was_started); +#endif /* BTR_CUR_HASH_ADAPT */ ut_ad(ibuf || !srv_was_started); ut_ad(log_sys || !srv_was_started); @@ -2864,9 +2866,11 @@ innodb_shutdown() /* This must be disabled before closing the buffer pool and closing the data dictionary. */ +#ifdef BTR_CUR_HASH_ADAPT if (dict_sys) { btr_search_disable(true); } +#endif /* BTR_CUR_HASH_ADAPT */ if (ibuf) { ibuf_close(); } @@ -2901,9 +2905,11 @@ innodb_shutdown() dict_close(); } +#ifdef BTR_CUR_HASH_ADAPT if (btr_search_sys) { btr_search_sys_free(); } +#endif /* BTR_CUR_HASH_ADAPT */ /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index cf3109c265e..9c5ae4d02da 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -588,7 +588,9 @@ thd_done: row->trx_foreign_key_error = NULL; } +#ifdef BTR_CUR_HASH_ADAPT row->trx_has_search_latch = (ibool) trx->has_search_latch; +#endif /* BTR_CUR_HASH_ADAPT */ row->trx_is_read_only = trx->read_only; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 29478edc9e2..609f7f8d39c 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -283,8 +283,7 @@ struct TrxFactory { ut_a(trx->lock.wait_lock == NULL); ut_a(trx->lock.wait_thr == NULL); - ut_a(!trx->has_search_latch); - + trx_assert_no_search_latch(trx); ut_a(trx->dict_operation_lock_mode == 0); if (trx->lock.lock_heap != NULL) { @@ -353,7 +352,7 @@ struct TrxFactory { ut_a(trx->lock.wait_thr == NULL); ut_a(trx->lock.wait_lock == NULL); - ut_a(!trx->has_search_latch); + trx_assert_no_search_latch(trx); ut_a(trx->dict_operation_lock_mode == 0); @@ -2627,10 +2626,12 @@ state_ok: (ulong) n_rec_locks); } +#ifdef BTR_CUR_HASH_ADAPT if (trx->has_search_latch) { newline = TRUE; fputs(", holds adaptive hash latch", f); } +#endif /* BTR_CUR_HASH_ADAPT */ if (trx->undo_no != 0) { newline = TRUE; diff --git a/storage/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc index 89d2d6c89ea..bf5515f4de0 100644 --- a/storage/innobase/ut/ut0new.cc +++ b/storage/innobase/ut/ut0new.cc @@ -32,7 +32,9 @@ const size_t alloc_max_retries = 60; /** Keys for registering allocations with performance schema. Keep this list alphabetically sorted. */ +#ifdef BTR_CUR_HASH_ADAPT PSI_memory_key mem_key_ahi; +#endif /* BTR_CUR_HASH_ADAPT */ PSI_memory_key mem_key_buf_buf_pool; PSI_memory_key mem_key_dict_stats_bg_recalc_pool_t; PSI_memory_key mem_key_dict_stats_index_map_t; @@ -59,7 +61,9 @@ the list below: (in ut_new_boot()) then mem_key_other is used. Keep this list alphabetically sorted. */ static PSI_memory_info pfs_info[] = { +#ifdef BTR_CUR_HASH_ADAPT {&mem_key_ahi, "adaptive hash index", 0}, +#endif /* BTR_CUR_HASH_ADAPT */ {&mem_key_buf_buf_pool, "buf_buf_pool", 0}, {&mem_key_dict_stats_bg_recalc_pool_t, "dict_stats_bg_recalc_pool_t", 0}, {&mem_key_dict_stats_index_map_t, "dict_stats_index_map_t", 0}, |