# name : innodb_adaptive_hash_index_num.patch # introduced : XtraDB on 5.5 (-13?) # maintainer : Yasufumi # #!!! notice !!! # Any small change to this file in the main branch # should be done or reviewed by the maintainer! diff -ruN a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c --- a/storage/innobase/btr/btr0btr.c 2010-12-04 15:52:23.355483176 +0900 +++ b/storage/innobase/btr/btr0btr.c 2010-12-04 16:12:48.639514256 +0900 @@ -1518,7 +1518,7 @@ } ut_a(block); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, NULL); header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP; #ifdef UNIV_BTR_DEBUG @@ -1587,7 +1587,7 @@ #ifndef UNIV_HOTBACKUP if (UNIV_LIKELY(!recovery)) { - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); } block->check_index_page_at_flush = TRUE; @@ -1755,7 +1755,7 @@ ut_a(!page_zip || page_zip_validate(page_zip, page)); #endif /* UNIV_ZIP_DEBUG */ - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); btr_blob_dbg_remove(page, index, "btr_page_empty"); /* Recreate the page: note that global data on page (possible @@ -3065,7 +3065,7 @@ mem_heap_free(heap); } - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); /* Make the father empty */ btr_page_empty(father_block, father_page_zip, index, page_level, mtr); @@ -3289,7 +3289,7 @@ goto err_exit; } - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); /* Remove the page from the level list */ btr_level_list_remove(space, zip_size, page, mtr); @@ -3330,7 +3330,7 @@ goto err_exit; } - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); #ifdef UNIV_BTR_DEBUG if (UNIV_LIKELY_NULL(merge_page_zip)) { @@ -3445,7 +3445,7 @@ ut_a(btr_page_get_next(page, mtr) == FIL_NULL); ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); btr_page_get_father(index, block, mtr, &cursor); father = btr_cur_get_block(&cursor); @@ -3550,7 +3550,7 @@ page = buf_block_get_frame(block); ut_a(page_is_comp(merge_page) == page_is_comp(page)); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); if (left_page_no == FIL_NULL && !page_is_leaf(page)) { diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c --- a/storage/innobase/btr/btr0cur.c 2010-12-04 15:52:23.359513820 +0900 +++ b/storage/innobase/btr/btr0cur.c 2010-12-04 16:12:48.643551837 +0900 @@ -498,7 +498,7 @@ #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; #endif - if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED + if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate @@ -534,7 +534,7 @@ if (has_search_latch) { /* Release possible search latch to obey latching order */ - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(cursor->index->id)); } /* Store the position of the tree latch we push to mtr so that we @@ -856,7 +856,7 @@ if (has_search_latch) { - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(cursor->index->id)); } } @@ -1971,7 +1971,7 @@ btr_search_update_hash_on_delete(cursor); } - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); } if (!(flags & BTR_KEEP_SYS_FLAG)) { @@ -1985,7 +1985,7 @@ row_upd_rec_in_place(rec, index, offsets, update, page_zip); if (block->is_hashed) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } if (page_zip && !dict_index_is_clust(index) @@ -2763,7 +2763,7 @@ } if (block->is_hashed) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index->id)); } page_zip = buf_block_get_page_zip(block); @@ -2779,7 +2779,7 @@ } if (block->is_hashed) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); } btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx, @@ -2906,13 +2906,13 @@ == dict_table_is_comp(cursor->index->table)); if (block->is_hashed) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); } btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val); if (block->is_hashed) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } btr_cur_del_mark_set_sec_rec_log(rec, val, mtr); diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c --- a/storage/innobase/btr/btr0sea.c 2010-12-04 15:52:23.387513429 +0900 +++ b/storage/innobase/btr/btr0sea.c 2010-12-04 16:14:51.721884049 +0900 @@ -48,6 +48,8 @@ UNIV_INTERN char btr_search_enabled = TRUE; UNIV_INTERN ibool btr_search_fully_disabled = FALSE; +UNIV_INTERN ulint btr_search_index_num = 1; + /** Mutex protecting btr_search_enabled */ static mutex_t btr_search_enabled_mutex; @@ -79,7 +81,9 @@ /* We will allocate the latch from dynamic memory to get it to the same DRAM page as other hotspot semaphores */ -UNIV_INTERN rw_lock_t* btr_search_latch_temp; +//UNIV_INTERN rw_lock_t* btr_search_latch_temp; + +UNIV_INTERN rw_lock_t** btr_search_latch_part; /** padding to prevent other memory update hotspots from residing on the same memory cache line */ @@ -131,18 +135,19 @@ will not guarantee success. */ static void -btr_search_check_free_space_in_heap(void) +btr_search_check_free_space_in_heap( /*=====================================*/ + index_id_t key) { hash_table_t* table; mem_heap_t* heap; #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(key); heap = table->heap; @@ -153,7 +158,7 @@ if (heap->free_block == NULL) { buf_block_t* block = buf_block_alloc(NULL); - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(key)); if (heap->free_block == NULL) { heap->free_block = block; @@ -161,7 +166,7 @@ buf_block_free(block); } - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(key)); } } @@ -173,19 +178,30 @@ /*==================*/ ulint hash_size) /*!< in: hash index hash table size */ { + ulint i; /* We allocate the search latch from dynamic memory: see above at the global variable definition */ - btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); + //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); - rw_lock_create(btr_search_latch_key, &btr_search_latch, - SYNC_SEARCH_SYS); + //rw_lock_create(btr_search_latch_key, &btr_search_latch, + // SYNC_SEARCH_SYS); mutex_create(btr_search_enabled_mutex_key, &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); - btr_search_sys->hash_index = ha_create(hash_size, 0, 0); + /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */ + btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num); + btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num); + for (i = 0; i < btr_search_index_num; i++) { + btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t)); + + rw_lock_create(btr_search_latch_key, + btr_search_latch_part[i], SYNC_SEARCH_SYS); + + btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0); + } } /*****************************************************************//** @@ -195,11 +211,20 @@ btr_search_sys_free(void) /*=====================*/ { - rw_lock_free(&btr_search_latch); - mem_free(btr_search_latch_temp); - btr_search_latch_temp = NULL; - mem_heap_free(btr_search_sys->hash_index->heap); - hash_table_free(btr_search_sys->hash_index); + ulint i; + + for (i = 0; i < btr_search_index_num; i++) { + mem_heap_free(btr_search_sys->hash_index[i]->heap); + hash_table_free(btr_search_sys->hash_index[i]); + + rw_lock_free(btr_search_latch_part[i]); + + mem_free(btr_search_latch_part[i]); + } + + //rw_lock_free(&btr_search_latch); + //mem_free(btr_search_latch_temp); + //btr_search_latch_temp = NULL; mem_free(btr_search_sys); btr_search_sys = NULL; } @@ -212,7 +237,7 @@ /*====================*/ { mutex_enter(&btr_search_enabled_mutex); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); /* Disable access to hash index, also tell ha_insert_for_fold() stop adding new nodes to hash index, but still allow updating @@ -230,7 +255,7 @@ /* btr_search_enabled_mutex should guarantee this. */ ut_ad(!btr_search_enabled); - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); mutex_exit(&btr_search_enabled_mutex); } @@ -242,12 +267,12 @@ /*====================*/ { mutex_enter(&btr_search_enabled_mutex); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); btr_search_enabled = TRUE; btr_search_fully_disabled = FALSE; - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); mutex_exit(&btr_search_enabled_mutex); } @@ -300,20 +325,21 @@ ulint btr_search_info_get_ref_count( /*==========================*/ - btr_search_t* info) /*!< in: search info. */ + btr_search_t* info, /*!< in: search info. */ + index_id_t key) { ulint ret; ut_ad(info); #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(key)); ret = info->ref_count; - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(key)); return(ret); } @@ -334,8 +360,8 @@ int cmp; #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ index = cursor->index; @@ -453,8 +479,8 @@ /*!< in: cursor */ { #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX)); ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED) || rw_lock_own(&block->lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ @@ -538,7 +564,7 @@ ut_ad(cursor->flag == BTR_CUR_HASH_FAIL); #ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX)); ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) || rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ @@ -578,10 +604,10 @@ mem_heap_free(heap); } #ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - ha_insert_for_fold(btr_search_sys->hash_index, fold, + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold, block, rec); } } @@ -601,8 +627,8 @@ ulint* params2; #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ block = btr_cur_get_block(cursor); @@ -623,7 +649,7 @@ if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) { - btr_search_check_free_space_in_heap(); + btr_search_check_free_space_in_heap(cursor->index->id); } if (cursor->flag == BTR_CUR_HASH_FAIL) { @@ -633,11 +659,11 @@ btr_search_n_hash_fail++; #endif /* UNIV_SEARCH_PERF_STAT */ - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); btr_search_update_hash_ref(info, block, cursor); - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } if (build_index) { @@ -881,17 +907,17 @@ cursor->flag = BTR_CUR_HASH; if (UNIV_LIKELY(!has_search_latch)) { - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index_id)); if (UNIV_UNLIKELY(!btr_search_enabled)) { goto failure_unlock; } } - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX); - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0); + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX); + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0); - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold); if (UNIV_UNLIKELY(!rec)) { goto failure_unlock; @@ -909,7 +935,7 @@ goto failure_unlock; } - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index_id)); buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); } @@ -1006,7 +1032,7 @@ /*-------------------------------------------*/ failure_unlock: if (UNIV_LIKELY(!has_search_latch)) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index_id)); } failure: cursor->flag = BTR_CUR_HASH_FAIL; @@ -1029,10 +1055,11 @@ void btr_search_drop_page_hash_index( /*============================*/ - buf_block_t* block) /*!< in: block containing index page, + buf_block_t* block, /*!< in: block containing index page, s- or x-latched, or an index page for which we know that block->buf_fix_count == 0 */ + dict_index_t* index_in) { hash_table_t* table; ulint n_fields; @@ -1051,22 +1078,60 @@ ulint* offsets; #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + if (index_in) { + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX)); + } #endif /* UNIV_SYNC_DEBUG */ retry: - rw_lock_s_lock(&btr_search_latch); + if (index_in) { + index = index_in; + rw_lock_s_lock(btr_search_get_latch(index->id)); + } else if (btr_search_index_num > 1) { + rw_lock_t* btr_search_latch; + + /* FIXME: This may be optimistic implementation still. */ + btr_search_latch = (rw_lock_t*)(block->btr_search_latch); + if (UNIV_LIKELY(!btr_search_latch)) { + if (block->is_hashed) { + goto retry; + } + return; + } + rw_lock_s_lock(btr_search_latch); + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) { + rw_lock_s_unlock(btr_search_latch); + goto retry; + } + if (UNIV_LIKELY(!block->is_hashed)) { + rw_lock_s_unlock(btr_search_latch); + return; + } + index = block->index; + ut_a(btr_search_latch == btr_search_get_latch(index->id)); + } else { + /* btr_search_index_num == 1 */ + /* btr_search_latch is only one and able to obtain + before evaluating block->is_hashed. */ + rw_lock_s_lock(btr_search_latch_part[0]); + if (UNIV_LIKELY(!block->is_hashed)) { + rw_lock_s_unlock(btr_search_latch_part[0]); + return; + } + index = block->index; + } + page = block->frame; if (UNIV_LIKELY(!block->is_hashed)) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); return; } - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(index->id); #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) @@ -1076,14 +1141,14 @@ n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; - index = block->index; + ut_a(index == block->index); ut_a(!dict_index_is_ibuf(index)); /* NOTE: The fields of block must not be accessed after releasing btr_search_latch, as the index page might only be s-latched! */ - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); ut_a(n_fields + n_bytes > 0); @@ -1133,7 +1198,7 @@ mem_heap_free(heap); } - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index->id)); if (UNIV_UNLIKELY(!block->is_hashed)) { /* Someone else has meanwhile dropped the hash index */ @@ -1149,7 +1214,7 @@ /* Someone else has meanwhile built a new hash index on the page, with different parameters */ - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); mem_free(folds); goto retry; @@ -1165,6 +1230,7 @@ block->is_hashed = FALSE; block->index = NULL; + block->btr_search_latch = NULL; cleanup: #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG @@ -1177,14 +1243,14 @@ "InnoDB: the hash index to a page of %s," " still %lu hash nodes remain.\n", index->name, (ulong) block->n_pointers); - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); btr_search_validate(); } else { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); } #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ mem_free(folds); @@ -1216,9 +1282,9 @@ ulint* offsets; ibool released_search_latch; - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(index->id); for (j = 0; j < srv_buf_pool_instances; j++) { buf_pool_t* buf_pool; @@ -1252,7 +1318,7 @@ /* keeping latch order */ - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); released_search_latch = TRUE; rw_lock_x_lock(&block->lock); @@ -1304,7 +1370,7 @@ mem_heap_empty(heap); } - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index->id)); if (UNIV_UNLIKELY(!block->is_hashed)) { goto cleanup; @@ -1314,12 +1380,12 @@ if (UNIV_UNLIKELY(block->curr_n_fields != n_fields) || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); rw_lock_x_unlock(&block->lock); mem_free(folds); - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); goto retry; } @@ -1333,6 +1399,7 @@ block->is_hashed = FALSE; block->index = NULL; + block->btr_search_latch = NULL; cleanup: #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG @@ -1345,18 +1412,18 @@ index->name, (ulong) block->n_pointers); } #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); rw_lock_x_unlock(&block->lock); mem_free(folds); - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); } } } while (released_search_latch); } - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -1403,7 +1470,7 @@ buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, NULL); } mtr_commit(&mtr); @@ -1445,26 +1512,26 @@ ut_ad(index); ut_a(!dict_index_is_ibuf(index)); - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(index->id); page = buf_block_get_frame(block); #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)); ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED) || rw_lock_own(&(block->lock), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); if (block->is_hashed && ((block->curr_n_fields != n_fields) || (block->curr_n_bytes != n_bytes) || (block->curr_left_side != left_side))) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); } else { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); } n_recs = page_get_n_recs(page); @@ -1558,9 +1625,9 @@ fold = next_fold; } - btr_search_check_free_space_in_heap(); + btr_search_check_free_space_in_heap(index->id); - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index->id)); if (UNIV_UNLIKELY(btr_search_fully_disabled)) { goto exit_func; @@ -1588,6 +1655,7 @@ block->curr_n_bytes = n_bytes; block->curr_left_side = left_side; block->index = index; + block->btr_search_latch = btr_search_get_latch(index->id); for (i = 0; i < n_cached; i++) { @@ -1595,7 +1663,7 @@ } exit_func: - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index->id)); mem_free(folds); mem_free(recs); @@ -1634,13 +1702,13 @@ ut_a(!(new_block->is_hashed || block->is_hashed) || !dict_index_is_ibuf(index)); - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); if (new_block->is_hashed) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); return; } @@ -1655,7 +1723,7 @@ new_block->n_bytes = block->curr_n_bytes; new_block->left_side = left_side; - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); ut_a(n_fields + n_bytes > 0); @@ -1667,7 +1735,7 @@ return; } - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); } /********************************************************************//** @@ -1706,7 +1774,7 @@ ut_a(block->curr_n_fields + block->curr_n_bytes > 0); ut_a(!dict_index_is_ibuf(cursor->index)); - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(cursor->index->id); index_id = cursor->index->id; fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_, @@ -1715,11 +1783,11 @@ if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); ha_search_and_delete_if_found(table, fold, rec); - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } /********************************************************************//** @@ -1753,21 +1821,21 @@ ut_a(block->index == cursor->index); ut_a(!dict_index_is_ibuf(cursor->index)); - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); if ((cursor->flag == BTR_CUR_HASH) && (cursor->n_fields == block->curr_n_fields) && (cursor->n_bytes == block->curr_n_bytes) && !block->curr_left_side) { - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(cursor->index->id); ha_search_and_update_if_found(table, cursor->fold, rec, block, page_rec_get_next(rec)); - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } else { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); btr_search_update_hash_on_insert(cursor); } @@ -1802,9 +1870,9 @@ ulint* offsets = offsets_; rec_offs_init(offsets_); - table = btr_search_sys->hash_index; + table = btr_search_get_hash_index(cursor->index->id); - btr_search_check_free_space_in_heap(); + btr_search_check_free_space_in_heap(cursor->index->id); rec = btr_cur_get_rec(cursor); @@ -1849,7 +1917,7 @@ } else { if (left_side) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index_id)); locked = TRUE; @@ -1863,7 +1931,7 @@ if (!locked) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index_id)); locked = TRUE; } @@ -1881,7 +1949,7 @@ if (!left_side) { if (!locked) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index_id)); locked = TRUE; } @@ -1896,7 +1964,7 @@ if (!locked) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(index_id)); locked = TRUE; } @@ -1919,7 +1987,7 @@ mem_heap_free(heap); } if (locked) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(index_id)); } } @@ -1935,7 +2003,7 @@ ha_node_t* node; ulint n_page_dumps = 0; ibool ok = TRUE; - ulint i; + ulint i,j; ulint cell_count; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -1947,23 +2015,25 @@ rec_offs_init(offsets_); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); buf_pool_page_hash_x_lock_all(); - cell_count = hash_get_n_cells(btr_search_sys->hash_index); + for (j = 0; j < btr_search_index_num; j++) { + + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]); for (i = 0; i < cell_count; i++) { /* We release btr_search_latch every once in a while to give other queries a chance to run. */ if ((i != 0) && ((i % chunk_size) == 0)) { buf_pool_page_hash_x_unlock_all(); - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); os_thread_yield(); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); buf_pool_page_hash_x_lock_all(); } - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node; for (; node != NULL; node = node->next) { const buf_block_t* block @@ -2072,19 +2142,21 @@ give other queries a chance to run. */ if (i != 0) { buf_pool_page_hash_x_unlock_all(); - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); os_thread_yield(); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); buf_pool_page_hash_x_lock_all(); } - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) { + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) { ok = FALSE; } } + } /*for (j = 0; j < btr_search_index_num; j++)*/ + buf_pool_page_hash_x_unlock_all(); - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c --- a/storage/innobase/buf/buf0buf.c 2010-12-04 15:55:21.351597052 +0900 +++ b/storage/innobase/buf/buf0buf.c 2010-12-04 16:12:48.654550708 +0900 @@ -949,6 +949,7 @@ block->check_index_page_at_flush = FALSE; block->index = NULL; + block->btr_search_latch = NULL; block->is_hashed = FALSE; @@ -1477,7 +1478,7 @@ /* To follow the latching order, we have to release btr_search_latch before acquiring block->latch. */ - rw_lock_x_unlock(&btr_search_latch); + btr_search_x_unlock_all(); /* When we release the search latch, we must rescan all blocks, because some may become hashed again. */ @@ -1508,11 +1509,11 @@ anything. block->is_hashed can only be set on uncompressed file pages. */ - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, NULL); rw_lock_x_unlock(&block->lock); - rw_lock_x_lock(&btr_search_latch); + btr_search_x_lock_all(); ut_ad(!btr_search_enabled); } @@ -1531,7 +1532,11 @@ ibool released_search_latch; #ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ulint j; + + for (j = 0; j < btr_search_index_num; j++) { + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX)); + } #endif /* UNIV_SYNC_DEBUG */ ut_ad(!btr_search_enabled); @@ -2636,6 +2641,7 @@ { block->check_index_page_at_flush = FALSE; block->index = NULL; + block->btr_search_latch = NULL; block->n_hash_helps = 0; block->is_hashed = FALSE; diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c --- a/storage/innobase/buf/buf0lru.c 2010-12-04 15:35:29.137347521 +0900 +++ b/storage/innobase/buf/buf0lru.c 2010-12-04 16:12:48.658550840 +0900 @@ -1776,7 +1776,7 @@ UNIV_MEM_VALID(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); - btr_search_drop_page_hash_index((buf_block_t*) bpage); + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL); UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame, UNIV_PAGE_SIZE); diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c --- a/storage/innobase/dict/dict0dict.c 2010-12-04 15:52:23.398513916 +0900 +++ b/storage/innobase/dict/dict0dict.c 2010-12-04 16:12:48.662550715 +0900 @@ -1812,7 +1812,7 @@ zero. */ for (;;) { - ulint ref_count = btr_search_info_get_ref_count(info); + ulint ref_count = btr_search_info_get_ref_count(info, index->id); if (ref_count == 0) { break; } diff -ruN a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c --- a/storage/innobase/ha/ha0ha.c 2010-11-03 07:01:13.000000000 +0900 +++ b/storage/innobase/ha/ha0ha.c 2010-12-04 16:12:48.665593752 +0900 @@ -102,7 +102,8 @@ ut_ad(table); ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); #ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE)); + /* cannot identificate which btr_search_latch[i] for now */ + //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE)); #endif /* UNIV_SYNC_DEBUG */ #ifndef UNIV_HOTBACKUP diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc --- a/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:20.185850734 +0900 +++ b/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:48.674552412 +0900 @@ -11682,6 +11682,11 @@ "Disable with --skip-innodb-adaptive-hash-index.", NULL, innodb_adaptive_hash_index_update, TRUE); +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)", + NULL, NULL, 1, 1, 32, 0); + static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay, PLUGIN_VAR_RQCMDARG, "Replication thread delay (ms) on the slave server if " @@ -12047,6 +12052,7 @@ MYSQL_SYSVAR(use_sys_stats_table), MYSQL_SYSVAR(stats_sample_pages), MYSQL_SYSVAR(adaptive_hash_index), + MYSQL_SYSVAR(adaptive_hash_index_partitions), MYSQL_SYSVAR(stats_method), MYSQL_SYSVAR(replication_delay), MYSQL_SYSVAR(status_file), diff -ruN a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h --- a/storage/innobase/include/btr0sea.h 2010-12-03 15:48:03.070987226 +0900 +++ b/storage/innobase/include/btr0sea.h 2010-12-04 16:12:48.707551382 +0900 @@ -85,7 +85,8 @@ ulint btr_search_info_get_ref_count( /*==========================*/ - btr_search_t* info); /*!< in: search info. */ + btr_search_t* info, /*!< in: search info. */ + index_id_t key); /*********************************************************************//** Updates the search info. */ UNIV_INLINE @@ -136,10 +137,11 @@ void btr_search_drop_page_hash_index( /*============================*/ - buf_block_t* block); /*!< in: block containing index page, + buf_block_t* block, /*!< in: block containing index page, s- or x-latched, or an index page for which we know that block->buf_fix_count == 0 */ + dict_index_t* index_in); /************************************************************************ Drops a page hash index based on index */ UNIV_INTERN @@ -199,10 +201,47 @@ # define btr_search_validate() TRUE #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ +/********************************************************************//** +New functions to control split btr_search_index */ +UNIV_INLINE +hash_table_t* +btr_search_get_hash_index( +/*======================*/ + index_id_t key); + +UNIV_INLINE +rw_lock_t* +btr_search_get_latch( +/*=================*/ + index_id_t key); + +UNIV_INLINE +void +btr_search_x_lock_all(void); +/*========================*/ + +UNIV_INLINE +void +btr_search_x_unlock_all(void); +/*==========================*/ + +UNIV_INLINE +void +btr_search_s_lock_all(void); +/*========================*/ + +UNIV_INLINE +void +btr_search_s_unlock_all(void); +/*==========================*/ + + /** Flag: has the search system been enabled? Protected by btr_search_latch and btr_search_enabled_mutex. */ extern char btr_search_enabled; +extern ulint btr_search_index_num; + /** Flag: whether the search system has completed its disabling process, It is set to TRUE right after buf_pool_drop_hash_index() in btr_search_disable(), indicating hash index entries are cleaned up. @@ -269,7 +308,7 @@ /** The hash index system */ struct btr_search_sys_struct{ - hash_table_t* hash_index; /*!< the adaptive hash index, + hash_table_t** hash_index; /*!< the adaptive hash index, mapping dtuple_fold values to rec_t pointers on index pages */ }; @@ -290,10 +329,12 @@ Bear in mind (3) and (4) when using the hash index. */ -extern rw_lock_t* btr_search_latch_temp; +//extern rw_lock_t* btr_search_latch_temp; + +extern rw_lock_t** btr_search_latch_part; /** The latch protecting the adaptive search system */ -#define btr_search_latch (*btr_search_latch_temp) +//#define btr_search_latch (*btr_search_latch_temp) #ifdef UNIV_SEARCH_PERF_STAT /** Number of successful adaptive hash index lookups */ diff -ruN a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic --- a/storage/innobase/include/btr0sea.ic 2010-11-03 07:01:13.000000000 +0900 +++ b/storage/innobase/include/btr0sea.ic 2010-12-04 16:12:48.709511202 +0900 @@ -62,8 +62,8 @@ btr_search_t* info; #ifdef UNIV_SYNC_DEBUG - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED)); + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ info = btr_search_get_info(index); @@ -82,3 +82,72 @@ btr_search_info_update_slow(info, cursor); } + +/*********************************************************************//** +New functions to control split btr_search_index */ +UNIV_INLINE +hash_table_t* +btr_search_get_hash_index( +/*======================*/ + index_id_t key) +{ + return(btr_search_sys->hash_index[key % btr_search_index_num]); +} + +UNIV_INLINE +rw_lock_t* +btr_search_get_latch( +/*=================*/ + index_id_t key) +{ + return(btr_search_latch_part[key % btr_search_index_num]); +} + +UNIV_INLINE +void +btr_search_x_lock_all(void) +/*=======================*/ +{ + ulint i; + + for (i = 0; i < btr_search_index_num; i++) { + rw_lock_x_lock(btr_search_latch_part[i]); + } +} + +UNIV_INLINE +void +btr_search_x_unlock_all(void) +/*==========================*/ +{ + ulint i; + + for (i = 0; i < btr_search_index_num; i++) { + rw_lock_x_unlock(btr_search_latch_part[i]); + } +} + +UNIV_INLINE +void +btr_search_s_lock_all(void) +/*=======================*/ +{ + ulint i; + + for (i = 0; i < btr_search_index_num; i++) { + rw_lock_s_lock(btr_search_latch_part[i]); + } +} + +UNIV_INLINE +void +btr_search_s_unlock_all(void) +/*=========================*/ +{ + ulint i; + + for (i = 0; i < btr_search_index_num; i++) { + rw_lock_s_unlock(btr_search_latch_part[i]); + } +} + diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h --- a/storage/innobase/include/buf0buf.h 2010-12-15 19:00:07.713604580 +0900 +++ b/storage/innobase/include/buf0buf.h 2010-12-15 20:58:03.546839883 +0900 @@ -1545,7 +1545,7 @@ pointers in the adaptive hash index pointing to this frame */ #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - unsigned is_hashed:1; /*!< TRUE if hash index has + volatile unsigned is_hashed:1; /*!< TRUE if hash index has already been built on this page; note that it does not guarantee that the index is @@ -1559,6 +1559,7 @@ unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */ dict_index_t* index; /*!< Index for which the adaptive hash index has been created. */ + volatile rw_lock_t* btr_search_latch; /* @} */ # ifdef UNIV_SYNC_DEBUG /** @name Debug fields */ diff -ruN a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic --- a/storage/innobase/include/row0upd.ic 2010-11-03 07:01:13.000000000 +0900 +++ b/storage/innobase/include/row0upd.ic 2010-12-04 16:12:48.710551113 +0900 @@ -158,7 +158,7 @@ ut_ad(dict_index_is_clust(index)); ut_ad(rec_offs_validate(rec, index, offsets)); #ifdef UNIV_SYNC_DEBUG - if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) { + if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) { ut_ad(!buf_block_align(rec)->is_hashed); } #endif /* UNIV_SYNC_DEBUG */ diff -ruN a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c --- a/storage/innobase/page/page0page.c 2010-11-03 07:01:13.000000000 +0900 +++ b/storage/innobase/page/page0page.c 2010-12-04 16:12:48.712550963 +0900 @@ -218,7 +218,7 @@ const ibool is_hashed = block->is_hashed; if (is_hashed) { - rw_lock_x_lock(&btr_search_latch); + rw_lock_x_lock(btr_search_get_latch(block->index->id)); } ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); @@ -244,7 +244,7 @@ #ifndef UNIV_HOTBACKUP if (is_hashed) { - rw_lock_x_unlock(&btr_search_latch); + rw_lock_x_unlock(btr_search_get_latch(block->index->id)); } #endif /* !UNIV_HOTBACKUP */ } diff -ruN a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c --- a/storage/innobase/page/page0zip.c 2010-12-04 15:57:13.061494433 +0900 +++ b/storage/innobase/page/page0zip.c 2010-12-04 16:12:48.716470334 +0900 @@ -4445,7 +4445,7 @@ #ifndef UNIV_HOTBACKUP temp_block = buf_block_alloc(buf_pool); - btr_search_drop_page_hash_index(block); + btr_search_drop_page_hash_index(block, index); block->check_index_page_at_flush = TRUE; #else /* !UNIV_HOTBACKUP */ ut_ad(block == back_block1); diff -ruN a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c --- a/storage/innobase/row/row0sel.c 2010-12-04 16:09:53.204513572 +0900 +++ b/storage/innobase/row/row0sel.c 2010-12-04 16:12:48.722551273 +0900 @@ -1210,7 +1210,7 @@ ut_ad(plan->unique_search); ut_ad(!plan->must_get_clust); #ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED)); #endif /* UNIV_SYNC_DEBUG */ row_sel_open_pcur(plan, TRUE, mtr); @@ -1381,10 +1381,10 @@ && !plan->must_get_clust && !plan->table->big_rows) { if (!search_latch_locked) { - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_lock(btr_search_get_latch(index->id)); search_latch_locked = TRUE; - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) { + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) { /* There is an x-latch request waiting: release the s-latch for a moment; as an s-latch here is often @@ -1393,8 +1393,8 @@ from acquiring an s-latch for a long time, lowering performance significantly in multiprocessors. */ - rw_lock_s_unlock(&btr_search_latch); - rw_lock_s_lock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); + rw_lock_s_lock(btr_search_get_latch(index->id)); } found_flag = row_sel_try_search_shortcut(node, plan, &mtr); @@ -1417,7 +1417,7 @@ } if (search_latch_locked) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); search_latch_locked = FALSE; } @@ -1993,7 +1993,7 @@ func_exit: if (search_latch_locked) { - rw_lock_s_unlock(&btr_search_latch); + rw_lock_s_unlock(btr_search_get_latch(index->id)); } if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); @@ -3356,6 +3356,8 @@ /* if the returned record was locked and we did a semi-consistent read (fetch the newest committed version), then this is set to TRUE */ + ulint i; + ulint should_release; #ifdef UNIV_SEARCH_DEBUG ulint cnt = 0; #endif /* UNIV_SEARCH_DEBUG */ @@ -3441,18 +3443,32 @@ /* PHASE 0: Release a possible s-latch we are holding on the adaptive hash index latch if there is someone waiting behind */ - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED) - && trx->has_search_latch) { + should_release = 0; + for (i = 0; i < btr_search_index_num; i++) { + if ((trx->has_search_latch & ((ulint)1 << i)) + && rw_lock_get_writer(btr_search_latch_part[i]) + != RW_LOCK_NOT_LOCKED) { + should_release |= ((ulint)1 << i); + } + } + + if (should_release) { /* 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 */ - rw_lock_s_unlock(&btr_search_latch); - trx->has_search_latch = FALSE; + for (i = 0; i < btr_search_index_num; i++) { + if (should_release & ((ulint)1 << i)) { + rw_lock_s_unlock(btr_search_latch_part[i]); + trx->has_search_latch &= ~((ulint)1 << i); + } + } + if (!trx->has_search_latch) { trx->search_latch_timeout = BTR_SEA_TIMEOUT; + } } /* Reset the new record lock info if srv_locks_unsafe_for_binlog @@ -3603,9 +3619,11 @@ hash index semaphore! */ #ifndef UNIV_SEARCH_DEBUG - if (!trx->has_search_latch) { - rw_lock_s_lock(&btr_search_latch); - trx->has_search_latch = TRUE; + if (!(trx->has_search_latch + & ((ulint)1 << (index->id % btr_search_index_num)))) { + rw_lock_s_lock(btr_search_get_latch(index->id)); + trx->has_search_latch |= + (ulint)1 << (index->id % btr_search_index_num); } #endif switch (row_sel_try_search_shortcut_for_mysql( @@ -3666,7 +3684,11 @@ trx->search_latch_timeout--; - rw_lock_s_unlock(&btr_search_latch); + for (i = 0; i < btr_search_index_num; i++) { + if (trx->has_search_latch & ((ulint)1 << i)) { + rw_lock_s_unlock(btr_search_latch_part[i]); + } + } trx->has_search_latch = FALSE; } @@ -3690,7 +3712,12 @@ /* PHASE 3: Open or restore index cursor position */ if (trx->has_search_latch) { - rw_lock_s_unlock(&btr_search_latch); + + for (i = 0; i < btr_search_index_num; i++) { + if (trx->has_search_latch & ((ulint)1 << i)) { + rw_lock_s_unlock(btr_search_latch_part[i]); + } + } trx->has_search_latch = FALSE; } diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c --- a/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:20.231484679 +0900 +++ b/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:48.726551018 +0900 @@ -2050,7 +2050,9 @@ "-------------------------------------\n", file); ibuf_print(file); - ha_print_info(file, btr_search_sys->hash_index); + for (i = 0; i < btr_search_index_num; i++) { + ha_print_info(file, btr_search_get_hash_index((index_id_t)i)); + } fprintf(file, "%.2f hash searches/s, %.2f non-hash searches/s\n", @@ -2075,14 +2077,15 @@ ut_total_allocated_memory, mem_pool_get_reserved(mem_comm_pool)); /* Calcurate reserved memories */ - if (btr_search_sys && btr_search_sys->hash_index->heap) { - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap); + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) { + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap); } else { btr_search_sys_subtotal = 0; - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) { - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]); + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) { + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]); } } + btr_search_sys_subtotal *= btr_search_index_num; lock_sys_subtotal = 0; if (trx_sys) { @@ -2109,10 +2112,10 @@ " Threads %lu \t(%lu + %lu)\n", (ulong) (btr_search_sys - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0) + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0) + btr_search_sys_subtotal, (ulong) (btr_search_sys - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0), + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0), (ulong) btr_search_sys_subtotal, (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)), diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c --- a/storage/innobase/sync/sync0sync.c 2010-12-03 17:36:44.300986571 +0900 +++ b/storage/innobase/sync/sync0sync.c 2010-12-04 16:12:48.729513564 +0900 @@ -1177,7 +1177,6 @@ case SYNC_OUTER_ANY_LATCH: case SYNC_FILE_FORMAT_TAG: case SYNC_DOUBLEWRITE: - case SYNC_SEARCH_SYS: case SYNC_SEARCH_SYS_CONF: case SYNC_TRX_LOCK_HEAP: case SYNC_KERNEL: @@ -1198,6 +1197,7 @@ ut_error; } break; + case SYNC_SEARCH_SYS: case SYNC_BUF_LRU_LIST: case SYNC_BUF_FLUSH_LIST: case SYNC_BUF_PAGE_HASH: diff -ruN a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c --- a/storage/innobase/trx/trx0trx.c 2010-12-03 17:49:11.623953784 +0900 +++ b/storage/innobase/trx/trx0trx.c 2010-12-04 16:12:48.731513275 +0900 @@ -267,8 +267,14 @@ /*=================================*/ trx_t* trx) /*!< in: transaction */ { + ulint i; + if (trx->has_search_latch) { - rw_lock_s_unlock(&btr_search_latch); + for (i = 0; i < btr_search_index_num; i++) { + if (trx->has_search_latch & ((ulint)1 << i)) { + rw_lock_s_unlock(btr_search_latch_part[i]); + } + } trx->has_search_latch = FALSE; }