1 # name : innodb_adaptive_hash_index_num.patch
2 # introduced : XtraDB on 5.5 (-13?)
3 # maintainer : Yasufumi
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 --- a/storage/innobase/btr/btr0btr.c
9 +++ b/storage/innobase/btr/btr0btr.c
14 - btr_search_drop_page_hash_index(block);
15 + btr_search_drop_page_hash_index(block, NULL);
17 header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
21 #ifndef UNIV_HOTBACKUP
22 if (UNIV_LIKELY(!recovery)) {
23 - btr_search_drop_page_hash_index(block);
24 + btr_search_drop_page_hash_index(block, index);
27 block->check_index_page_at_flush = TRUE;
29 ut_a(!page_zip || page_zip_validate(page_zip, page));
30 #endif /* UNIV_ZIP_DEBUG */
32 - btr_search_drop_page_hash_index(block);
33 + btr_search_drop_page_hash_index(block, index);
34 btr_blob_dbg_remove(page, index, "btr_page_empty");
36 /* Recreate the page: note that global data on page (possible
41 - btr_search_drop_page_hash_index(block);
42 + btr_search_drop_page_hash_index(block, index);
44 /* Make the father empty */
45 btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
50 - btr_search_drop_page_hash_index(block);
51 + btr_search_drop_page_hash_index(block, index);
53 /* Remove the page from the level list */
54 btr_level_list_remove(space, zip_size, page, mtr);
59 - btr_search_drop_page_hash_index(block);
60 + btr_search_drop_page_hash_index(block, index);
63 if (UNIV_LIKELY_NULL(merge_page_zip)) {
65 ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
67 ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
68 - btr_search_drop_page_hash_index(block);
69 + btr_search_drop_page_hash_index(block, index);
71 btr_page_get_father(index, block, mtr, &cursor);
72 father = btr_cur_get_block(&cursor);
75 page = buf_block_get_frame(block);
76 ut_a(page_is_comp(merge_page) == page_is_comp(page));
77 - btr_search_drop_page_hash_index(block);
78 + btr_search_drop_page_hash_index(block, index);
80 if (left_page_no == FIL_NULL && !page_is_leaf(page)) {
82 --- a/storage/innobase/btr/btr0cur.c
83 +++ b/storage/innobase/btr/btr0cur.c
85 #ifdef UNIV_SEARCH_PERF_STAT
88 - if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
89 + if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED
90 && latch_mode <= BTR_MODIFY_LEAF
91 && info->last_hash_succ
95 if (has_search_latch) {
96 /* Release possible search latch to obey latching order */
97 - rw_lock_s_unlock(&btr_search_latch);
98 + rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
101 /* Store the position of the tree latch we push to mtr so that we
104 if (has_search_latch) {
106 - rw_lock_s_lock(&btr_search_latch);
107 + rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
111 @@ -1971,7 +1971,7 @@
112 btr_search_update_hash_on_delete(cursor);
115 - rw_lock_x_lock(&btr_search_latch);
116 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
119 if (!(flags & BTR_KEEP_SYS_FLAG)) {
120 @@ -1985,7 +1985,7 @@
121 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
123 if (block->is_hashed) {
124 - rw_lock_x_unlock(&btr_search_latch);
125 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
128 if (page_zip && !dict_index_is_clust(index)
129 @@ -2824,7 +2824,7 @@
132 if (block->is_hashed) {
133 - rw_lock_x_lock(&btr_search_latch);
134 + rw_lock_x_lock(btr_search_get_latch(index->id));
137 page_zip = buf_block_get_page_zip(block);
138 @@ -2840,7 +2840,7 @@
141 if (block->is_hashed) {
142 - rw_lock_x_unlock(&btr_search_latch);
143 + rw_lock_x_unlock(btr_search_get_latch(index->id));
146 btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
147 @@ -2967,13 +2967,13 @@
148 == dict_table_is_comp(cursor->index->table));
150 if (block->is_hashed) {
151 - rw_lock_x_lock(&btr_search_latch);
152 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
155 btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
157 if (block->is_hashed) {
158 - rw_lock_x_unlock(&btr_search_latch);
159 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
162 btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
163 --- a/storage/innobase/btr/btr0sea.c
164 +++ b/storage/innobase/btr/btr0sea.c
166 UNIV_INTERN char btr_search_enabled = TRUE;
167 UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
169 +UNIV_INTERN ulint btr_search_index_num = 1;
171 /** Mutex protecting btr_search_enabled */
172 static mutex_t btr_search_enabled_mutex;
176 /* We will allocate the latch from dynamic memory to get it to the
177 same DRAM page as other hotspot semaphores */
178 -UNIV_INTERN rw_lock_t* btr_search_latch_temp;
179 +//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
181 +UNIV_INTERN rw_lock_t** btr_search_latch_part;
183 /** padding to prevent other memory update hotspots from residing on
184 the same memory cache line */
185 @@ -131,18 +135,19 @@
186 will not guarantee success. */
189 -btr_search_check_free_space_in_heap(void)
190 +btr_search_check_free_space_in_heap(
191 /*=====================================*/
197 #ifdef UNIV_SYNC_DEBUG
198 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
199 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
200 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
201 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
202 #endif /* UNIV_SYNC_DEBUG */
204 - table = btr_search_sys->hash_index;
205 + table = btr_search_get_hash_index(key);
210 if (heap->free_block == NULL) {
211 buf_block_t* block = buf_block_alloc(NULL);
213 - rw_lock_x_lock(&btr_search_latch);
214 + rw_lock_x_lock(btr_search_get_latch(key));
216 if (heap->free_block == NULL) {
217 heap->free_block = block;
219 buf_block_free(block);
222 - rw_lock_x_unlock(&btr_search_latch);
223 + rw_lock_x_unlock(btr_search_get_latch(key));
227 @@ -173,19 +178,30 @@
228 /*==================*/
229 ulint hash_size) /*!< in: hash index hash table size */
232 /* We allocate the search latch from dynamic memory:
233 see above at the global variable definition */
235 - btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
236 + //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
238 - rw_lock_create(btr_search_latch_key, &btr_search_latch,
240 + //rw_lock_create(btr_search_latch_key, &btr_search_latch,
241 + // SYNC_SEARCH_SYS);
242 mutex_create(btr_search_enabled_mutex_key,
243 &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
245 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
247 - btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
248 + /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
249 + btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
250 + btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
251 + for (i = 0; i < btr_search_index_num; i++) {
252 + btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
254 + rw_lock_create(btr_search_latch_key,
255 + btr_search_latch_part[i], SYNC_SEARCH_SYS);
257 + btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
261 /*****************************************************************//**
262 @@ -195,11 +211,22 @@
263 btr_search_sys_free(void)
264 /*=====================*/
266 - rw_lock_free(&btr_search_latch);
267 - mem_free(btr_search_latch_temp);
268 - btr_search_latch_temp = NULL;
269 - mem_heap_free(btr_search_sys->hash_index->heap);
270 - hash_table_free(btr_search_sys->hash_index);
273 + for (i = 0; i < btr_search_index_num; i++) {
274 + mem_heap_free(btr_search_sys->hash_index[i]->heap);
275 + hash_table_free(btr_search_sys->hash_index[i]);
277 + rw_lock_free(btr_search_latch_part[i]);
279 + mem_free(btr_search_latch_part[i]);
281 + mem_free(btr_search_sys->hash_index);
282 + mem_free(btr_search_latch_part);
284 + //rw_lock_free(&btr_search_latch);
285 + //mem_free(btr_search_latch_temp);
286 + //btr_search_latch_temp = NULL;
287 mem_free(btr_search_sys);
288 btr_search_sys = NULL;
291 /*====================*/
293 mutex_enter(&btr_search_enabled_mutex);
294 - rw_lock_x_lock(&btr_search_latch);
295 + btr_search_x_lock_all();
297 /* Disable access to hash index, also tell ha_insert_for_fold()
298 stop adding new nodes to hash index, but still allow updating
300 /* btr_search_enabled_mutex should guarantee this. */
301 ut_ad(!btr_search_enabled);
303 - rw_lock_x_unlock(&btr_search_latch);
304 + btr_search_x_unlock_all();
305 mutex_exit(&btr_search_enabled_mutex);
308 @@ -242,12 +269,12 @@
309 /*====================*/
311 mutex_enter(&btr_search_enabled_mutex);
312 - rw_lock_x_lock(&btr_search_latch);
313 + btr_search_x_lock_all();
315 btr_search_enabled = TRUE;
316 btr_search_fully_disabled = FALSE;
318 - rw_lock_x_unlock(&btr_search_latch);
319 + btr_search_x_unlock_all();
320 mutex_exit(&btr_search_enabled_mutex);
323 @@ -300,20 +327,21 @@
325 btr_search_info_get_ref_count(
326 /*==========================*/
327 - btr_search_t* info) /*!< in: search info. */
328 + btr_search_t* info, /*!< in: search info. */
335 #ifdef UNIV_SYNC_DEBUG
336 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
337 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
338 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
339 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
340 #endif /* UNIV_SYNC_DEBUG */
342 - rw_lock_s_lock(&btr_search_latch);
343 + rw_lock_s_lock(btr_search_get_latch(key));
344 ret = info->ref_count;
345 - rw_lock_s_unlock(&btr_search_latch);
346 + rw_lock_s_unlock(btr_search_get_latch(key));
353 #ifdef UNIV_SYNC_DEBUG
354 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
355 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
356 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
357 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
358 #endif /* UNIV_SYNC_DEBUG */
360 index = cursor->index;
364 #ifdef UNIV_SYNC_DEBUG
365 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
366 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
367 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
368 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
369 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
370 || rw_lock_own(&block->lock, RW_LOCK_EX));
371 #endif /* UNIV_SYNC_DEBUG */
374 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
375 #ifdef UNIV_SYNC_DEBUG
376 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
377 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
378 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
379 || rw_lock_own(&(block->lock), RW_LOCK_EX));
380 #endif /* UNIV_SYNC_DEBUG */
381 @@ -578,10 +606,10 @@
384 #ifdef UNIV_SYNC_DEBUG
385 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
386 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
387 #endif /* UNIV_SYNC_DEBUG */
389 - ha_insert_for_fold(btr_search_sys->hash_index, fold,
390 + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
397 #ifdef UNIV_SYNC_DEBUG
398 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
399 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
400 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
401 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
402 #endif /* UNIV_SYNC_DEBUG */
404 block = btr_cur_get_block(cursor);
407 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
409 - btr_search_check_free_space_in_heap();
410 + btr_search_check_free_space_in_heap(cursor->index->id);
413 if (cursor->flag == BTR_CUR_HASH_FAIL) {
414 @@ -633,11 +661,11 @@
415 btr_search_n_hash_fail++;
416 #endif /* UNIV_SEARCH_PERF_STAT */
418 - rw_lock_x_lock(&btr_search_latch);
419 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
421 btr_search_update_hash_ref(info, block, cursor);
423 - rw_lock_x_unlock(&btr_search_latch);
424 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
428 @@ -881,17 +909,17 @@
429 cursor->flag = BTR_CUR_HASH;
431 if (UNIV_LIKELY(!has_search_latch)) {
432 - rw_lock_s_lock(&btr_search_latch);
433 + rw_lock_s_lock(btr_search_get_latch(index_id));
435 if (UNIV_UNLIKELY(!btr_search_enabled)) {
440 - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
441 - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
442 + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
443 + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
445 - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
446 + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
448 if (UNIV_UNLIKELY(!rec)) {
454 - rw_lock_s_unlock(&btr_search_latch);
455 + rw_lock_s_unlock(btr_search_get_latch(index_id));
457 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
459 @@ -1006,7 +1034,7 @@
460 /*-------------------------------------------*/
462 if (UNIV_LIKELY(!has_search_latch)) {
463 - rw_lock_s_unlock(&btr_search_latch);
464 + rw_lock_s_unlock(btr_search_get_latch(index_id));
467 cursor->flag = BTR_CUR_HASH_FAIL;
468 @@ -1029,10 +1057,11 @@
470 btr_search_drop_page_hash_index(
471 /*============================*/
472 - buf_block_t* block) /*!< in: block containing index page,
473 + buf_block_t* block, /*!< in: block containing index page,
474 s- or x-latched, or an index page
475 for which we know that
476 block->buf_fix_count == 0 */
477 + dict_index_t* index_in)
481 @@ -1051,22 +1080,60 @@
484 #ifdef UNIV_SYNC_DEBUG
485 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
486 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
488 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
489 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
491 #endif /* UNIV_SYNC_DEBUG */
494 - rw_lock_s_lock(&btr_search_latch);
497 + rw_lock_s_lock(btr_search_get_latch(index->id));
498 + } else if (btr_search_index_num > 1) {
499 + rw_lock_t* btr_search_latch;
501 + /* FIXME: This may be optimistic implementation still. */
502 + btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
503 + if (UNIV_LIKELY(!btr_search_latch)) {
504 + if (block->is_hashed) {
509 + rw_lock_s_lock(btr_search_latch);
510 + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
511 + rw_lock_s_unlock(btr_search_latch);
514 + if (UNIV_LIKELY(!block->is_hashed)) {
515 + rw_lock_s_unlock(btr_search_latch);
518 + index = block->index;
519 + ut_a(btr_search_latch == btr_search_get_latch(index->id));
521 + /* btr_search_index_num == 1 */
522 + /* btr_search_latch is only one and able to obtain
523 + before evaluating block->is_hashed. */
524 + rw_lock_s_lock(btr_search_latch_part[0]);
525 + if (UNIV_LIKELY(!block->is_hashed)) {
526 + rw_lock_s_unlock(btr_search_latch_part[0]);
529 + index = block->index;
534 if (UNIV_LIKELY(!block->is_hashed)) {
536 - rw_lock_s_unlock(&btr_search_latch);
537 + rw_lock_s_unlock(btr_search_get_latch(index->id));
542 - table = btr_search_sys->hash_index;
543 + table = btr_search_get_hash_index(index->id);
545 #ifdef UNIV_SYNC_DEBUG
546 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
547 @@ -1076,14 +1143,14 @@
549 n_fields = block->curr_n_fields;
550 n_bytes = block->curr_n_bytes;
551 - index = block->index;
552 + ut_a(index == block->index);
553 ut_a(!dict_index_is_ibuf(index));
555 /* NOTE: The fields of block must not be accessed after
556 releasing btr_search_latch, as the index page might only
559 - rw_lock_s_unlock(&btr_search_latch);
560 + rw_lock_s_unlock(btr_search_get_latch(index->id));
562 ut_a(n_fields + n_bytes > 0);
564 @@ -1133,7 +1200,7 @@
568 - rw_lock_x_lock(&btr_search_latch);
569 + rw_lock_x_lock(btr_search_get_latch(index->id));
571 if (UNIV_UNLIKELY(!block->is_hashed)) {
572 /* Someone else has meanwhile dropped the hash index */
573 @@ -1149,7 +1216,7 @@
574 /* Someone else has meanwhile built a new hash index on the
575 page, with different parameters */
577 - rw_lock_x_unlock(&btr_search_latch);
578 + rw_lock_x_unlock(btr_search_get_latch(index->id));
582 @@ -1165,6 +1232,7 @@
584 block->is_hashed = FALSE;
586 + block->btr_search_latch = NULL;
589 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
590 @@ -1177,14 +1245,14 @@
591 "InnoDB: the hash index to a page of %s,"
592 " still %lu hash nodes remain.\n",
593 index->name, (ulong) block->n_pointers);
594 - rw_lock_x_unlock(&btr_search_latch);
595 + rw_lock_x_unlock(btr_search_get_latch(index->id));
597 btr_search_validate();
599 - rw_lock_x_unlock(&btr_search_latch);
600 + rw_lock_x_unlock(btr_search_get_latch(index->id));
602 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
603 - rw_lock_x_unlock(&btr_search_latch);
604 + rw_lock_x_unlock(btr_search_get_latch(index->id));
605 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
608 @@ -1216,9 +1284,9 @@
610 ibool released_search_latch;
612 - rw_lock_s_lock(&btr_search_latch);
613 + rw_lock_s_lock(btr_search_get_latch(index->id));
615 - table = btr_search_sys->hash_index;
616 + table = btr_search_get_hash_index(index->id);
618 for (j = 0; j < srv_buf_pool_instances; j++) {
619 buf_pool_t* buf_pool;
620 @@ -1252,7 +1320,7 @@
623 /* keeping latch order */
624 - rw_lock_s_unlock(&btr_search_latch);
625 + rw_lock_s_unlock(btr_search_get_latch(index->id));
626 released_search_latch = TRUE;
627 rw_lock_x_lock(&block->lock);
629 @@ -1304,7 +1372,7 @@
630 mem_heap_empty(heap);
633 - rw_lock_x_lock(&btr_search_latch);
634 + rw_lock_x_lock(btr_search_get_latch(index->id));
636 if (UNIV_UNLIKELY(!block->is_hashed)) {
638 @@ -1314,12 +1382,12 @@
640 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
641 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
642 - rw_lock_x_unlock(&btr_search_latch);
643 + rw_lock_x_unlock(btr_search_get_latch(index->id));
644 rw_lock_x_unlock(&block->lock);
648 - rw_lock_s_lock(&btr_search_latch);
649 + rw_lock_s_lock(btr_search_get_latch(index->id));
653 @@ -1333,6 +1401,7 @@
655 block->is_hashed = FALSE;
657 + block->btr_search_latch = NULL;
660 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
661 @@ -1345,18 +1414,18 @@
662 index->name, (ulong) block->n_pointers);
664 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
665 - rw_lock_x_unlock(&btr_search_latch);
666 + rw_lock_x_unlock(btr_search_get_latch(index->id));
667 rw_lock_x_unlock(&block->lock);
671 - rw_lock_s_lock(&btr_search_latch);
672 + rw_lock_s_lock(btr_search_get_latch(index->id));
675 } while (released_search_latch);
678 - rw_lock_s_unlock(&btr_search_latch);
679 + rw_lock_s_unlock(btr_search_get_latch(index->id));
681 if (UNIV_LIKELY_NULL(heap)) {
683 @@ -1403,7 +1472,7 @@
685 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
687 - btr_search_drop_page_hash_index(block);
688 + btr_search_drop_page_hash_index(block, NULL);
692 @@ -1445,26 +1514,26 @@
694 ut_a(!dict_index_is_ibuf(index));
696 - table = btr_search_sys->hash_index;
697 + table = btr_search_get_hash_index(index->id);
698 page = buf_block_get_frame(block);
700 #ifdef UNIV_SYNC_DEBUG
701 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
702 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
703 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
704 || rw_lock_own(&(block->lock), RW_LOCK_EX));
705 #endif /* UNIV_SYNC_DEBUG */
707 - rw_lock_s_lock(&btr_search_latch);
708 + rw_lock_s_lock(btr_search_get_latch(index->id));
710 if (block->is_hashed && ((block->curr_n_fields != n_fields)
711 || (block->curr_n_bytes != n_bytes)
712 || (block->curr_left_side != left_side))) {
714 - rw_lock_s_unlock(&btr_search_latch);
715 + rw_lock_s_unlock(btr_search_get_latch(index->id));
717 - btr_search_drop_page_hash_index(block);
718 + btr_search_drop_page_hash_index(block, index);
720 - rw_lock_s_unlock(&btr_search_latch);
721 + rw_lock_s_unlock(btr_search_get_latch(index->id));
724 n_recs = page_get_n_recs(page);
725 @@ -1558,9 +1627,9 @@
729 - btr_search_check_free_space_in_heap();
730 + btr_search_check_free_space_in_heap(index->id);
732 - rw_lock_x_lock(&btr_search_latch);
733 + rw_lock_x_lock(btr_search_get_latch(index->id));
735 if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
737 @@ -1588,6 +1657,7 @@
738 block->curr_n_bytes = n_bytes;
739 block->curr_left_side = left_side;
740 block->index = index;
741 + block->btr_search_latch = btr_search_get_latch(index->id);
743 for (i = 0; i < n_cached; i++) {
745 @@ -1595,7 +1665,7 @@
749 - rw_lock_x_unlock(&btr_search_latch);
750 + rw_lock_x_unlock(btr_search_get_latch(index->id));
754 @@ -1634,13 +1704,13 @@
755 ut_a(!(new_block->is_hashed || block->is_hashed)
756 || !dict_index_is_ibuf(index));
758 - rw_lock_s_lock(&btr_search_latch);
759 + rw_lock_s_lock(btr_search_get_latch(index->id));
761 if (new_block->is_hashed) {
763 - rw_lock_s_unlock(&btr_search_latch);
764 + rw_lock_s_unlock(btr_search_get_latch(index->id));
766 - btr_search_drop_page_hash_index(block);
767 + btr_search_drop_page_hash_index(block, index);
771 @@ -1655,7 +1725,7 @@
772 new_block->n_bytes = block->curr_n_bytes;
773 new_block->left_side = left_side;
775 - rw_lock_s_unlock(&btr_search_latch);
776 + rw_lock_s_unlock(btr_search_get_latch(index->id));
778 ut_a(n_fields + n_bytes > 0);
780 @@ -1667,7 +1737,7 @@
784 - rw_lock_s_unlock(&btr_search_latch);
785 + rw_lock_s_unlock(btr_search_get_latch(index->id));
788 /********************************************************************//**
789 @@ -1706,7 +1776,7 @@
790 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
791 ut_a(!dict_index_is_ibuf(cursor->index));
793 - table = btr_search_sys->hash_index;
794 + table = btr_search_get_hash_index(cursor->index->id);
796 index_id = cursor->index->id;
797 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
798 @@ -1715,11 +1785,11 @@
799 if (UNIV_LIKELY_NULL(heap)) {
802 - rw_lock_x_lock(&btr_search_latch);
803 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
805 ha_search_and_delete_if_found(table, fold, rec);
807 - rw_lock_x_unlock(&btr_search_latch);
808 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
811 /********************************************************************//**
812 @@ -1753,21 +1823,21 @@
813 ut_a(block->index == cursor->index);
814 ut_a(!dict_index_is_ibuf(cursor->index));
816 - rw_lock_x_lock(&btr_search_latch);
817 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
819 if ((cursor->flag == BTR_CUR_HASH)
820 && (cursor->n_fields == block->curr_n_fields)
821 && (cursor->n_bytes == block->curr_n_bytes)
822 && !block->curr_left_side) {
824 - table = btr_search_sys->hash_index;
825 + table = btr_search_get_hash_index(cursor->index->id);
827 ha_search_and_update_if_found(table, cursor->fold, rec,
828 block, page_rec_get_next(rec));
830 - rw_lock_x_unlock(&btr_search_latch);
831 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
833 - rw_lock_x_unlock(&btr_search_latch);
834 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
836 btr_search_update_hash_on_insert(cursor);
838 @@ -1802,9 +1872,9 @@
839 ulint* offsets = offsets_;
840 rec_offs_init(offsets_);
842 - table = btr_search_sys->hash_index;
843 + table = btr_search_get_hash_index(cursor->index->id);
845 - btr_search_check_free_space_in_heap();
846 + btr_search_check_free_space_in_heap(cursor->index->id);
848 rec = btr_cur_get_rec(cursor);
850 @@ -1849,7 +1919,7 @@
854 - rw_lock_x_lock(&btr_search_latch);
855 + rw_lock_x_lock(btr_search_get_latch(index_id));
859 @@ -1863,7 +1933,7 @@
863 - rw_lock_x_lock(&btr_search_latch);
864 + rw_lock_x_lock(btr_search_get_latch(index_id));
868 @@ -1881,7 +1951,7 @@
872 - rw_lock_x_lock(&btr_search_latch);
873 + rw_lock_x_lock(btr_search_get_latch(index_id));
877 @@ -1896,7 +1966,7 @@
881 - rw_lock_x_lock(&btr_search_latch);
882 + rw_lock_x_lock(btr_search_get_latch(index_id));
886 @@ -1919,7 +1989,7 @@
890 - rw_lock_x_unlock(&btr_search_latch);
891 + rw_lock_x_unlock(btr_search_get_latch(index_id));
895 @@ -1935,7 +2005,7 @@
897 ulint n_page_dumps = 0;
902 mem_heap_t* heap = NULL;
903 ulint offsets_[REC_OFFS_NORMAL_SIZE];
904 @@ -1947,23 +2017,25 @@
906 rec_offs_init(offsets_);
908 - rw_lock_x_lock(&btr_search_latch);
909 + btr_search_x_lock_all();
910 buf_pool_page_hash_x_lock_all();
912 - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
913 + for (j = 0; j < btr_search_index_num; j++) {
915 + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
917 for (i = 0; i < cell_count; i++) {
918 /* We release btr_search_latch every once in a while to
919 give other queries a chance to run. */
920 if ((i != 0) && ((i % chunk_size) == 0)) {
921 buf_pool_page_hash_x_unlock_all();
922 - rw_lock_x_unlock(&btr_search_latch);
923 + btr_search_x_unlock_all();
925 - rw_lock_x_lock(&btr_search_latch);
926 + btr_search_x_lock_all();
927 buf_pool_page_hash_x_lock_all();
930 - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
931 + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
933 for (; node != NULL; node = node->next) {
934 const buf_block_t* block
935 @@ -2072,19 +2144,21 @@
936 give other queries a chance to run. */
938 buf_pool_page_hash_x_unlock_all();
939 - rw_lock_x_unlock(&btr_search_latch);
940 + btr_search_x_unlock_all();
942 - rw_lock_x_lock(&btr_search_latch);
943 + btr_search_x_lock_all();
944 buf_pool_page_hash_x_lock_all();
947 - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
948 + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
953 + } /*for (j = 0; j < btr_search_index_num; j++)*/
955 buf_pool_page_hash_x_unlock_all();
956 - rw_lock_x_unlock(&btr_search_latch);
957 + btr_search_x_unlock_all();
958 if (UNIV_LIKELY_NULL(heap)) {
961 --- a/storage/innobase/buf/buf0buf.c
962 +++ b/storage/innobase/buf/buf0buf.c
965 block->check_index_page_at_flush = FALSE;
967 + block->btr_search_latch = NULL;
969 block->is_hashed = FALSE;
971 @@ -1413,7 +1414,7 @@
972 /* To follow the latching order, we
973 have to release btr_search_latch
974 before acquiring block->latch. */
975 - rw_lock_x_unlock(&btr_search_latch);
976 + btr_search_x_unlock_all();
977 /* When we release the search latch,
978 we must rescan all blocks, because
979 some may become hashed again. */
980 @@ -1444,11 +1445,11 @@
981 anything. block->is_hashed can only
982 be set on uncompressed file pages. */
984 - btr_search_drop_page_hash_index(block);
985 + btr_search_drop_page_hash_index(block, NULL);
987 rw_lock_x_unlock(&block->lock);
989 - rw_lock_x_lock(&btr_search_latch);
990 + btr_search_x_lock_all();
992 ut_ad(!btr_search_enabled);
994 @@ -1467,7 +1468,11 @@
995 ibool released_search_latch;
997 #ifdef UNIV_SYNC_DEBUG
998 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1001 + for (j = 0; j < btr_search_index_num; j++) {
1002 + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
1004 #endif /* UNIV_SYNC_DEBUG */
1005 ut_ad(!btr_search_enabled);
1007 @@ -2203,6 +2208,7 @@
1009 block->check_index_page_at_flush = FALSE;
1010 block->index = NULL;
1011 + block->btr_search_latch = NULL;
1013 block->n_hash_helps = 0;
1014 block->is_hashed = FALSE;
1015 --- a/storage/innobase/buf/buf0lru.c
1016 +++ b/storage/innobase/buf/buf0lru.c
1019 mutex_exit(&buf_pool->LRU_list_mutex);
1021 - rw_lock_s_lock(&btr_search_latch);
1022 + btr_search_s_lock_all();
1023 chunk = buf_pool->chunks;
1024 for (j = buf_pool->n_chunks; j--; chunk++) {
1025 buf_block_t* block = chunk->blocks;
1026 @@ -572,16 +572,16 @@
1030 - rw_lock_s_unlock(&btr_search_latch);
1031 + btr_search_s_unlock_all();
1033 rw_lock_x_lock(&block->lock);
1034 - btr_search_drop_page_hash_index(block);
1035 + btr_search_drop_page_hash_index(block, NULL);
1036 rw_lock_x_unlock(&block->lock);
1038 - rw_lock_s_lock(&btr_search_latch);
1039 + btr_search_s_lock_all();
1042 - rw_lock_s_unlock(&btr_search_latch);
1043 + btr_search_s_unlock_all();
1047 @@ -1744,7 +1744,7 @@
1049 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1051 - btr_search_drop_page_hash_index((buf_block_t*) bpage);
1052 + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1053 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1056 --- a/storage/innobase/dict/dict0dict.c
1057 +++ b/storage/innobase/dict/dict0dict.c
1058 @@ -1845,7 +1845,7 @@
1062 - ulint ref_count = btr_search_info_get_ref_count(info);
1063 + ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1064 if (ref_count == 0) {
1067 --- a/storage/innobase/ha/ha0ha.c
1068 +++ b/storage/innobase/ha/ha0ha.c
1071 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1072 #ifdef UNIV_SYNC_DEBUG
1073 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1074 + /* cannot identificate which btr_search_latch[i] for now */
1075 + //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1076 #endif /* UNIV_SYNC_DEBUG */
1078 #ifndef UNIV_HOTBACKUP
1079 --- a/storage/innobase/handler/ha_innodb.cc
1080 +++ b/storage/innobase/handler/ha_innodb.cc
1081 @@ -11718,6 +11718,11 @@
1082 "Disable with --skip-innodb-adaptive-hash-index.",
1083 NULL, innodb_adaptive_hash_index_update, TRUE);
1085 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1086 + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1087 + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1088 + NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
1090 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1091 PLUGIN_VAR_RQCMDARG,
1092 "Replication thread delay (ms) on the slave server if "
1093 @@ -12085,6 +12090,7 @@
1094 MYSQL_SYSVAR(use_sys_stats_table),
1095 MYSQL_SYSVAR(stats_sample_pages),
1096 MYSQL_SYSVAR(adaptive_hash_index),
1097 + MYSQL_SYSVAR(adaptive_hash_index_partitions),
1098 MYSQL_SYSVAR(stats_method),
1099 MYSQL_SYSVAR(replication_delay),
1100 MYSQL_SYSVAR(status_file),
1101 --- a/storage/innobase/include/btr0sea.h
1102 +++ b/storage/innobase/include/btr0sea.h
1105 btr_search_info_get_ref_count(
1106 /*==========================*/
1107 - btr_search_t* info); /*!< in: search info. */
1108 + btr_search_t* info, /*!< in: search info. */
1110 /*********************************************************************//**
1111 Updates the search info. */
1113 @@ -136,10 +137,11 @@
1115 btr_search_drop_page_hash_index(
1116 /*============================*/
1117 - buf_block_t* block); /*!< in: block containing index page,
1118 + buf_block_t* block, /*!< in: block containing index page,
1119 s- or x-latched, or an index page
1120 for which we know that
1121 block->buf_fix_count == 0 */
1122 + dict_index_t* index_in);
1123 /************************************************************************
1124 Drops a page hash index based on index */
1126 @@ -199,10 +201,47 @@
1127 # define btr_search_validate() TRUE
1128 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1130 +/********************************************************************//**
1131 +New functions to control split btr_search_index */
1134 +btr_search_get_hash_index(
1135 +/*======================*/
1140 +btr_search_get_latch(
1141 +/*=================*/
1146 +btr_search_x_lock_all(void);
1147 +/*========================*/
1151 +btr_search_x_unlock_all(void);
1152 +/*==========================*/
1156 +btr_search_s_lock_all(void);
1157 +/*========================*/
1161 +btr_search_s_unlock_all(void);
1162 +/*==========================*/
1165 /** Flag: has the search system been enabled?
1166 Protected by btr_search_latch and btr_search_enabled_mutex. */
1167 extern char btr_search_enabled;
1169 +extern ulint btr_search_index_num;
1171 /** Flag: whether the search system has completed its disabling process,
1172 It is set to TRUE right after buf_pool_drop_hash_index() in
1173 btr_search_disable(), indicating hash index entries are cleaned up.
1176 /** The hash index system */
1177 struct btr_search_sys_struct{
1178 - hash_table_t* hash_index; /*!< the adaptive hash index,
1179 + hash_table_t** hash_index; /*!< the adaptive hash index,
1180 mapping dtuple_fold values
1181 to rec_t pointers on index pages */
1183 @@ -290,10 +329,12 @@
1185 Bear in mind (3) and (4) when using the hash index.
1187 -extern rw_lock_t* btr_search_latch_temp;
1188 +//extern rw_lock_t* btr_search_latch_temp;
1190 +extern rw_lock_t** btr_search_latch_part;
1192 /** The latch protecting the adaptive search system */
1193 -#define btr_search_latch (*btr_search_latch_temp)
1194 +//#define btr_search_latch (*btr_search_latch_temp)
1196 #ifdef UNIV_SEARCH_PERF_STAT
1197 /** Number of successful adaptive hash index lookups */
1198 --- a/storage/innobase/include/btr0sea.ic
1199 +++ b/storage/innobase/include/btr0sea.ic
1203 #ifdef UNIV_SYNC_DEBUG
1204 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1205 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1206 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1207 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1208 #endif /* UNIV_SYNC_DEBUG */
1210 info = btr_search_get_info(index);
1213 btr_search_info_update_slow(info, cursor);
1216 +/*********************************************************************//**
1217 +New functions to control split btr_search_index */
1220 +btr_search_get_hash_index(
1221 +/*======================*/
1224 + return(btr_search_sys->hash_index[key % btr_search_index_num]);
1229 +btr_search_get_latch(
1230 +/*=================*/
1233 + return(btr_search_latch_part[key % btr_search_index_num]);
1238 +btr_search_x_lock_all(void)
1239 +/*=======================*/
1243 + for (i = 0; i < btr_search_index_num; i++) {
1244 + rw_lock_x_lock(btr_search_latch_part[i]);
1250 +btr_search_x_unlock_all(void)
1251 +/*==========================*/
1255 + for (i = 0; i < btr_search_index_num; i++) {
1256 + rw_lock_x_unlock(btr_search_latch_part[i]);
1262 +btr_search_s_lock_all(void)
1263 +/*=======================*/
1267 + for (i = 0; i < btr_search_index_num; i++) {
1268 + rw_lock_s_lock(btr_search_latch_part[i]);
1274 +btr_search_s_unlock_all(void)
1275 +/*=========================*/
1279 + for (i = 0; i < btr_search_index_num; i++) {
1280 + rw_lock_s_unlock(btr_search_latch_part[i]);
1284 --- a/storage/innobase/include/buf0buf.h
1285 +++ b/storage/innobase/include/buf0buf.h
1286 @@ -1585,7 +1585,7 @@
1287 pointers in the adaptive hash index
1288 pointing to this frame */
1289 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1290 - unsigned is_hashed:1; /*!< TRUE if hash index has
1291 + volatile unsigned is_hashed:1; /*!< TRUE if hash index has
1292 already been built on this
1293 page; note that it does not
1294 guarantee that the index is
1295 @@ -1599,6 +1599,7 @@
1296 unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1297 dict_index_t* index; /*!< Index for which the adaptive
1298 hash index has been created. */
1299 + volatile rw_lock_t* btr_search_latch;
1301 # ifdef UNIV_SYNC_DEBUG
1302 /** @name Debug fields */
1303 --- a/storage/innobase/include/row0upd.ic
1304 +++ b/storage/innobase/include/row0upd.ic
1306 ut_ad(dict_index_is_clust(index));
1307 ut_ad(rec_offs_validate(rec, index, offsets));
1308 #ifdef UNIV_SYNC_DEBUG
1309 - if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
1310 + if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) {
1311 ut_ad(!buf_block_align(rec)->is_hashed);
1313 #endif /* UNIV_SYNC_DEBUG */
1314 --- a/storage/innobase/page/page0page.c
1315 +++ b/storage/innobase/page/page0page.c
1317 const ibool is_hashed = block->is_hashed;
1320 - rw_lock_x_lock(&btr_search_latch);
1321 + rw_lock_x_lock(btr_search_get_latch(block->index->id));
1324 ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1327 #ifndef UNIV_HOTBACKUP
1329 - rw_lock_x_unlock(&btr_search_latch);
1330 + rw_lock_x_unlock(btr_search_get_latch(block->index->id));
1332 #endif /* !UNIV_HOTBACKUP */
1334 --- a/storage/innobase/page/page0zip.c
1335 +++ b/storage/innobase/page/page0zip.c
1336 @@ -4456,7 +4456,7 @@
1338 #ifndef UNIV_HOTBACKUP
1339 temp_block = buf_block_alloc(buf_pool);
1340 - btr_search_drop_page_hash_index(block);
1341 + btr_search_drop_page_hash_index(block, index);
1342 block->check_index_page_at_flush = TRUE;
1343 #else /* !UNIV_HOTBACKUP */
1344 ut_ad(block == back_block1);
1345 --- a/storage/innobase/row/row0mysql.c
1346 +++ b/storage/innobase/row/row0mysql.c
1347 @@ -2593,7 +2593,7 @@
1348 /* check adaptive hash entries */
1349 index = dict_table_get_first_index(table);
1351 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1352 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1354 fprintf(stderr, "InnoDB: Warning:"
1355 " hash index ref_count (%lu) is not zero"
1356 @@ -2954,7 +2954,7 @@
1357 table->space = space;
1358 index = dict_table_get_first_index(table);
1360 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1361 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1362 /* check adaptive hash entries */
1364 fprintf(stderr, "InnoDB: Warning:"
1365 --- a/storage/innobase/row/row0sel.c
1366 +++ b/storage/innobase/row/row0sel.c
1367 @@ -1211,7 +1211,7 @@
1368 ut_ad(plan->unique_search);
1369 ut_ad(!plan->must_get_clust);
1370 #ifdef UNIV_SYNC_DEBUG
1371 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1372 + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1373 #endif /* UNIV_SYNC_DEBUG */
1375 row_sel_open_pcur(plan, TRUE, mtr);
1376 @@ -1382,10 +1382,10 @@
1377 && !plan->must_get_clust
1378 && !plan->table->big_rows) {
1379 if (!search_latch_locked) {
1380 - rw_lock_s_lock(&btr_search_latch);
1381 + rw_lock_s_lock(btr_search_get_latch(index->id));
1383 search_latch_locked = TRUE;
1384 - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1385 + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1387 /* There is an x-latch request waiting: release the
1388 s-latch for a moment; as an s-latch here is often
1389 @@ -1394,8 +1394,8 @@
1390 from acquiring an s-latch for a long time, lowering
1391 performance significantly in multiprocessors. */
1393 - rw_lock_s_unlock(&btr_search_latch);
1394 - rw_lock_s_lock(&btr_search_latch);
1395 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1396 + rw_lock_s_lock(btr_search_get_latch(index->id));
1399 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1400 @@ -1418,7 +1418,7 @@
1403 if (search_latch_locked) {
1404 - rw_lock_s_unlock(&btr_search_latch);
1405 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1407 search_latch_locked = FALSE;
1409 @@ -1994,7 +1994,7 @@
1412 if (search_latch_locked) {
1413 - rw_lock_s_unlock(&btr_search_latch);
1414 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1416 if (UNIV_LIKELY_NULL(heap)) {
1417 mem_heap_free(heap);
1418 @@ -3357,6 +3357,8 @@
1419 /* if the returned record was locked and we did a semi-consistent
1420 read (fetch the newest committed version), then this is set to
1423 + ulint should_release;
1424 #ifdef UNIV_SEARCH_DEBUG
1426 #endif /* UNIV_SEARCH_DEBUG */
1427 @@ -3447,18 +3449,33 @@
1428 /* PHASE 0: Release a possible s-latch we are holding on the
1429 adaptive hash index latch if there is someone waiting behind */
1431 - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1432 - && trx->has_search_latch) {
1433 + should_release = 0;
1434 + for (i = 0; i < btr_search_index_num; i++) {
1435 + /* we should check all latches (fix Bug#791030) */
1436 + if (rw_lock_get_writer(btr_search_latch_part[i])
1437 + != RW_LOCK_NOT_LOCKED) {
1438 + should_release |= ((ulint)1 << i);
1442 + if (should_release) {
1444 /* There is an x-latch request on the adaptive hash index:
1445 release the s-latch to reduce starvation and wait for
1446 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1449 - rw_lock_s_unlock(&btr_search_latch);
1450 - trx->has_search_latch = FALSE;
1451 + for (i = 0; i < btr_search_index_num; i++) {
1452 + /* we should release all s-latches (fix Bug#791030) */
1453 + if (trx->has_search_latch & ((ulint)1 << i)) {
1454 + rw_lock_s_unlock(btr_search_latch_part[i]);
1455 + trx->has_search_latch &= (~((ulint)1 << i));
1459 + if (!trx->has_search_latch) {
1460 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1464 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1465 @@ -3609,9 +3626,28 @@
1466 hash index semaphore! */
1468 #ifndef UNIV_SEARCH_DEBUG
1469 - if (!trx->has_search_latch) {
1470 - rw_lock_s_lock(&btr_search_latch);
1471 - trx->has_search_latch = TRUE;
1472 + if (!(trx->has_search_latch
1473 + & ((ulint)1 << (index->id % btr_search_index_num)))) {
1474 + if (trx->has_search_latch
1475 + < ((ulint)1 << (index->id % btr_search_index_num))) {
1476 + rw_lock_s_lock(btr_search_get_latch(index->id));
1477 + trx->has_search_latch |=
1478 + ((ulint)1 << (index->id % btr_search_index_num));
1480 + /* should re-lock to obay latch-order */
1481 + for (i = 0; i < btr_search_index_num; i++) {
1482 + if (trx->has_search_latch & ((ulint)1 << i)) {
1483 + rw_lock_s_unlock(btr_search_latch_part[i]);
1486 + trx->has_search_latch |=
1487 + ((ulint)1 << (index->id % btr_search_index_num));
1488 + for (i = 0; i < btr_search_index_num; i++) {
1489 + if (trx->has_search_latch & ((ulint)1 << i)) {
1490 + rw_lock_s_lock(btr_search_latch_part[i]);
1496 switch (row_sel_try_search_shortcut_for_mysql(
1497 @@ -3672,7 +3708,11 @@
1499 trx->search_latch_timeout--;
1501 - rw_lock_s_unlock(&btr_search_latch);
1502 + for (i = 0; i < btr_search_index_num; i++) {
1503 + if (trx->has_search_latch & ((ulint)1 << i)) {
1504 + rw_lock_s_unlock(btr_search_latch_part[i]);
1507 trx->has_search_latch = FALSE;
1510 @@ -3696,7 +3736,12 @@
1511 /* PHASE 3: Open or restore index cursor position */
1513 if (trx->has_search_latch) {
1514 - rw_lock_s_unlock(&btr_search_latch);
1516 + for (i = 0; i < btr_search_index_num; i++) {
1517 + if (trx->has_search_latch & ((ulint)1 << i)) {
1518 + rw_lock_s_unlock(btr_search_latch_part[i]);
1521 trx->has_search_latch = FALSE;
1524 --- a/storage/innobase/srv/srv0srv.c
1525 +++ b/storage/innobase/srv/srv0srv.c
1526 @@ -2045,7 +2045,9 @@
1527 "-------------------------------------\n", file);
1530 - ha_print_info(file, btr_search_sys->hash_index);
1531 + for (i = 0; i < btr_search_index_num; i++) {
1532 + ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1536 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1537 @@ -2070,14 +2072,15 @@
1538 ut_total_allocated_memory,
1539 mem_pool_get_reserved(mem_comm_pool));
1540 /* Calcurate reserved memories */
1541 - if (btr_search_sys && btr_search_sys->hash_index->heap) {
1542 - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1543 + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1544 + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1546 btr_search_sys_subtotal = 0;
1547 - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1548 - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1549 + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1550 + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1553 + btr_search_sys_subtotal *= btr_search_index_num;
1555 lock_sys_subtotal = 0;
1557 @@ -2103,10 +2106,10 @@
1558 " Recovery system %lu \t(%lu + %lu)\n",
1560 (ulong) (btr_search_sys
1561 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1562 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1563 + btr_search_sys_subtotal,
1564 (ulong) (btr_search_sys
1565 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1566 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1567 (ulong) btr_search_sys_subtotal,
1569 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1570 --- a/storage/innobase/sync/sync0sync.c
1571 +++ b/storage/innobase/sync/sync0sync.c
1572 @@ -1228,7 +1228,6 @@
1573 case SYNC_OUTER_ANY_LATCH:
1574 case SYNC_FILE_FORMAT_TAG:
1575 case SYNC_DOUBLEWRITE:
1576 - case SYNC_SEARCH_SYS:
1577 case SYNC_SEARCH_SYS_CONF:
1578 case SYNC_TRX_LOCK_HEAP:
1580 @@ -1249,6 +1248,7 @@
1584 + case SYNC_SEARCH_SYS:
1585 case SYNC_BUF_LRU_LIST:
1586 case SYNC_BUF_FLUSH_LIST:
1587 case SYNC_BUF_PAGE_HASH:
1588 --- a/storage/innobase/trx/trx0trx.c
1589 +++ b/storage/innobase/trx/trx0trx.c
1590 @@ -265,8 +265,14 @@
1591 /*=================================*/
1592 trx_t* trx) /*!< in: transaction */
1596 if (trx->has_search_latch) {
1597 - rw_lock_s_unlock(&btr_search_latch);
1598 + for (i = 0; i < btr_search_index_num; i++) {
1599 + if (trx->has_search_latch & ((ulint)1 << i)) {
1600 + rw_lock_s_unlock(btr_search_latch_part[i]);
1604 trx->has_search_latch = FALSE;