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 @@ -1977,13 +1977,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 Protected by btr_search_latch. */
131 UNIV_INTERN char btr_search_enabled = TRUE;
133 +UNIV_INTERN ulint btr_search_index_num = 1;
135 #ifdef UNIV_PFS_MUTEX
136 /* Key to register btr_search_enabled_mutex with performance schema */
137 UNIV_INTERN mysql_pfs_key_t btr_search_enabled_mutex_key;
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 @@ -127,18 +131,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 @@ -169,17 +174,28 @@
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);
207 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
209 - btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
210 + /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
211 + btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
212 + btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
213 + for (i = 0; i < btr_search_index_num; i++) {
214 + btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
216 + rw_lock_create(btr_search_latch_key,
217 + btr_search_latch_part[i], SYNC_SEARCH_SYS);
219 + btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
223 /*****************************************************************//**
224 @@ -189,11 +205,22 @@
225 btr_search_sys_free(void)
226 /*=====================*/
228 - rw_lock_free(&btr_search_latch);
229 - mem_free(btr_search_latch_temp);
230 - btr_search_latch_temp = NULL;
231 - mem_heap_free(btr_search_sys->hash_index->heap);
232 - hash_table_free(btr_search_sys->hash_index);
235 + for (i = 0; i < btr_search_index_num; i++) {
236 + mem_heap_free(btr_search_sys->hash_index[i]->heap);
237 + hash_table_free(btr_search_sys->hash_index[i]);
239 + rw_lock_free(btr_search_latch_part[i]);
241 + mem_free(btr_search_latch_part[i]);
243 + mem_free(btr_search_sys->hash_index);
244 + mem_free(btr_search_latch_part);
246 + //rw_lock_free(&btr_search_latch);
247 + //mem_free(btr_search_latch_temp);
248 + //btr_search_latch_temp = NULL;
249 mem_free(btr_search_sys);
250 btr_search_sys = NULL;
253 /*====================*/
258 mutex_enter(&dict_sys->mutex);
259 - rw_lock_x_lock(&btr_search_latch);
260 + btr_search_x_lock_all();
262 btr_search_enabled = FALSE;
264 @@ -232,10 +260,12 @@
265 buf_pool_clear_hash_index();
267 /* Clear the adaptive hash index. */
268 - hash_table_clear(btr_search_sys->hash_index);
269 - mem_heap_empty(btr_search_sys->hash_index->heap);
270 + for (i = 0; i < btr_search_index_num; i++) {
271 + hash_table_clear(btr_search_sys->hash_index[i]);
272 + mem_heap_empty(btr_search_sys->hash_index[i]->heap);
275 - rw_lock_x_unlock(&btr_search_latch);
276 + btr_search_x_unlock_all();
279 /********************************************************************//**
280 @@ -245,11 +275,11 @@
281 btr_search_enable(void)
282 /*====================*/
284 - rw_lock_x_lock(&btr_search_latch);
285 + btr_search_x_lock_all();
287 btr_search_enabled = TRUE;
289 - rw_lock_x_unlock(&btr_search_latch);
290 + btr_search_x_unlock_all();
293 /*****************************************************************//**
294 @@ -301,20 +331,21 @@
296 btr_search_info_get_ref_count(
297 /*==========================*/
298 - btr_search_t* info) /*!< in: search info. */
299 + btr_search_t* info, /*!< in: search info. */
306 #ifdef UNIV_SYNC_DEBUG
307 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
308 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
309 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
310 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
311 #endif /* UNIV_SYNC_DEBUG */
313 - rw_lock_s_lock(&btr_search_latch);
314 + rw_lock_s_lock(btr_search_get_latch(key));
315 ret = info->ref_count;
316 - rw_lock_s_unlock(&btr_search_latch);
317 + rw_lock_s_unlock(btr_search_get_latch(key));
324 #ifdef UNIV_SYNC_DEBUG
325 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
326 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
327 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
328 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
329 #endif /* UNIV_SYNC_DEBUG */
331 index = cursor->index;
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(cursor->index->id), RW_LOCK_SHARED));
339 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
340 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
341 || rw_lock_own(&block->lock, RW_LOCK_EX));
342 #endif /* UNIV_SYNC_DEBUG */
345 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
346 #ifdef UNIV_SYNC_DEBUG
347 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
348 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
349 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
350 || rw_lock_own(&(block->lock), RW_LOCK_EX));
351 #endif /* UNIV_SYNC_DEBUG */
352 @@ -580,10 +611,10 @@
355 #ifdef UNIV_SYNC_DEBUG
356 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
357 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
358 #endif /* UNIV_SYNC_DEBUG */
360 - ha_insert_for_fold(btr_search_sys->hash_index, fold,
361 + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
368 #ifdef UNIV_SYNC_DEBUG
369 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
370 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
371 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
372 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
373 #endif /* UNIV_SYNC_DEBUG */
375 block = btr_cur_get_block(cursor);
378 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
380 - btr_search_check_free_space_in_heap();
381 + btr_search_check_free_space_in_heap(cursor->index->id);
384 if (cursor->flag == BTR_CUR_HASH_FAIL) {
385 @@ -635,11 +666,11 @@
386 btr_search_n_hash_fail++;
387 #endif /* UNIV_SEARCH_PERF_STAT */
389 - rw_lock_x_lock(&btr_search_latch);
390 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
392 btr_search_update_hash_ref(info, block, cursor);
394 - rw_lock_x_unlock(&btr_search_latch);
395 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
399 @@ -884,17 +915,17 @@
400 cursor->flag = BTR_CUR_HASH;
402 if (UNIV_LIKELY(!has_search_latch)) {
403 - rw_lock_s_lock(&btr_search_latch);
404 + rw_lock_s_lock(btr_search_get_latch(index_id));
406 if (UNIV_UNLIKELY(!btr_search_enabled)) {
411 - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
412 - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
413 + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
414 + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
416 - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
417 + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
419 if (UNIV_UNLIKELY(!rec)) {
425 - rw_lock_s_unlock(&btr_search_latch);
426 + rw_lock_s_unlock(btr_search_get_latch(index_id));
428 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
430 @@ -1009,7 +1040,7 @@
431 /*-------------------------------------------*/
433 if (UNIV_LIKELY(!has_search_latch)) {
434 - rw_lock_s_unlock(&btr_search_latch);
435 + rw_lock_s_unlock(btr_search_get_latch(index_id));
438 cursor->flag = BTR_CUR_HASH_FAIL;
439 @@ -1032,10 +1063,11 @@
441 btr_search_drop_page_hash_index(
442 /*============================*/
443 - buf_block_t* block) /*!< in: block containing index page,
444 + buf_block_t* block, /*!< in: block containing index page,
445 s- or x-latched, or an index page
446 for which we know that
447 block->buf_fix_count == 0 */
448 + dict_index_t* index_in)
452 @@ -1054,23 +1086,55 @@
455 #ifdef UNIV_SYNC_DEBUG
456 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
457 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
459 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
460 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
462 #endif /* UNIV_SYNC_DEBUG */
465 - rw_lock_s_lock(&btr_search_latch);
466 - index = block->index;
467 + if (btr_search_index_num > 1) {
468 + rw_lock_t* btr_search_latch;
470 + /* FIXME: This may be optimistic implementation still. */
471 + btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
472 + if (UNIV_LIKELY(!btr_search_latch)) {
473 + if (block->index) {
478 + rw_lock_s_lock(btr_search_latch);
479 + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
480 + rw_lock_s_unlock(btr_search_latch);
483 + if (UNIV_LIKELY(!block->index)) {
484 + rw_lock_s_unlock(btr_search_latch);
487 + index = block->index;
488 + ut_a(btr_search_latch == btr_search_get_latch(index->id));
490 + /* btr_search_index_num == 1 */
491 + /* btr_search_latch is only one and able to obtain
492 + before evaluating block->index. */
493 + rw_lock_s_lock(btr_search_latch_part[0]);
494 + if (UNIV_LIKELY(!block->index)) {
495 + rw_lock_s_unlock(btr_search_latch_part[0]);
498 + index = block->index;
501 if (UNIV_LIKELY(!index)) {
503 - rw_lock_s_unlock(&btr_search_latch);
504 + rw_lock_s_unlock(btr_search_get_latch(index->id));
509 - ut_a(!dict_index_is_ibuf(index));
510 - table = btr_search_sys->hash_index;
511 + table = btr_search_get_hash_index(index->id);
513 #ifdef UNIV_SYNC_DEBUG
514 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
515 @@ -1080,12 +1144,14 @@
517 n_fields = block->curr_n_fields;
518 n_bytes = block->curr_n_bytes;
519 + ut_a(index == block->index);
520 + ut_a(!dict_index_is_ibuf(index));
522 /* NOTE: The fields of block must not be accessed after
523 releasing btr_search_latch, as the index page might only
526 - rw_lock_s_unlock(&btr_search_latch);
527 + rw_lock_s_unlock(btr_search_get_latch(index->id));
529 ut_a(n_fields + n_bytes > 0);
531 @@ -1136,7 +1202,7 @@
535 - rw_lock_x_lock(&btr_search_latch);
536 + rw_lock_x_lock(btr_search_get_latch(index->id));
538 if (UNIV_UNLIKELY(!block->index)) {
539 /* Someone else has meanwhile dropped the hash index */
540 @@ -1152,7 +1218,7 @@
541 /* Someone else has meanwhile built a new hash index on the
542 page, with different parameters */
544 - rw_lock_x_unlock(&btr_search_latch);
545 + rw_lock_x_unlock(btr_search_get_latch(index->id));
549 @@ -1167,6 +1233,7 @@
550 index->search_info->ref_count--;
553 + block->btr_search_latch = NULL;
556 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
557 @@ -1179,14 +1246,14 @@
558 "InnoDB: the hash index to a page of %s,"
559 " still %lu hash nodes remain.\n",
560 index->name, (ulong) block->n_pointers);
561 - rw_lock_x_unlock(&btr_search_latch);
562 + rw_lock_x_unlock(btr_search_get_latch(index->id));
564 btr_search_validate();
566 - rw_lock_x_unlock(&btr_search_latch);
567 + rw_lock_x_unlock(btr_search_get_latch(index->id));
569 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
570 - rw_lock_x_unlock(&btr_search_latch);
571 + rw_lock_x_unlock(btr_search_get_latch(index->id));
572 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
575 @@ -1218,9 +1285,9 @@
577 ibool released_search_latch;
579 - rw_lock_s_lock(&btr_search_latch);
580 + rw_lock_s_lock(btr_search_get_latch(index->id));
582 - table = btr_search_sys->hash_index;
583 + table = btr_search_get_hash_index(index->id);
585 for (j = 0; j < srv_buf_pool_instances; j++) {
586 buf_pool_t* buf_pool;
587 @@ -1254,7 +1321,7 @@
590 /* keeping latch order */
591 - rw_lock_s_unlock(&btr_search_latch);
592 + rw_lock_s_unlock(btr_search_get_latch(index->id));
593 released_search_latch = TRUE;
594 rw_lock_x_lock(&block->lock);
596 @@ -1306,7 +1373,7 @@
597 mem_heap_empty(heap);
600 - rw_lock_x_lock(&btr_search_latch);
601 + rw_lock_x_lock(btr_search_get_latch(index->id));
603 if (UNIV_UNLIKELY(!block->index)) {
605 @@ -1316,12 +1383,12 @@
607 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
608 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
609 - rw_lock_x_unlock(&btr_search_latch);
610 + rw_lock_x_unlock(btr_search_get_latch(index->id));
611 rw_lock_x_unlock(&block->lock);
615 - rw_lock_s_lock(&btr_search_latch);
616 + rw_lock_s_lock(btr_search_get_latch(index->id));
620 @@ -1334,6 +1401,7 @@
621 index->search_info->ref_count--;
624 + block->btr_search_latch = NULL;
627 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
628 @@ -1346,18 +1414,18 @@
629 index->name, (ulong) block->n_pointers);
631 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
632 - rw_lock_x_unlock(&btr_search_latch);
633 + rw_lock_x_unlock(btr_search_get_latch(index->id));
634 rw_lock_x_unlock(&block->lock);
638 - rw_lock_s_lock(&btr_search_latch);
639 + rw_lock_s_lock(btr_search_get_latch(index->id));
642 } while (released_search_latch);
645 - rw_lock_s_unlock(&btr_search_latch);
646 + rw_lock_s_unlock(btr_search_get_latch(index->id));
648 if (UNIV_LIKELY_NULL(heap)) {
650 @@ -1395,7 +1463,7 @@
652 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
654 - btr_search_drop_page_hash_index(block);
655 + btr_search_drop_page_hash_index(block, NULL);
659 @@ -1436,31 +1504,26 @@
661 ut_a(!dict_index_is_ibuf(index));
663 + table = btr_search_get_hash_index(index->id);
664 + page = buf_block_get_frame(block);
666 #ifdef UNIV_SYNC_DEBUG
667 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
668 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
669 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
670 || rw_lock_own(&(block->lock), RW_LOCK_EX));
671 #endif /* UNIV_SYNC_DEBUG */
673 - rw_lock_s_lock(&btr_search_latch);
675 - if (!btr_search_enabled) {
676 - rw_lock_s_unlock(&btr_search_latch);
680 - table = btr_search_sys->hash_index;
681 - page = buf_block_get_frame(block);
682 + rw_lock_s_lock(btr_search_get_latch(index->id));
684 if (block->index && ((block->curr_n_fields != n_fields)
685 - || (block->curr_n_bytes != n_bytes)
686 - || (block->curr_left_side != left_side))) {
687 + || (block->curr_n_bytes != n_bytes)
688 + || (block->curr_left_side != left_side))) {
690 - rw_lock_s_unlock(&btr_search_latch);
691 + rw_lock_s_unlock(btr_search_get_latch(index->id));
693 - btr_search_drop_page_hash_index(block);
694 + btr_search_drop_page_hash_index(block, index);
696 - rw_lock_s_unlock(&btr_search_latch);
697 + rw_lock_s_unlock(btr_search_get_latch(index->id));
700 n_recs = page_get_n_recs(page);
701 @@ -1554,9 +1617,9 @@
705 - btr_search_check_free_space_in_heap();
706 + btr_search_check_free_space_in_heap(index->id);
708 - rw_lock_x_lock(&btr_search_latch);
709 + rw_lock_x_lock(btr_search_get_latch(index->id));
711 if (UNIV_UNLIKELY(!btr_search_enabled)) {
713 @@ -1583,6 +1646,7 @@
714 block->curr_n_bytes = n_bytes;
715 block->curr_left_side = left_side;
716 block->index = index;
717 + block->btr_search_latch = btr_search_get_latch(index->id);
719 for (i = 0; i < n_cached; i++) {
721 @@ -1590,7 +1654,7 @@
725 - rw_lock_x_unlock(&btr_search_latch);
726 + rw_lock_x_unlock(btr_search_get_latch(index->id));
730 @@ -1625,7 +1689,7 @@
731 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
732 #endif /* UNIV_SYNC_DEBUG */
734 - rw_lock_s_lock(&btr_search_latch);
735 + rw_lock_s_lock(btr_search_get_latch(index->id));
737 ut_a(!new_block->index || new_block->index == index);
738 ut_a(!block->index || block->index == index);
739 @@ -1634,9 +1698,9 @@
741 if (new_block->index) {
743 - rw_lock_s_unlock(&btr_search_latch);
744 + rw_lock_s_unlock(btr_search_get_latch(index->id));
746 - btr_search_drop_page_hash_index(block);
747 + btr_search_drop_page_hash_index(block, index);
751 @@ -1651,7 +1715,7 @@
752 new_block->n_bytes = block->curr_n_bytes;
753 new_block->left_side = left_side;
755 - rw_lock_s_unlock(&btr_search_latch);
756 + rw_lock_s_unlock(btr_search_get_latch(index->id));
758 ut_a(n_fields + n_bytes > 0);
760 @@ -1663,7 +1727,7 @@
764 - rw_lock_s_unlock(&btr_search_latch);
765 + rw_lock_s_unlock(btr_search_get_latch(index->id));
768 /********************************************************************//**
769 @@ -1702,7 +1766,7 @@
770 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
771 ut_a(!dict_index_is_ibuf(index));
773 - table = btr_search_sys->hash_index;
774 + table = btr_search_get_hash_index(cursor->index->id);
776 rec = btr_cur_get_rec(cursor);
778 @@ -1713,7 +1777,7 @@
782 - rw_lock_x_lock(&btr_search_latch);
783 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
786 ut_a(block->index == index);
787 @@ -1721,7 +1785,7 @@
788 ha_search_and_delete_if_found(table, fold, rec);
791 - rw_lock_x_unlock(&btr_search_latch);
792 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
795 /********************************************************************//**
796 @@ -1758,7 +1822,7 @@
797 ut_a(cursor->index == index);
798 ut_a(!dict_index_is_ibuf(index));
800 - rw_lock_x_lock(&btr_search_latch);
801 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
805 @@ -1772,15 +1836,15 @@
806 && (cursor->n_bytes == block->curr_n_bytes)
807 && !block->curr_left_side) {
809 - table = btr_search_sys->hash_index;
810 + table = btr_search_get_hash_index(cursor->index->id);
812 ha_search_and_update_if_found(table, cursor->fold, rec,
813 block, page_rec_get_next(rec));
816 - rw_lock_x_unlock(&btr_search_latch);
817 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
819 - rw_lock_x_unlock(&btr_search_latch);
820 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
822 btr_search_update_hash_on_insert(cursor);
824 @@ -1815,9 +1879,9 @@
825 ulint* offsets = offsets_;
826 rec_offs_init(offsets_);
828 - table = btr_search_sys->hash_index;
829 + table = btr_search_get_hash_index(cursor->index->id);
831 - btr_search_check_free_space_in_heap();
832 + btr_search_check_free_space_in_heap(cursor->index->id);
834 rec = btr_cur_get_rec(cursor);
836 @@ -1862,7 +1926,7 @@
840 - rw_lock_x_lock(&btr_search_latch);
841 + rw_lock_x_lock(btr_search_get_latch(index->id));
845 @@ -1880,7 +1944,7 @@
849 - rw_lock_x_lock(&btr_search_latch);
850 + rw_lock_x_lock(btr_search_get_latch(index->id));
854 @@ -1902,7 +1966,7 @@
858 - rw_lock_x_lock(&btr_search_latch);
859 + rw_lock_x_lock(btr_search_get_latch(index->id));
863 @@ -1921,7 +1985,7 @@
867 - rw_lock_x_lock(&btr_search_latch);
868 + rw_lock_x_lock(btr_search_get_latch(index->id));
872 @@ -1948,7 +2012,7 @@
876 - rw_lock_x_unlock(&btr_search_latch);
877 + rw_lock_x_unlock(btr_search_get_latch(index->id));
881 @@ -1964,7 +2028,7 @@
883 ulint n_page_dumps = 0;
888 mem_heap_t* heap = NULL;
889 ulint offsets_[REC_OFFS_NORMAL_SIZE];
890 @@ -1976,23 +2040,25 @@
892 rec_offs_init(offsets_);
894 - rw_lock_x_lock(&btr_search_latch);
895 + btr_search_x_lock_all();
896 buf_pool_page_hash_x_lock_all();
898 - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
899 + for (j = 0; j < btr_search_index_num; j++) {
901 + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
903 for (i = 0; i < cell_count; i++) {
904 /* We release btr_search_latch every once in a while to
905 give other queries a chance to run. */
906 if ((i != 0) && ((i % chunk_size) == 0)) {
907 buf_pool_page_hash_x_unlock_all();
908 - rw_lock_x_unlock(&btr_search_latch);
909 + btr_search_x_unlock_all();
911 - rw_lock_x_lock(&btr_search_latch);
912 + btr_search_x_lock_all();
913 buf_pool_page_hash_x_lock_all();
916 - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
917 + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
919 for (; node != NULL; node = node->next) {
920 const buf_block_t* block
921 @@ -2099,19 +2165,21 @@
922 give other queries a chance to run. */
924 buf_pool_page_hash_x_unlock_all();
925 - rw_lock_x_unlock(&btr_search_latch);
926 + btr_search_x_unlock_all();
928 - rw_lock_x_lock(&btr_search_latch);
929 + btr_search_x_lock_all();
930 buf_pool_page_hash_x_lock_all();
933 - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
934 + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
939 + } /*for (j = 0; j < btr_search_index_num; j++)*/
941 buf_pool_page_hash_x_unlock_all();
942 - rw_lock_x_unlock(&btr_search_latch);
943 + btr_search_x_unlock_all();
944 if (UNIV_LIKELY_NULL(heap)) {
947 --- a/storage/innobase/buf/buf0buf.c
948 +++ b/storage/innobase/buf/buf0buf.c
951 block->check_index_page_at_flush = FALSE;
953 + block->btr_search_latch = NULL;
956 block->page.in_page_hash = FALSE;
957 @@ -1427,7 +1428,11 @@
960 #ifdef UNIV_SYNC_DEBUG
961 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
964 + for (j = 0; j < btr_search_index_num; j++) {
965 + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
967 #endif /* UNIV_SYNC_DEBUG */
968 ut_ad(!btr_search_enabled);
970 @@ -2142,6 +2147,7 @@
972 block->check_index_page_at_flush = FALSE;
974 + block->btr_search_latch = NULL;
976 block->n_hash_helps = 0;
978 --- a/storage/innobase/buf/buf0lru.c
979 +++ b/storage/innobase/buf/buf0lru.c
982 mutex_exit(&buf_pool->LRU_list_mutex);
984 - rw_lock_s_lock(&btr_search_latch);
985 + btr_search_s_lock_all();
986 chunk = buf_pool->chunks;
987 for (j = buf_pool->n_chunks; j--; chunk++) {
988 buf_block_t* block = chunk->blocks;
989 @@ -572,16 +572,16 @@
993 - rw_lock_s_unlock(&btr_search_latch);
994 + btr_search_s_unlock_all();
996 rw_lock_x_lock(&block->lock);
997 - btr_search_drop_page_hash_index(block);
998 + btr_search_drop_page_hash_index(block, NULL);
999 rw_lock_x_unlock(&block->lock);
1001 - rw_lock_s_lock(&btr_search_latch);
1002 + btr_search_s_lock_all();
1005 - rw_lock_s_unlock(&btr_search_latch);
1006 + btr_search_s_unlock_all();
1010 @@ -1744,7 +1744,7 @@
1012 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1014 - btr_search_drop_page_hash_index((buf_block_t*) bpage);
1015 + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1016 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1019 --- a/storage/innobase/dict/dict0dict.c
1020 +++ b/storage/innobase/dict/dict0dict.c
1021 @@ -1846,7 +1846,7 @@
1025 - ulint ref_count = btr_search_info_get_ref_count(info);
1026 + ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1027 if (ref_count == 0) {
1030 --- a/storage/innobase/handler/ha_innodb.cc
1031 +++ b/storage/innobase/handler/ha_innodb.cc
1032 @@ -11833,6 +11833,11 @@
1033 "Disable with --skip-innodb-adaptive-hash-index.",
1034 NULL, innodb_adaptive_hash_index_update, TRUE);
1036 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1037 + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1038 + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1039 + NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
1041 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1042 PLUGIN_VAR_RQCMDARG,
1043 "Replication thread delay (ms) on the slave server if "
1044 @@ -12213,6 +12218,7 @@
1045 MYSQL_SYSVAR(use_sys_stats_table),
1046 MYSQL_SYSVAR(stats_sample_pages),
1047 MYSQL_SYSVAR(adaptive_hash_index),
1048 + MYSQL_SYSVAR(adaptive_hash_index_partitions),
1049 MYSQL_SYSVAR(stats_method),
1050 MYSQL_SYSVAR(replication_delay),
1051 MYSQL_SYSVAR(status_file),
1052 --- a/storage/innobase/include/btr0sea.h
1053 +++ b/storage/innobase/include/btr0sea.h
1056 btr_search_info_get_ref_count(
1057 /*==========================*/
1058 - btr_search_t* info); /*!< in: search info. */
1059 + btr_search_t* info, /*!< in: search info. */
1061 /*********************************************************************//**
1062 Updates the search info. */
1064 @@ -136,10 +137,11 @@
1066 btr_search_drop_page_hash_index(
1067 /*============================*/
1068 - buf_block_t* block); /*!< in: block containing index page,
1069 + buf_block_t* block, /*!< in: block containing index page,
1070 s- or x-latched, or an index page
1071 for which we know that
1072 block->buf_fix_count == 0 */
1073 + dict_index_t* index_in);
1074 /************************************************************************
1075 Drops a page hash index based on index */
1077 @@ -199,6 +201,40 @@
1078 # define btr_search_validate() TRUE
1079 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1081 +/********************************************************************//**
1082 +New functions to control split btr_search_index */
1085 +btr_search_get_hash_index(
1086 +/*======================*/
1091 +btr_search_get_latch(
1092 +/*=================*/
1097 +btr_search_x_lock_all(void);
1098 +/*========================*/
1102 +btr_search_x_unlock_all(void);
1103 +/*==========================*/
1107 +btr_search_s_lock_all(void);
1108 +/*========================*/
1112 +btr_search_s_unlock_all(void);
1113 +/*==========================*/
1115 /** The search info struct in an index */
1116 struct btr_search_struct{
1117 ulint ref_count; /*!< Number of blocks in this index tree
1120 /** The hash index system */
1121 struct btr_search_sys_struct{
1122 - hash_table_t* hash_index; /*!< the adaptive hash index,
1123 + hash_table_t** hash_index; /*!< the adaptive hash index,
1124 mapping dtuple_fold values
1125 to rec_t pointers on index pages */
1127 --- a/storage/innobase/include/btr0sea.ic
1128 +++ b/storage/innobase/include/btr0sea.ic
1132 #ifdef UNIV_SYNC_DEBUG
1133 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1134 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1135 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1136 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1137 #endif /* UNIV_SYNC_DEBUG */
1139 info = btr_search_get_info(index);
1142 btr_search_info_update_slow(info, cursor);
1145 +/*********************************************************************//**
1146 +New functions to control split btr_search_index */
1149 +btr_search_get_hash_index(
1150 +/*======================*/
1153 + return(btr_search_sys->hash_index[key % btr_search_index_num]);
1158 +btr_search_get_latch(
1159 +/*=================*/
1162 + return(btr_search_latch_part[key % btr_search_index_num]);
1167 +btr_search_x_lock_all(void)
1168 +/*=======================*/
1172 + for (i = 0; i < btr_search_index_num; i++) {
1173 + rw_lock_x_lock(btr_search_latch_part[i]);
1179 +btr_search_x_unlock_all(void)
1180 +/*==========================*/
1184 + for (i = 0; i < btr_search_index_num; i++) {
1185 + rw_lock_x_unlock(btr_search_latch_part[i]);
1191 +btr_search_s_lock_all(void)
1192 +/*=======================*/
1196 + for (i = 0; i < btr_search_index_num; i++) {
1197 + rw_lock_s_lock(btr_search_latch_part[i]);
1203 +btr_search_s_unlock_all(void)
1204 +/*=========================*/
1208 + for (i = 0; i < btr_search_index_num; i++) {
1209 + rw_lock_s_unlock(btr_search_latch_part[i]);
1213 --- a/storage/innobase/page/page0zip.c
1214 +++ b/storage/innobase/page/page0zip.c
1215 @@ -4456,7 +4456,7 @@
1217 #ifndef UNIV_HOTBACKUP
1218 temp_block = buf_block_alloc(buf_pool);
1219 - btr_search_drop_page_hash_index(block);
1220 + btr_search_drop_page_hash_index(block, index);
1221 block->check_index_page_at_flush = TRUE;
1222 #else /* !UNIV_HOTBACKUP */
1223 ut_ad(block == back_block1);
1224 --- a/storage/innobase/row/row0mysql.c
1225 +++ b/storage/innobase/row/row0mysql.c
1226 @@ -2594,7 +2594,7 @@
1227 /* check adaptive hash entries */
1228 index = dict_table_get_first_index(table);
1230 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1231 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1233 fprintf(stderr, "InnoDB: Warning:"
1234 " hash index ref_count (%lu) is not zero"
1235 @@ -2955,7 +2955,7 @@
1236 table->space = space;
1237 index = dict_table_get_first_index(table);
1239 - ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1240 + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1241 /* check adaptive hash entries */
1243 fprintf(stderr, "InnoDB: Warning:"
1244 --- a/storage/innobase/row/row0sel.c
1245 +++ b/storage/innobase/row/row0sel.c
1246 @@ -1222,7 +1222,7 @@
1247 ut_ad(plan->unique_search);
1248 ut_ad(!plan->must_get_clust);
1249 #ifdef UNIV_SYNC_DEBUG
1250 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1251 + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1252 #endif /* UNIV_SYNC_DEBUG */
1254 row_sel_open_pcur(plan, TRUE, mtr);
1255 @@ -1393,10 +1393,10 @@
1256 && !plan->must_get_clust
1257 && !plan->table->big_rows) {
1258 if (!search_latch_locked) {
1259 - rw_lock_s_lock(&btr_search_latch);
1260 + rw_lock_s_lock(btr_search_get_latch(index->id));
1262 search_latch_locked = TRUE;
1263 - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1264 + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1266 /* There is an x-latch request waiting: release the
1267 s-latch for a moment; as an s-latch here is often
1268 @@ -1405,8 +1405,8 @@
1269 from acquiring an s-latch for a long time, lowering
1270 performance significantly in multiprocessors. */
1272 - rw_lock_s_unlock(&btr_search_latch);
1273 - rw_lock_s_lock(&btr_search_latch);
1274 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1275 + rw_lock_s_lock(btr_search_get_latch(index->id));
1278 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1279 @@ -1429,7 +1429,7 @@
1282 if (search_latch_locked) {
1283 - rw_lock_s_unlock(&btr_search_latch);
1284 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1286 search_latch_locked = FALSE;
1288 @@ -2005,7 +2005,7 @@
1291 if (search_latch_locked) {
1292 - rw_lock_s_unlock(&btr_search_latch);
1293 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1295 if (UNIV_LIKELY_NULL(heap)) {
1296 mem_heap_free(heap);
1297 @@ -3408,6 +3408,8 @@
1298 /* if the returned record was locked and we did a semi-consistent
1299 read (fetch the newest committed version), then this is set to
1302 + ulint should_release;
1303 #ifdef UNIV_SEARCH_DEBUG
1305 #endif /* UNIV_SEARCH_DEBUG */
1306 @@ -3505,18 +3507,33 @@
1307 /* PHASE 0: Release a possible s-latch we are holding on the
1308 adaptive hash index latch if there is someone waiting behind */
1310 - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1311 - && trx->has_search_latch) {
1312 + should_release = 0;
1313 + for (i = 0; i < btr_search_index_num; i++) {
1314 + /* we should check all latches (fix Bug#791030) */
1315 + if (rw_lock_get_writer(btr_search_latch_part[i])
1316 + != RW_LOCK_NOT_LOCKED) {
1317 + should_release |= ((ulint)1 << i);
1321 + if (should_release) {
1323 /* There is an x-latch request on the adaptive hash index:
1324 release the s-latch to reduce starvation and wait for
1325 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1328 - rw_lock_s_unlock(&btr_search_latch);
1329 - trx->has_search_latch = FALSE;
1330 + for (i = 0; i < btr_search_index_num; i++) {
1331 + /* we should release all s-latches (fix Bug#791030) */
1332 + if (trx->has_search_latch & ((ulint)1 << i)) {
1333 + rw_lock_s_unlock(btr_search_latch_part[i]);
1334 + trx->has_search_latch &= (~((ulint)1 << i));
1338 + if (!trx->has_search_latch) {
1339 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1343 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1344 @@ -3667,9 +3684,28 @@
1345 hash index semaphore! */
1347 #ifndef UNIV_SEARCH_DEBUG
1348 - if (!trx->has_search_latch) {
1349 - rw_lock_s_lock(&btr_search_latch);
1350 - trx->has_search_latch = TRUE;
1351 + if (!(trx->has_search_latch
1352 + & ((ulint)1 << (index->id % btr_search_index_num)))) {
1353 + if (trx->has_search_latch
1354 + < ((ulint)1 << (index->id % btr_search_index_num))) {
1355 + rw_lock_s_lock(btr_search_get_latch(index->id));
1356 + trx->has_search_latch |=
1357 + ((ulint)1 << (index->id % btr_search_index_num));
1359 + /* should re-lock to obay latch-order */
1360 + for (i = 0; i < btr_search_index_num; i++) {
1361 + if (trx->has_search_latch & ((ulint)1 << i)) {
1362 + rw_lock_s_unlock(btr_search_latch_part[i]);
1365 + trx->has_search_latch |=
1366 + ((ulint)1 << (index->id % btr_search_index_num));
1367 + for (i = 0; i < btr_search_index_num; i++) {
1368 + if (trx->has_search_latch & ((ulint)1 << i)) {
1369 + rw_lock_s_lock(btr_search_latch_part[i]);
1375 switch (row_sel_try_search_shortcut_for_mysql(
1376 @@ -3730,7 +3766,11 @@
1378 trx->search_latch_timeout--;
1380 - rw_lock_s_unlock(&btr_search_latch);
1381 + for (i = 0; i < btr_search_index_num; i++) {
1382 + if (trx->has_search_latch & ((ulint)1 << i)) {
1383 + rw_lock_s_unlock(btr_search_latch_part[i]);
1386 trx->has_search_latch = FALSE;
1389 @@ -3754,7 +3794,12 @@
1390 /* PHASE 3: Open or restore index cursor position */
1392 if (trx->has_search_latch) {
1393 - rw_lock_s_unlock(&btr_search_latch);
1395 + for (i = 0; i < btr_search_index_num; i++) {
1396 + if (trx->has_search_latch & ((ulint)1 << i)) {
1397 + rw_lock_s_unlock(btr_search_latch_part[i]);
1400 trx->has_search_latch = FALSE;
1403 --- a/storage/innobase/srv/srv0srv.c
1404 +++ b/storage/innobase/srv/srv0srv.c
1405 @@ -2051,7 +2051,9 @@
1406 "-------------------------------------\n", file);
1409 - ha_print_info(file, btr_search_sys->hash_index);
1410 + for (i = 0; i < btr_search_index_num; i++) {
1411 + ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1415 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1416 @@ -2076,14 +2078,15 @@
1417 ut_total_allocated_memory,
1418 mem_pool_get_reserved(mem_comm_pool));
1419 /* Calcurate reserved memories */
1420 - if (btr_search_sys && btr_search_sys->hash_index->heap) {
1421 - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1422 + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1423 + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1425 btr_search_sys_subtotal = 0;
1426 - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1427 - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1428 + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1429 + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1432 + btr_search_sys_subtotal *= btr_search_index_num;
1434 lock_sys_subtotal = 0;
1436 @@ -2109,10 +2112,10 @@
1437 " Recovery system %lu \t(%lu + %lu)\n",
1439 (ulong) (btr_search_sys
1440 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1441 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1442 + btr_search_sys_subtotal,
1443 (ulong) (btr_search_sys
1444 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1445 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1446 (ulong) btr_search_sys_subtotal,
1448 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1449 --- a/storage/innobase/trx/trx0trx.c
1450 +++ b/storage/innobase/trx/trx0trx.c
1451 @@ -265,8 +265,14 @@
1452 /*=================================*/
1453 trx_t* trx) /*!< in: transaction */
1457 if (trx->has_search_latch) {
1458 - rw_lock_s_unlock(&btr_search_latch);
1459 + for (i = 0; i < btr_search_index_num; i++) {
1460 + if (trx->has_search_latch & ((ulint)1 << i)) {
1461 + rw_lock_s_unlock(btr_search_latch_part[i]);
1465 trx->has_search_latch = FALSE;
1467 --- a/storage/innobase/include/btr0types.h
1468 +++ b/storage/innobase/include/btr0types.h
1471 Bear in mind (3) and (4) when using the hash index.
1473 -extern rw_lock_t* btr_search_latch_temp;
1474 +//extern rw_lock_t* btr_search_latch_temp;
1476 +extern rw_lock_t** btr_search_latch_part;
1478 /** The latch protecting the adaptive search system */
1479 -#define btr_search_latch (*btr_search_latch_temp)
1480 +//#define btr_search_latch (*btr_search_latch_temp)
1482 /** Flag: has the search system been enabled?
1483 Protected by btr_search_latch. */
1484 extern char btr_search_enabled;
1486 +extern ulint btr_search_index_num;
1488 #ifdef UNIV_BLOB_DEBUG
1489 # include "buf0types.h"
1490 /** An index->blobs entry for keeping track of off-page column references */
1491 --- a/storage/innobase/ha/ha0ha.c
1492 +++ b/storage/innobase/ha/ha0ha.c
1494 ut_a(block->frame == page_align(data));
1495 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1496 #ifdef UNIV_SYNC_DEBUG
1497 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1498 + ut_ad(rw_lock_own(block->btr_search_latch, RW_LOCK_EX));
1499 #endif /* UNIV_SYNC_DEBUG */
1500 ASSERT_HASH_MUTEX_OWN(table, fold);
1501 ut_ad(btr_search_enabled);
1504 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1505 #ifdef UNIV_SYNC_DEBUG
1506 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1507 + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1508 #endif /* UNIV_SYNC_DEBUG */
1509 ut_ad(btr_search_enabled);
1510 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1512 ut_a(new_block->frame == page_align(new_data));
1513 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1514 #ifdef UNIV_SYNC_DEBUG
1515 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1516 + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1517 #endif /* UNIV_SYNC_DEBUG */
1519 if (!btr_search_enabled) {
1521 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1522 ASSERT_HASH_MUTEX_OWN(table, fold);
1523 #ifdef UNIV_SYNC_DEBUG
1524 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1525 + // ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1526 #endif /* UNIV_SYNC_DEBUG */
1527 ut_ad(btr_search_enabled);
1529 --- a/storage/innobase/include/ha0ha.ic
1530 +++ b/storage/innobase/include/ha0ha.ic
1533 ASSERT_HASH_MUTEX_OWN(table, fold);
1534 #ifdef UNIV_SYNC_DEBUG
1535 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1536 +// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1537 #endif /* UNIV_SYNC_DEBUG */
1538 ut_ad(btr_search_enabled);
1542 ASSERT_HASH_MUTEX_OWN(table, fold);
1543 #ifdef UNIV_SYNC_DEBUG
1544 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1545 +// ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1546 #endif /* UNIV_SYNC_DEBUG */
1547 ut_ad(btr_search_enabled);
1549 --- a/storage/innobase/include/buf0buf.h
1550 +++ b/storage/innobase/include/buf0buf.h
1551 @@ -1580,6 +1580,7 @@
1552 complete, though: there may
1553 have been hash collisions,
1554 record deletions, etc. */
1555 + volatile rw_lock_t* btr_search_latch;
1557 # ifdef UNIV_SYNC_DEBUG
1558 /** @name Debug fields */
1559 --- a/storage/innobase/sync/sync0sync.c
1560 +++ b/storage/innobase/sync/sync0sync.c
1561 @@ -1222,7 +1222,6 @@
1562 case SYNC_OUTER_ANY_LATCH:
1563 case SYNC_FILE_FORMAT_TAG:
1564 case SYNC_DOUBLEWRITE:
1565 - case SYNC_SEARCH_SYS:
1566 case SYNC_TRX_LOCK_HEAP:
1568 case SYNC_IBUF_BITMAP_MUTEX:
1569 @@ -1243,6 +1242,7 @@
1573 + case SYNC_SEARCH_SYS:
1574 case SYNC_BUF_LRU_LIST:
1575 case SYNC_BUF_FLUSH_LIST:
1576 case SYNC_BUF_PAGE_HASH: