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, index, 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 @@ -1992,13 +1992,13 @@
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 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
122 - rw_lock_x_unlock(&btr_search_latch);
123 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
126 if (page_zip && !dict_index_is_clust(index)
127 --- a/storage/innobase/btr/btr0sea.c
128 +++ b/storage/innobase/btr/btr0sea.c
130 UNIV_INTERN char btr_search_enabled = TRUE;
131 UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
133 +UNIV_INTERN ulint btr_search_index_num = 1;
135 /** Mutex protecting btr_search_enabled */
136 static mutex_t btr_search_enabled_mutex;
140 /* We will allocate the latch from dynamic memory to get it to the
141 same DRAM page as other hotspot semaphores */
142 -UNIV_INTERN rw_lock_t* btr_search_latch_temp;
143 +//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
145 +UNIV_INTERN rw_lock_t** btr_search_latch_part;
147 /** padding to prevent other memory update hotspots from residing on
148 the same memory cache line */
149 @@ -131,18 +135,19 @@
150 will not guarantee success. */
153 -btr_search_check_free_space_in_heap(void)
154 +btr_search_check_free_space_in_heap(
155 /*=====================================*/
161 #ifdef UNIV_SYNC_DEBUG
162 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
163 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
164 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
165 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
166 #endif /* UNIV_SYNC_DEBUG */
168 - table = btr_search_sys->hash_index;
169 + table = btr_search_get_hash_index(key);
174 if (heap->free_block == NULL) {
175 buf_block_t* block = buf_block_alloc(NULL);
177 - rw_lock_x_lock(&btr_search_latch);
178 + rw_lock_x_lock(btr_search_get_latch(key));
180 if (heap->free_block == NULL) {
181 heap->free_block = block;
183 buf_block_free(block);
186 - rw_lock_x_unlock(&btr_search_latch);
187 + rw_lock_x_unlock(btr_search_get_latch(key));
191 @@ -173,19 +178,30 @@
192 /*==================*/
193 ulint hash_size) /*!< in: hash index hash table size */
196 /* We allocate the search latch from dynamic memory:
197 see above at the global variable definition */
199 - btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
200 + //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
202 - rw_lock_create(btr_search_latch_key, &btr_search_latch,
204 + //rw_lock_create(btr_search_latch_key, &btr_search_latch,
205 + // SYNC_SEARCH_SYS);
206 mutex_create(btr_search_enabled_mutex_key,
207 &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
209 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
211 - btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
212 + /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
213 + btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
214 + btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
215 + for (i = 0; i < btr_search_index_num; i++) {
216 + btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
218 + rw_lock_create(btr_search_latch_key,
219 + btr_search_latch_part[i], SYNC_SEARCH_SYS);
221 + btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
225 /*****************************************************************//**
226 @@ -195,11 +211,22 @@
227 btr_search_sys_free(void)
228 /*=====================*/
230 - rw_lock_free(&btr_search_latch);
231 - mem_free(btr_search_latch_temp);
232 - btr_search_latch_temp = NULL;
233 - mem_heap_free(btr_search_sys->hash_index->heap);
234 - hash_table_free(btr_search_sys->hash_index);
237 + for (i = 0; i < btr_search_index_num; i++) {
238 + mem_heap_free(btr_search_sys->hash_index[i]->heap);
239 + hash_table_free(btr_search_sys->hash_index[i]);
241 + rw_lock_free(btr_search_latch_part[i]);
243 + mem_free(btr_search_latch_part[i]);
245 + mem_free(btr_search_sys->hash_index);
246 + mem_free(btr_search_latch_part);
248 + //rw_lock_free(&btr_search_latch);
249 + //mem_free(btr_search_latch_temp);
250 + //btr_search_latch_temp = NULL;
251 mem_free(btr_search_sys);
252 btr_search_sys = NULL;
255 /*====================*/
257 mutex_enter(&btr_search_enabled_mutex);
258 - rw_lock_x_lock(&btr_search_latch);
259 + btr_search_x_lock_all();
261 /* Disable access to hash index, also tell ha_insert_for_fold()
262 stop adding new nodes to hash index, but still allow updating
264 /* btr_search_enabled_mutex should guarantee this. */
265 ut_ad(!btr_search_enabled);
267 - rw_lock_x_unlock(&btr_search_latch);
268 + btr_search_x_unlock_all();
269 mutex_exit(&btr_search_enabled_mutex);
272 @@ -242,12 +269,12 @@
273 /*====================*/
275 mutex_enter(&btr_search_enabled_mutex);
276 - rw_lock_x_lock(&btr_search_latch);
277 + btr_search_x_lock_all();
279 btr_search_enabled = TRUE;
280 btr_search_fully_disabled = FALSE;
282 - rw_lock_x_unlock(&btr_search_latch);
283 + btr_search_x_unlock_all();
284 mutex_exit(&btr_search_enabled_mutex);
287 @@ -300,20 +327,21 @@
289 btr_search_info_get_ref_count(
290 /*==========================*/
291 - btr_search_t* info) /*!< in: search info. */
292 + btr_search_t* info, /*!< in: search info. */
299 #ifdef UNIV_SYNC_DEBUG
300 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
301 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
302 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
303 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
304 #endif /* UNIV_SYNC_DEBUG */
306 - rw_lock_s_lock(&btr_search_latch);
307 + rw_lock_s_lock(btr_search_get_latch(key));
308 ret = info->ref_count;
309 - rw_lock_s_unlock(&btr_search_latch);
310 + rw_lock_s_unlock(btr_search_get_latch(key));
317 #ifdef UNIV_SYNC_DEBUG
318 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
319 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
320 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
321 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
322 #endif /* UNIV_SYNC_DEBUG */
324 index = cursor->index;
328 #ifdef UNIV_SYNC_DEBUG
329 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
330 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
331 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
332 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
333 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
334 || rw_lock_own(&block->lock, RW_LOCK_EX));
335 #endif /* UNIV_SYNC_DEBUG */
338 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
339 #ifdef UNIV_SYNC_DEBUG
340 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
341 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
342 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
343 || rw_lock_own(&(block->lock), RW_LOCK_EX));
344 #endif /* UNIV_SYNC_DEBUG */
345 @@ -578,10 +606,10 @@
348 #ifdef UNIV_SYNC_DEBUG
349 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
350 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
351 #endif /* UNIV_SYNC_DEBUG */
353 - ha_insert_for_fold(btr_search_sys->hash_index, fold,
354 + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
361 #ifdef UNIV_SYNC_DEBUG
362 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
363 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
364 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
365 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
366 #endif /* UNIV_SYNC_DEBUG */
368 block = btr_cur_get_block(cursor);
371 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
373 - btr_search_check_free_space_in_heap();
374 + btr_search_check_free_space_in_heap(cursor->index->id);
377 if (cursor->flag == BTR_CUR_HASH_FAIL) {
378 @@ -633,11 +661,11 @@
379 btr_search_n_hash_fail++;
380 #endif /* UNIV_SEARCH_PERF_STAT */
382 - rw_lock_x_lock(&btr_search_latch);
383 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
385 btr_search_update_hash_ref(info, block, cursor);
387 - rw_lock_x_unlock(&btr_search_latch);
388 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
392 @@ -882,17 +910,17 @@
393 cursor->flag = BTR_CUR_HASH;
395 if (UNIV_LIKELY(!has_search_latch)) {
396 - rw_lock_s_lock(&btr_search_latch);
397 + rw_lock_s_lock(btr_search_get_latch(index_id));
399 if (UNIV_UNLIKELY(!btr_search_enabled)) {
404 - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
405 - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
406 + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
407 + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
409 - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
410 + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
412 if (UNIV_UNLIKELY(!rec)) {
418 - rw_lock_s_unlock(&btr_search_latch);
419 + rw_lock_s_unlock(btr_search_get_latch(index_id));
421 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
423 @@ -1007,7 +1035,7 @@
424 /*-------------------------------------------*/
426 if (UNIV_LIKELY(!has_search_latch)) {
427 - rw_lock_s_unlock(&btr_search_latch);
428 + rw_lock_s_unlock(btr_search_get_latch(index_id));
431 cursor->flag = BTR_CUR_HASH_FAIL;
432 @@ -1030,10 +1058,11 @@
434 btr_search_drop_page_hash_index(
435 /*============================*/
436 - buf_block_t* block) /*!< in: block containing index page,
437 + buf_block_t* block, /*!< in: block containing index page,
438 s- or x-latched, or an index page
439 for which we know that
440 block->buf_fix_count == 0 */
441 + dict_index_t* index_in)
445 @@ -1052,22 +1081,60 @@
448 #ifdef UNIV_SYNC_DEBUG
449 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
450 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
452 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
453 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
455 #endif /* UNIV_SYNC_DEBUG */
458 - rw_lock_s_lock(&btr_search_latch);
461 + rw_lock_s_lock(btr_search_get_latch(index->id));
462 + } else if (btr_search_index_num > 1) {
463 + rw_lock_t* btr_search_latch;
465 + /* FIXME: This may be optimistic implementation still. */
466 + btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
467 + if (UNIV_LIKELY(!btr_search_latch)) {
468 + if (block->is_hashed) {
473 + rw_lock_s_lock(btr_search_latch);
474 + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
475 + rw_lock_s_unlock(btr_search_latch);
478 + if (UNIV_LIKELY(!block->is_hashed)) {
479 + rw_lock_s_unlock(btr_search_latch);
482 + index = block->index;
483 + ut_a(btr_search_latch == btr_search_get_latch(index->id));
485 + /* btr_search_index_num == 1 */
486 + /* btr_search_latch is only one and able to obtain
487 + before evaluating block->is_hashed. */
488 + rw_lock_s_lock(btr_search_latch_part[0]);
489 + if (UNIV_LIKELY(!block->is_hashed)) {
490 + rw_lock_s_unlock(btr_search_latch_part[0]);
493 + index = block->index;
498 if (UNIV_LIKELY(!block->is_hashed)) {
500 - rw_lock_s_unlock(&btr_search_latch);
501 + rw_lock_s_unlock(btr_search_get_latch(index->id));
506 - table = btr_search_sys->hash_index;
507 + table = btr_search_get_hash_index(index->id);
509 #ifdef UNIV_SYNC_DEBUG
510 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
511 @@ -1077,14 +1144,14 @@
513 n_fields = block->curr_n_fields;
514 n_bytes = block->curr_n_bytes;
515 - index = block->index;
516 + ut_a(index == block->index);
517 ut_a(!dict_index_is_ibuf(index));
519 /* NOTE: The fields of block must not be accessed after
520 releasing btr_search_latch, as the index page might only
523 - rw_lock_s_unlock(&btr_search_latch);
524 + rw_lock_s_unlock(btr_search_get_latch(index->id));
526 ut_a(n_fields + n_bytes > 0);
528 @@ -1134,7 +1201,7 @@
532 - rw_lock_x_lock(&btr_search_latch);
533 + rw_lock_x_lock(btr_search_get_latch(index->id));
535 if (UNIV_UNLIKELY(!block->is_hashed)) {
536 /* Someone else has meanwhile dropped the hash index */
537 @@ -1150,7 +1217,7 @@
538 /* Someone else has meanwhile built a new hash index on the
539 page, with different parameters */
541 - rw_lock_x_unlock(&btr_search_latch);
542 + rw_lock_x_unlock(btr_search_get_latch(index->id));
546 @@ -1166,6 +1233,7 @@
548 block->is_hashed = FALSE;
550 + block->btr_search_latch = NULL;
553 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
554 @@ -1178,14 +1246,14 @@
555 "InnoDB: the hash index to a page of %s,"
556 " still %lu hash nodes remain.\n",
557 index->name, (ulong) block->n_pointers);
558 - rw_lock_x_unlock(&btr_search_latch);
559 + rw_lock_x_unlock(btr_search_get_latch(index->id));
561 btr_search_validate();
563 - rw_lock_x_unlock(&btr_search_latch);
564 + rw_lock_x_unlock(btr_search_get_latch(index->id));
566 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
567 - rw_lock_x_unlock(&btr_search_latch);
568 + rw_lock_x_unlock(btr_search_get_latch(index->id));
569 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
572 @@ -1217,9 +1285,9 @@
574 ibool released_search_latch;
576 - rw_lock_s_lock(&btr_search_latch);
577 + rw_lock_s_lock(btr_search_get_latch(index->id));
579 - table = btr_search_sys->hash_index;
580 + table = btr_search_get_hash_index(index->id);
582 for (j = 0; j < srv_buf_pool_instances; j++) {
583 buf_pool_t* buf_pool;
584 @@ -1253,7 +1321,7 @@
587 /* keeping latch order */
588 - rw_lock_s_unlock(&btr_search_latch);
589 + rw_lock_s_unlock(btr_search_get_latch(index->id));
590 released_search_latch = TRUE;
591 rw_lock_x_lock(&block->lock);
593 @@ -1305,7 +1373,7 @@
594 mem_heap_empty(heap);
597 - rw_lock_x_lock(&btr_search_latch);
598 + rw_lock_x_lock(btr_search_get_latch(index->id));
600 if (UNIV_UNLIKELY(!block->is_hashed)) {
602 @@ -1315,12 +1383,12 @@
604 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
605 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
606 - rw_lock_x_unlock(&btr_search_latch);
607 + rw_lock_x_unlock(btr_search_get_latch(index->id));
608 rw_lock_x_unlock(&block->lock);
612 - rw_lock_s_lock(&btr_search_latch);
613 + rw_lock_s_lock(btr_search_get_latch(index->id));
617 @@ -1334,6 +1402,7 @@
619 block->is_hashed = FALSE;
621 + block->btr_search_latch = NULL;
624 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
625 @@ -1346,18 +1415,18 @@
626 index->name, (ulong) block->n_pointers);
628 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
629 - rw_lock_x_unlock(&btr_search_latch);
630 + rw_lock_x_unlock(btr_search_get_latch(index->id));
631 rw_lock_x_unlock(&block->lock);
635 - rw_lock_s_lock(&btr_search_latch);
636 + rw_lock_s_lock(btr_search_get_latch(index->id));
639 } while (released_search_latch);
642 - rw_lock_s_unlock(&btr_search_latch);
643 + rw_lock_s_unlock(btr_search_get_latch(index->id));
645 if (UNIV_LIKELY_NULL(heap)) {
647 @@ -1404,7 +1473,7 @@
649 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
651 - btr_search_drop_page_hash_index(block);
652 + btr_search_drop_page_hash_index(block, NULL);
656 @@ -1446,26 +1515,26 @@
658 ut_a(!dict_index_is_ibuf(index));
660 - table = btr_search_sys->hash_index;
661 + table = btr_search_get_hash_index(index->id);
662 page = buf_block_get_frame(block);
664 #ifdef UNIV_SYNC_DEBUG
665 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
666 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
667 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
668 || rw_lock_own(&(block->lock), RW_LOCK_EX));
669 #endif /* UNIV_SYNC_DEBUG */
671 - rw_lock_s_lock(&btr_search_latch);
672 + rw_lock_s_lock(btr_search_get_latch(index->id));
674 if (block->is_hashed && ((block->curr_n_fields != n_fields)
675 || (block->curr_n_bytes != n_bytes)
676 || (block->curr_left_side != left_side))) {
678 - rw_lock_s_unlock(&btr_search_latch);
679 + rw_lock_s_unlock(btr_search_get_latch(index->id));
681 - btr_search_drop_page_hash_index(block);
682 + btr_search_drop_page_hash_index(block, index);
684 - rw_lock_s_unlock(&btr_search_latch);
685 + rw_lock_s_unlock(btr_search_get_latch(index->id));
688 n_recs = page_get_n_recs(page);
689 @@ -1559,9 +1628,9 @@
693 - btr_search_check_free_space_in_heap();
694 + btr_search_check_free_space_in_heap(index->id);
696 - rw_lock_x_lock(&btr_search_latch);
697 + rw_lock_x_lock(btr_search_get_latch(index->id));
699 if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
701 @@ -1589,6 +1658,7 @@
702 block->curr_n_bytes = n_bytes;
703 block->curr_left_side = left_side;
704 block->index = index;
705 + block->btr_search_latch = btr_search_get_latch(index->id);
707 for (i = 0; i < n_cached; i++) {
709 @@ -1596,7 +1666,7 @@
713 - rw_lock_x_unlock(&btr_search_latch);
714 + rw_lock_x_unlock(btr_search_get_latch(index->id));
718 @@ -1635,13 +1705,13 @@
719 ut_a(!(new_block->is_hashed || block->is_hashed)
720 || !dict_index_is_ibuf(index));
722 - rw_lock_s_lock(&btr_search_latch);
723 + rw_lock_s_lock(btr_search_get_latch(index->id));
725 if (new_block->is_hashed) {
727 - rw_lock_s_unlock(&btr_search_latch);
728 + rw_lock_s_unlock(btr_search_get_latch(index->id));
730 - btr_search_drop_page_hash_index(block);
731 + btr_search_drop_page_hash_index(block, index);
735 @@ -1656,7 +1726,7 @@
736 new_block->n_bytes = block->curr_n_bytes;
737 new_block->left_side = left_side;
739 - rw_lock_s_unlock(&btr_search_latch);
740 + rw_lock_s_unlock(btr_search_get_latch(index->id));
742 ut_a(n_fields + n_bytes > 0);
744 @@ -1668,7 +1738,7 @@
748 - rw_lock_s_unlock(&btr_search_latch);
749 + rw_lock_s_unlock(btr_search_get_latch(index->id));
752 /********************************************************************//**
753 @@ -1707,7 +1777,7 @@
754 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
755 ut_a(!dict_index_is_ibuf(cursor->index));
757 - table = btr_search_sys->hash_index;
758 + table = btr_search_get_hash_index(cursor->index->id);
760 index_id = cursor->index->id;
761 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
762 @@ -1716,11 +1786,11 @@
763 if (UNIV_LIKELY_NULL(heap)) {
766 - rw_lock_x_lock(&btr_search_latch);
767 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
769 ha_search_and_delete_if_found(table, fold, rec);
771 - rw_lock_x_unlock(&btr_search_latch);
772 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
775 /********************************************************************//**
776 @@ -1754,21 +1824,21 @@
777 ut_a(block->index == cursor->index);
778 ut_a(!dict_index_is_ibuf(cursor->index));
780 - rw_lock_x_lock(&btr_search_latch);
781 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
783 if ((cursor->flag == BTR_CUR_HASH)
784 && (cursor->n_fields == block->curr_n_fields)
785 && (cursor->n_bytes == block->curr_n_bytes)
786 && !block->curr_left_side) {
788 - table = btr_search_sys->hash_index;
789 + table = btr_search_get_hash_index(cursor->index->id);
791 ha_search_and_update_if_found(table, cursor->fold, rec,
792 block, page_rec_get_next(rec));
794 - rw_lock_x_unlock(&btr_search_latch);
795 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
797 - rw_lock_x_unlock(&btr_search_latch);
798 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
800 btr_search_update_hash_on_insert(cursor);
802 @@ -1803,9 +1873,9 @@
803 ulint* offsets = offsets_;
804 rec_offs_init(offsets_);
806 - table = btr_search_sys->hash_index;
807 + table = btr_search_get_hash_index(cursor->index->id);
809 - btr_search_check_free_space_in_heap();
810 + btr_search_check_free_space_in_heap(cursor->index->id);
812 rec = btr_cur_get_rec(cursor);
814 @@ -1850,7 +1920,7 @@
818 - rw_lock_x_lock(&btr_search_latch);
819 + rw_lock_x_lock(btr_search_get_latch(index_id));
823 @@ -1864,7 +1934,7 @@
827 - rw_lock_x_lock(&btr_search_latch);
828 + rw_lock_x_lock(btr_search_get_latch(index_id));
832 @@ -1882,7 +1952,7 @@
836 - rw_lock_x_lock(&btr_search_latch);
837 + rw_lock_x_lock(btr_search_get_latch(index_id));
841 @@ -1897,7 +1967,7 @@
845 - rw_lock_x_lock(&btr_search_latch);
846 + rw_lock_x_lock(btr_search_get_latch(index_id));
850 @@ -1920,7 +1990,7 @@
854 - rw_lock_x_unlock(&btr_search_latch);
855 + rw_lock_x_unlock(btr_search_get_latch(index_id));
859 @@ -1936,7 +2006,7 @@
861 ulint n_page_dumps = 0;
866 mem_heap_t* heap = NULL;
867 ulint offsets_[REC_OFFS_NORMAL_SIZE];
868 @@ -1948,23 +2018,25 @@
870 rec_offs_init(offsets_);
872 - rw_lock_x_lock(&btr_search_latch);
873 + btr_search_x_lock_all();
874 buf_pool_page_hash_x_lock_all();
876 - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
877 + for (j = 0; j < btr_search_index_num; j++) {
879 + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
881 for (i = 0; i < cell_count; i++) {
882 /* We release btr_search_latch every once in a while to
883 give other queries a chance to run. */
884 if ((i != 0) && ((i % chunk_size) == 0)) {
885 buf_pool_page_hash_x_unlock_all();
886 - rw_lock_x_unlock(&btr_search_latch);
887 + btr_search_x_unlock_all();
889 - rw_lock_x_lock(&btr_search_latch);
890 + btr_search_x_lock_all();
891 buf_pool_page_hash_x_lock_all();
894 - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
895 + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
897 for (; node != NULL; node = node->next) {
898 const buf_block_t* block
899 @@ -2073,19 +2145,21 @@
900 give other queries a chance to run. */
902 buf_pool_page_hash_x_unlock_all();
903 - rw_lock_x_unlock(&btr_search_latch);
904 + btr_search_x_unlock_all();
906 - rw_lock_x_lock(&btr_search_latch);
907 + btr_search_x_lock_all();
908 buf_pool_page_hash_x_lock_all();
911 - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
912 + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
917 + } /*for (j = 0; j < btr_search_index_num; j++)*/
919 buf_pool_page_hash_x_unlock_all();
920 - rw_lock_x_unlock(&btr_search_latch);
921 + btr_search_x_unlock_all();
922 if (UNIV_LIKELY_NULL(heap)) {
925 --- a/storage/innobase/buf/buf0buf.c
926 +++ b/storage/innobase/buf/buf0buf.c
929 block->check_index_page_at_flush = FALSE;
931 + block->btr_search_latch = NULL;
933 block->is_hashed = FALSE;
935 @@ -1414,7 +1415,7 @@
936 /* To follow the latching order, we
937 have to release btr_search_latch
938 before acquiring block->latch. */
939 - rw_lock_x_unlock(&btr_search_latch);
940 + btr_search_x_unlock_all();
941 /* When we release the search latch,
942 we must rescan all blocks, because
943 some may become hashed again. */
944 @@ -1445,11 +1446,11 @@
945 anything. block->is_hashed can only
946 be set on uncompressed file pages. */
948 - btr_search_drop_page_hash_index(block);
949 + btr_search_drop_page_hash_index(block, NULL);
951 rw_lock_x_unlock(&block->lock);
953 - rw_lock_x_lock(&btr_search_latch);
954 + btr_search_x_lock_all();
956 ut_ad(!btr_search_enabled);
958 @@ -1468,7 +1469,11 @@
959 ibool released_search_latch;
961 #ifdef UNIV_SYNC_DEBUG
962 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
965 + for (j = 0; j < btr_search_index_num; j++) {
966 + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
968 #endif /* UNIV_SYNC_DEBUG */
969 ut_ad(!btr_search_enabled);
971 @@ -2204,6 +2209,7 @@
973 block->check_index_page_at_flush = FALSE;
975 + block->btr_search_latch = NULL;
977 block->n_hash_helps = 0;
978 block->is_hashed = FALSE;
979 --- a/storage/innobase/buf/buf0lru.c
980 +++ b/storage/innobase/buf/buf0lru.c
983 mutex_exit(&buf_pool->LRU_list_mutex);
985 - rw_lock_s_lock(&btr_search_latch);
986 + btr_search_s_lock_all();
987 chunk = buf_pool->chunks;
988 for (j = buf_pool->n_chunks; j--; chunk++) {
989 buf_block_t* block = chunk->blocks;
990 @@ -572,16 +572,16 @@
994 - rw_lock_s_unlock(&btr_search_latch);
995 + btr_search_s_unlock_all();
997 rw_lock_x_lock(&block->lock);
998 - btr_search_drop_page_hash_index(block);
999 + btr_search_drop_page_hash_index(block, NULL);
1000 rw_lock_x_unlock(&block->lock);
1002 - rw_lock_s_lock(&btr_search_latch);
1003 + btr_search_s_lock_all();
1006 - rw_lock_s_unlock(&btr_search_latch);
1007 + btr_search_s_unlock_all();
1011 @@ -1744,7 +1744,7 @@
1013 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1015 - btr_search_drop_page_hash_index((buf_block_t*) bpage);
1016 + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1017 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1020 --- a/storage/innobase/dict/dict0dict.c
1021 +++ b/storage/innobase/dict/dict0dict.c
1022 @@ -1846,7 +1846,7 @@
1026 - ulint ref_count = btr_search_info_get_ref_count(info);
1027 + ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1028 if (ref_count == 0) {
1031 --- a/storage/innobase/ha/ha0ha.c
1032 +++ b/storage/innobase/ha/ha0ha.c
1035 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1036 #ifdef UNIV_SYNC_DEBUG
1037 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1038 + /* cannot identificate which btr_search_latch[i] for now */
1039 + //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1040 #endif /* UNIV_SYNC_DEBUG */
1042 #ifndef UNIV_HOTBACKUP
1043 --- a/storage/innobase/handler/ha_innodb.cc
1044 +++ b/storage/innobase/handler/ha_innodb.cc
1045 @@ -11824,6 +11824,11 @@
1046 "Disable with --skip-innodb-adaptive-hash-index.",
1047 NULL, innodb_adaptive_hash_index_update, TRUE);
1049 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1050 + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1051 + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1052 + NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
1054 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1055 PLUGIN_VAR_RQCMDARG,
1056 "Replication thread delay (ms) on the slave server if "
1057 @@ -12204,6 +12209,7 @@
1058 MYSQL_SYSVAR(use_sys_stats_table),
1059 MYSQL_SYSVAR(stats_sample_pages),
1060 MYSQL_SYSVAR(adaptive_hash_index),
1061 + MYSQL_SYSVAR(adaptive_hash_index_partitions),
1062 MYSQL_SYSVAR(stats_method),
1063 MYSQL_SYSVAR(replication_delay),
1064 MYSQL_SYSVAR(status_file),
1065 --- a/storage/innobase/include/btr0sea.h
1066 +++ b/storage/innobase/include/btr0sea.h
1069 btr_search_info_get_ref_count(
1070 /*==========================*/
1071 - btr_search_t* info); /*!< in: search info. */
1072 + btr_search_t* info, /*!< in: search info. */
1074 /*********************************************************************//**
1075 Updates the search info. */
1077 @@ -136,10 +137,11 @@
1079 btr_search_drop_page_hash_index(
1080 /*============================*/
1081 - buf_block_t* block); /*!< in: block containing index page,
1082 + buf_block_t* block, /*!< in: block containing index page,
1083 s- or x-latched, or an index page
1084 for which we know that
1085 block->buf_fix_count == 0 */
1086 + dict_index_t* index_in);
1087 /************************************************************************
1088 Drops a page hash index based on index */
1090 @@ -199,10 +201,47 @@
1091 # define btr_search_validate() TRUE
1092 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1094 +/********************************************************************//**
1095 +New functions to control split btr_search_index */
1098 +btr_search_get_hash_index(
1099 +/*======================*/
1104 +btr_search_get_latch(
1105 +/*=================*/
1110 +btr_search_x_lock_all(void);
1111 +/*========================*/
1115 +btr_search_x_unlock_all(void);
1116 +/*==========================*/
1120 +btr_search_s_lock_all(void);
1121 +/*========================*/
1125 +btr_search_s_unlock_all(void);
1126 +/*==========================*/
1129 /** Flag: has the search system been enabled?
1130 Protected by btr_search_latch and btr_search_enabled_mutex. */
1131 extern char btr_search_enabled;
1133 +extern ulint btr_search_index_num;
1135 /** Flag: whether the search system has completed its disabling process,
1136 It is set to TRUE right after buf_pool_drop_hash_index() in
1137 btr_search_disable(), indicating hash index entries are cleaned up.
1140 /** The hash index system */
1141 struct btr_search_sys_struct{
1142 - hash_table_t* hash_index; /*!< the adaptive hash index,
1143 + hash_table_t** hash_index; /*!< the adaptive hash index,
1144 mapping dtuple_fold values
1145 to rec_t pointers on index pages */
1147 @@ -290,10 +329,12 @@
1149 Bear in mind (3) and (4) when using the hash index.
1151 -extern rw_lock_t* btr_search_latch_temp;
1152 +//extern rw_lock_t* btr_search_latch_temp;
1154 +extern rw_lock_t** btr_search_latch_part;
1156 /** The latch protecting the adaptive search system */
1157 -#define btr_search_latch (*btr_search_latch_temp)
1158 +//#define btr_search_latch (*btr_search_latch_temp)
1160 #ifdef UNIV_SEARCH_PERF_STAT
1161 /** Number of successful adaptive hash index lookups */
1162 --- a/storage/innobase/include/btr0sea.ic
1163 +++ b/storage/innobase/include/btr0sea.ic
1167 #ifdef UNIV_SYNC_DEBUG
1168 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1169 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1170 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1171 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1172 #endif /* UNIV_SYNC_DEBUG */
1174 info = btr_search_get_info(index);
1177 btr_search_info_update_slow(info, cursor);
1180 +/*********************************************************************//**
1181 +New functions to control split btr_search_index */
1184 +btr_search_get_hash_index(
1185 +/*======================*/
1188 + return(btr_search_sys->hash_index[key % btr_search_index_num]);
1193 +btr_search_get_latch(
1194 +/*=================*/
1197 + return(btr_search_latch_part[key % btr_search_index_num]);
1202 +btr_search_x_lock_all(void)
1203 +/*=======================*/
1207 + for (i = 0; i < btr_search_index_num; i++) {
1208 + rw_lock_x_lock(btr_search_latch_part[i]);
1214 +btr_search_x_unlock_all(void)
1215 +/*==========================*/
1219 + for (i = 0; i < btr_search_index_num; i++) {
1220 + rw_lock_x_unlock(btr_search_latch_part[i]);
1226 +btr_search_s_lock_all(void)
1227 +/*=======================*/
1231 + for (i = 0; i < btr_search_index_num; i++) {
1232 + rw_lock_s_lock(btr_search_latch_part[i]);
1238 +btr_search_s_unlock_all(void)
1239 +/*=========================*/
1243 + for (i = 0; i < btr_search_index_num; i++) {
1244 + rw_lock_s_unlock(btr_search_latch_part[i]);
1248 --- a/storage/innobase/include/buf0buf.h
1249 +++ b/storage/innobase/include/buf0buf.h
1250 @@ -1576,7 +1576,7 @@
1251 pointers in the adaptive hash index
1252 pointing to this frame */
1253 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1254 - unsigned is_hashed:1; /*!< TRUE if hash index has
1255 + volatile unsigned is_hashed:1; /*!< TRUE if hash index has
1256 already been built on this
1257 page; note that it does not
1258 guarantee that the index is
1259 @@ -1590,6 +1590,7 @@
1260 unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1261 dict_index_t* index; /*!< Index for which the adaptive
1262 hash index has been created. */
1263 + volatile rw_lock_t* btr_search_latch;
1265 # ifdef UNIV_SYNC_DEBUG
1266 /** @name Debug fields */
1267 --- a/storage/innobase/page/page0page.c
1268 +++ b/storage/innobase/page/page0page.c
1270 const ibool is_hashed = block->is_hashed;
1273 - rw_lock_x_lock(&btr_search_latch);
1274 + rw_lock_x_lock(btr_search_get_latch(block->index->id));
1277 ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1280 #ifndef UNIV_HOTBACKUP
1282 - rw_lock_x_unlock(&btr_search_latch);
1283 + rw_lock_x_unlock(btr_search_get_latch(block->index->id));
1285 #endif /* !UNIV_HOTBACKUP */
1287 --- a/storage/innobase/page/page0zip.c
1288 +++ b/storage/innobase/page/page0zip.c
1289 @@ -4456,7 +4456,7 @@
1291 #ifndef UNIV_HOTBACKUP
1292 temp_block = buf_block_alloc(buf_pool);
1293 - btr_search_drop_page_hash_index(block);
1294 + btr_search_drop_page_hash_index(block, index);
1295 block->check_index_page_at_flush = TRUE;
1296 #else /* !UNIV_HOTBACKUP */
1297 ut_ad(block == back_block1);
1298 --- a/storage/innobase/row/row0mysql.c
1299 +++ b/storage/innobase/row/row0mysql.c
1300 @@ -2594,7 +2594,7 @@
1301 /* check adaptive hash entries */
1302 index = dict_table_get_first_index(table);
1304 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1305 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1307 fprintf(stderr, "InnoDB: Warning:"
1308 " hash index ref_count (%lu) is not zero"
1309 @@ -2955,7 +2955,7 @@
1310 table->space = space;
1311 index = dict_table_get_first_index(table);
1313 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1314 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1315 /* check adaptive hash entries */
1317 fprintf(stderr, "InnoDB: Warning:"
1318 --- a/storage/innobase/row/row0sel.c
1319 +++ b/storage/innobase/row/row0sel.c
1320 @@ -1222,7 +1222,7 @@
1321 ut_ad(plan->unique_search);
1322 ut_ad(!plan->must_get_clust);
1323 #ifdef UNIV_SYNC_DEBUG
1324 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1325 + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1326 #endif /* UNIV_SYNC_DEBUG */
1328 row_sel_open_pcur(plan, TRUE, mtr);
1329 @@ -1393,10 +1393,10 @@
1330 && !plan->must_get_clust
1331 && !plan->table->big_rows) {
1332 if (!search_latch_locked) {
1333 - rw_lock_s_lock(&btr_search_latch);
1334 + rw_lock_s_lock(btr_search_get_latch(index->id));
1336 search_latch_locked = TRUE;
1337 - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1338 + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1340 /* There is an x-latch request waiting: release the
1341 s-latch for a moment; as an s-latch here is often
1342 @@ -1405,8 +1405,8 @@
1343 from acquiring an s-latch for a long time, lowering
1344 performance significantly in multiprocessors. */
1346 - rw_lock_s_unlock(&btr_search_latch);
1347 - rw_lock_s_lock(&btr_search_latch);
1348 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1349 + rw_lock_s_lock(btr_search_get_latch(index->id));
1352 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1353 @@ -1429,7 +1429,7 @@
1356 if (search_latch_locked) {
1357 - rw_lock_s_unlock(&btr_search_latch);
1358 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1360 search_latch_locked = FALSE;
1362 @@ -2005,7 +2005,7 @@
1365 if (search_latch_locked) {
1366 - rw_lock_s_unlock(&btr_search_latch);
1367 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1369 if (UNIV_LIKELY_NULL(heap)) {
1370 mem_heap_free(heap);
1371 @@ -3408,6 +3408,8 @@
1372 /* if the returned record was locked and we did a semi-consistent
1373 read (fetch the newest committed version), then this is set to
1376 + ulint should_release;
1377 #ifdef UNIV_SEARCH_DEBUG
1379 #endif /* UNIV_SEARCH_DEBUG */
1380 @@ -3505,18 +3507,33 @@
1381 /* PHASE 0: Release a possible s-latch we are holding on the
1382 adaptive hash index latch if there is someone waiting behind */
1384 - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1385 - && trx->has_search_latch) {
1386 + should_release = 0;
1387 + for (i = 0; i < btr_search_index_num; i++) {
1388 + /* we should check all latches (fix Bug#791030) */
1389 + if (rw_lock_get_writer(btr_search_latch_part[i])
1390 + != RW_LOCK_NOT_LOCKED) {
1391 + should_release |= ((ulint)1 << i);
1395 + if (should_release) {
1397 /* There is an x-latch request on the adaptive hash index:
1398 release the s-latch to reduce starvation and wait for
1399 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1402 - rw_lock_s_unlock(&btr_search_latch);
1403 - trx->has_search_latch = FALSE;
1404 + for (i = 0; i < btr_search_index_num; i++) {
1405 + /* we should release all s-latches (fix Bug#791030) */
1406 + if (trx->has_search_latch & ((ulint)1 << i)) {
1407 + rw_lock_s_unlock(btr_search_latch_part[i]);
1408 + trx->has_search_latch &= (~((ulint)1 << i));
1412 + if (!trx->has_search_latch) {
1413 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1417 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1418 @@ -3667,9 +3684,28 @@
1419 hash index semaphore! */
1421 #ifndef UNIV_SEARCH_DEBUG
1422 - if (!trx->has_search_latch) {
1423 - rw_lock_s_lock(&btr_search_latch);
1424 - trx->has_search_latch = TRUE;
1425 + if (!(trx->has_search_latch
1426 + & ((ulint)1 << (index->id % btr_search_index_num)))) {
1427 + if (trx->has_search_latch
1428 + < ((ulint)1 << (index->id % btr_search_index_num))) {
1429 + rw_lock_s_lock(btr_search_get_latch(index->id));
1430 + trx->has_search_latch |=
1431 + ((ulint)1 << (index->id % btr_search_index_num));
1433 + /* should re-lock to obay latch-order */
1434 + for (i = 0; i < btr_search_index_num; i++) {
1435 + if (trx->has_search_latch & ((ulint)1 << i)) {
1436 + rw_lock_s_unlock(btr_search_latch_part[i]);
1439 + trx->has_search_latch |=
1440 + ((ulint)1 << (index->id % btr_search_index_num));
1441 + for (i = 0; i < btr_search_index_num; i++) {
1442 + if (trx->has_search_latch & ((ulint)1 << i)) {
1443 + rw_lock_s_lock(btr_search_latch_part[i]);
1449 switch (row_sel_try_search_shortcut_for_mysql(
1450 @@ -3730,7 +3766,11 @@
1452 trx->search_latch_timeout--;
1454 - rw_lock_s_unlock(&btr_search_latch);
1455 + for (i = 0; i < btr_search_index_num; i++) {
1456 + if (trx->has_search_latch & ((ulint)1 << i)) {
1457 + rw_lock_s_unlock(btr_search_latch_part[i]);
1460 trx->has_search_latch = FALSE;
1463 @@ -3754,7 +3794,12 @@
1464 /* PHASE 3: Open or restore index cursor position */
1466 if (trx->has_search_latch) {
1467 - rw_lock_s_unlock(&btr_search_latch);
1469 + for (i = 0; i < btr_search_index_num; i++) {
1470 + if (trx->has_search_latch & ((ulint)1 << i)) {
1471 + rw_lock_s_unlock(btr_search_latch_part[i]);
1474 trx->has_search_latch = FALSE;
1477 --- a/storage/innobase/srv/srv0srv.c
1478 +++ b/storage/innobase/srv/srv0srv.c
1479 @@ -2051,7 +2051,9 @@
1480 "-------------------------------------\n", file);
1483 - ha_print_info(file, btr_search_sys->hash_index);
1484 + for (i = 0; i < btr_search_index_num; i++) {
1485 + ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1489 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1490 @@ -2076,14 +2078,15 @@
1491 ut_total_allocated_memory,
1492 mem_pool_get_reserved(mem_comm_pool));
1493 /* Calcurate reserved memories */
1494 - if (btr_search_sys && btr_search_sys->hash_index->heap) {
1495 - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1496 + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1497 + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1499 btr_search_sys_subtotal = 0;
1500 - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1501 - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1502 + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1503 + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1506 + btr_search_sys_subtotal *= btr_search_index_num;
1508 lock_sys_subtotal = 0;
1510 @@ -2109,10 +2112,10 @@
1511 " Recovery system %lu \t(%lu + %lu)\n",
1513 (ulong) (btr_search_sys
1514 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1515 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1516 + btr_search_sys_subtotal,
1517 (ulong) (btr_search_sys
1518 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1519 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1520 (ulong) btr_search_sys_subtotal,
1522 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1523 --- a/storage/innobase/sync/sync0sync.c
1524 +++ b/storage/innobase/sync/sync0sync.c
1525 @@ -1222,7 +1222,6 @@
1526 case SYNC_OUTER_ANY_LATCH:
1527 case SYNC_FILE_FORMAT_TAG:
1528 case SYNC_DOUBLEWRITE:
1529 - case SYNC_SEARCH_SYS:
1530 case SYNC_SEARCH_SYS_CONF:
1531 case SYNC_TRX_LOCK_HEAP:
1533 @@ -1244,6 +1243,7 @@
1537 + case SYNC_SEARCH_SYS:
1538 case SYNC_BUF_LRU_LIST:
1539 case SYNC_BUF_FLUSH_LIST:
1540 case SYNC_BUF_PAGE_HASH:
1541 --- a/storage/innobase/trx/trx0trx.c
1542 +++ b/storage/innobase/trx/trx0trx.c
1543 @@ -265,8 +265,14 @@
1544 /*=================================*/
1545 trx_t* trx) /*!< in: transaction */
1549 if (trx->has_search_latch) {
1550 - rw_lock_s_unlock(&btr_search_latch);
1551 + for (i = 0; i < btr_search_index_num; i++) {
1552 + if (trx->has_search_latch & ((ulint)1 << i)) {
1553 + rw_lock_s_unlock(btr_search_latch_part[i]);
1557 trx->has_search_latch = FALSE;