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 diff -ruN a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c
9 --- a/storage/innobase/btr/btr0btr.c 2010-12-04 15:52:23.355483176 +0900
10 +++ b/storage/innobase/btr/btr0btr.c 2010-12-04 16:12:48.639514256 +0900
15 - btr_search_drop_page_hash_index(block);
16 + btr_search_drop_page_hash_index(block, NULL);
18 header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
22 #ifndef UNIV_HOTBACKUP
23 if (UNIV_LIKELY(!recovery)) {
24 - btr_search_drop_page_hash_index(block);
25 + btr_search_drop_page_hash_index(block, index);
28 block->check_index_page_at_flush = TRUE;
30 ut_a(!page_zip || page_zip_validate(page_zip, page));
31 #endif /* UNIV_ZIP_DEBUG */
33 - btr_search_drop_page_hash_index(block);
34 + btr_search_drop_page_hash_index(block, index);
36 /* Recreate the page: note that global data on page (possible
37 segment headers, next page-field, etc.) is preserved intact */
42 - btr_search_drop_page_hash_index(block);
43 + btr_search_drop_page_hash_index(block, index);
45 /* Make the father empty */
46 btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
51 - btr_search_drop_page_hash_index(block);
52 + btr_search_drop_page_hash_index(block, index);
54 /* Remove the page from the level list */
55 btr_level_list_remove(space, zip_size, page, mtr);
60 - btr_search_drop_page_hash_index(block);
61 + btr_search_drop_page_hash_index(block, index);
64 if (UNIV_LIKELY_NULL(merge_page_zip)) {
66 ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
68 ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
69 - btr_search_drop_page_hash_index(block);
70 + btr_search_drop_page_hash_index(block, index);
72 btr_page_get_father(index, block, mtr, &cursor);
73 father = btr_cur_get_block(&cursor);
76 page = buf_block_get_frame(block);
77 ut_a(page_is_comp(merge_page) == page_is_comp(page));
78 - btr_search_drop_page_hash_index(block);
79 + btr_search_drop_page_hash_index(block, index);
81 if (left_page_no == FIL_NULL && !page_is_leaf(page)) {
83 diff -ruN a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
84 --- a/storage/innobase/btr/btr0cur.c 2010-12-04 15:52:23.359513820 +0900
85 +++ b/storage/innobase/btr/btr0cur.c 2010-12-04 16:12:48.643551837 +0900
87 #ifdef UNIV_SEARCH_PERF_STAT
90 - if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED
91 + if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED
92 && latch_mode <= BTR_MODIFY_LEAF
93 && info->last_hash_succ
97 if (has_search_latch) {
98 /* Release possible search latch to obey latching order */
99 - rw_lock_s_unlock(&btr_search_latch);
100 + rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
103 /* Store the position of the tree latch we push to mtr so that we
106 if (has_search_latch) {
108 - rw_lock_s_lock(&btr_search_latch);
109 + rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
113 @@ -2060,7 +2060,7 @@
114 btr_search_update_hash_on_delete(cursor);
117 - rw_lock_x_lock(&btr_search_latch);
118 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
121 if (!(flags & BTR_KEEP_SYS_FLAG)) {
122 @@ -2074,7 +2074,7 @@
123 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
125 if (block->is_hashed) {
126 - rw_lock_x_unlock(&btr_search_latch);
127 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
130 if (page_zip && !dict_index_is_clust(index)
131 @@ -2852,7 +2852,7 @@
134 if (block->is_hashed) {
135 - rw_lock_x_lock(&btr_search_latch);
136 + rw_lock_x_lock(btr_search_get_latch(index->id));
139 page_zip = buf_block_get_page_zip(block);
140 @@ -2867,7 +2867,7 @@
143 if (block->is_hashed) {
144 - rw_lock_x_unlock(&btr_search_latch);
145 + rw_lock_x_unlock(btr_search_get_latch(index->id));
148 btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
149 @@ -2994,13 +2994,13 @@
150 == dict_table_is_comp(cursor->index->table));
152 if (block->is_hashed) {
153 - rw_lock_x_lock(&btr_search_latch);
154 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
157 btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val);
159 if (block->is_hashed) {
160 - rw_lock_x_unlock(&btr_search_latch);
161 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
164 btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
165 diff -ruN a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c
166 --- a/storage/innobase/btr/btr0sea.c 2010-12-04 15:52:23.387513429 +0900
167 +++ b/storage/innobase/btr/btr0sea.c 2010-12-04 16:14:51.721884049 +0900
169 UNIV_INTERN char btr_search_enabled = TRUE;
170 UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
172 +UNIV_INTERN ulint btr_search_index_num = 1;
174 /** Mutex protecting btr_search_enabled */
175 static mutex_t btr_search_enabled_mutex;
179 /* We will allocate the latch from dynamic memory to get it to the
180 same DRAM page as other hotspot semaphores */
181 -UNIV_INTERN rw_lock_t* btr_search_latch_temp;
182 +//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
184 +UNIV_INTERN rw_lock_t** btr_search_latch_part;
186 /** padding to prevent other memory update hotspots from residing on
187 the same memory cache line */
188 @@ -131,18 +135,19 @@
189 will not guarantee success. */
192 -btr_search_check_free_space_in_heap(void)
193 +btr_search_check_free_space_in_heap(
194 /*=====================================*/
200 #ifdef UNIV_SYNC_DEBUG
201 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
202 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
203 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
204 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
205 #endif /* UNIV_SYNC_DEBUG */
207 - table = btr_search_sys->hash_index;
208 + table = btr_search_get_hash_index(key);
213 if (heap->free_block == NULL) {
214 buf_block_t* block = buf_block_alloc(NULL, 0);
216 - rw_lock_x_lock(&btr_search_latch);
217 + rw_lock_x_lock(btr_search_get_latch(key));
219 if (heap->free_block == NULL) {
220 heap->free_block = block;
222 buf_block_free(block);
225 - rw_lock_x_unlock(&btr_search_latch);
226 + rw_lock_x_unlock(btr_search_get_latch(key));
230 @@ -173,19 +178,30 @@
231 /*==================*/
232 ulint hash_size) /*!< in: hash index hash table size */
235 /* We allocate the search latch from dynamic memory:
236 see above at the global variable definition */
238 - btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
239 + //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
241 - rw_lock_create(btr_search_latch_key, &btr_search_latch,
243 + //rw_lock_create(btr_search_latch_key, &btr_search_latch,
244 + // SYNC_SEARCH_SYS);
245 mutex_create(btr_search_enabled_mutex_key,
246 &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
248 btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
250 - btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
251 + /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
252 + btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
253 + btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
254 + for (i = 0; i < btr_search_index_num; i++) {
255 + btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
257 + rw_lock_create(btr_search_latch_key,
258 + btr_search_latch_part[i], SYNC_SEARCH_SYS);
260 + btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
264 /*****************************************************************//**
265 @@ -195,11 +211,20 @@
266 btr_search_sys_free(void)
267 /*=====================*/
269 - rw_lock_free(&btr_search_latch);
270 - mem_free(btr_search_latch_temp);
271 - btr_search_latch_temp = NULL;
272 - mem_heap_free(btr_search_sys->hash_index->heap);
273 - hash_table_free(btr_search_sys->hash_index);
276 + for (i = 0; i < btr_search_index_num; i++) {
277 + mem_heap_free(btr_search_sys->hash_index[i]->heap);
278 + hash_table_free(btr_search_sys->hash_index[i]);
280 + rw_lock_free(btr_search_latch_part[i]);
282 + mem_free(btr_search_latch_part[i]);
285 + //rw_lock_free(&btr_search_latch);
286 + //mem_free(btr_search_latch_temp);
287 + //btr_search_latch_temp = NULL;
288 mem_free(btr_search_sys);
289 btr_search_sys = NULL;
292 /*====================*/
294 mutex_enter(&btr_search_enabled_mutex);
295 - rw_lock_x_lock(&btr_search_latch);
296 + btr_search_x_lock_all();
298 /* Disable access to hash index, also tell ha_insert_for_fold()
299 stop adding new nodes to hash index, but still allow updating
301 /* btr_search_enabled_mutex should guarantee this. */
302 ut_ad(!btr_search_enabled);
304 - rw_lock_x_unlock(&btr_search_latch);
305 + btr_search_x_unlock_all();
306 mutex_exit(&btr_search_enabled_mutex);
309 @@ -242,12 +267,12 @@
310 /*====================*/
312 mutex_enter(&btr_search_enabled_mutex);
313 - rw_lock_x_lock(&btr_search_latch);
314 + btr_search_x_lock_all();
316 btr_search_enabled = TRUE;
317 btr_search_fully_disabled = FALSE;
319 - rw_lock_x_unlock(&btr_search_latch);
320 + btr_search_x_unlock_all();
321 mutex_exit(&btr_search_enabled_mutex);
324 @@ -300,20 +325,21 @@
326 btr_search_info_get_ref_count(
327 /*==========================*/
328 - btr_search_t* info) /*!< in: search info. */
329 + btr_search_t* info, /*!< in: search info. */
336 #ifdef UNIV_SYNC_DEBUG
337 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
338 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
339 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
340 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
341 #endif /* UNIV_SYNC_DEBUG */
343 - rw_lock_s_lock(&btr_search_latch);
344 + rw_lock_s_lock(btr_search_get_latch(key));
345 ret = info->ref_count;
346 - rw_lock_s_unlock(&btr_search_latch);
347 + rw_lock_s_unlock(btr_search_get_latch(key));
354 #ifdef UNIV_SYNC_DEBUG
355 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
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_SHARED));
358 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
359 #endif /* UNIV_SYNC_DEBUG */
361 index = cursor->index;
365 #ifdef UNIV_SYNC_DEBUG
366 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
367 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
368 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
369 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
370 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
371 || rw_lock_own(&block->lock, RW_LOCK_EX));
372 #endif /* UNIV_SYNC_DEBUG */
375 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
376 #ifdef UNIV_SYNC_DEBUG
377 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
378 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
379 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
380 || rw_lock_own(&(block->lock), RW_LOCK_EX));
381 #endif /* UNIV_SYNC_DEBUG */
382 @@ -578,10 +604,10 @@
385 #ifdef UNIV_SYNC_DEBUG
386 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
387 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
388 #endif /* UNIV_SYNC_DEBUG */
390 - ha_insert_for_fold(btr_search_sys->hash_index, fold,
391 + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
398 #ifdef UNIV_SYNC_DEBUG
399 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
400 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
401 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
402 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
403 #endif /* UNIV_SYNC_DEBUG */
405 block = btr_cur_get_block(cursor);
408 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
410 - btr_search_check_free_space_in_heap();
411 + btr_search_check_free_space_in_heap(cursor->index->id);
414 if (cursor->flag == BTR_CUR_HASH_FAIL) {
415 @@ -633,11 +659,11 @@
416 btr_search_n_hash_fail++;
417 #endif /* UNIV_SEARCH_PERF_STAT */
419 - rw_lock_x_lock(&btr_search_latch);
420 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
422 btr_search_update_hash_ref(info, block, cursor);
424 - rw_lock_x_unlock(&btr_search_latch);
425 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
429 @@ -881,17 +907,17 @@
430 cursor->flag = BTR_CUR_HASH;
432 if (UNIV_LIKELY(!has_search_latch)) {
433 - rw_lock_s_lock(&btr_search_latch);
434 + rw_lock_s_lock(btr_search_get_latch(index_id));
436 if (UNIV_UNLIKELY(!btr_search_enabled)) {
441 - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
442 - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
443 + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
444 + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
446 - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
447 + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
449 if (UNIV_UNLIKELY(!rec)) {
455 - rw_lock_s_unlock(&btr_search_latch);
456 + rw_lock_s_unlock(btr_search_get_latch(index_id));
458 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
460 @@ -1006,7 +1032,7 @@
461 /*-------------------------------------------*/
463 if (UNIV_LIKELY(!has_search_latch)) {
464 - rw_lock_s_unlock(&btr_search_latch);
465 + rw_lock_s_unlock(btr_search_get_latch(index_id));
468 cursor->flag = BTR_CUR_HASH_FAIL;
469 @@ -1029,10 +1055,11 @@
471 btr_search_drop_page_hash_index(
472 /*============================*/
473 - buf_block_t* block) /*!< in: block containing index page,
474 + buf_block_t* block, /*!< in: block containing index page,
475 s- or x-latched, or an index page
476 for which we know that
477 block->buf_fix_count == 0 */
478 + dict_index_t* index_in)
482 @@ -1051,22 +1078,60 @@
485 #ifdef UNIV_SYNC_DEBUG
486 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
487 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
489 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
490 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
492 #endif /* UNIV_SYNC_DEBUG */
495 - rw_lock_s_lock(&btr_search_latch);
498 + rw_lock_s_lock(btr_search_get_latch(index->id));
499 + } else if (btr_search_index_num > 1) {
500 + rw_lock_t* btr_search_latch;
502 + /* FIXME: This may be optimistic implementation still. */
503 + btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
504 + if (UNIV_LIKELY(!btr_search_latch)) {
505 + if (block->is_hashed) {
510 + rw_lock_s_lock(btr_search_latch);
511 + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
512 + rw_lock_s_unlock(btr_search_latch);
515 + if (UNIV_LIKELY(!block->is_hashed)) {
516 + rw_lock_s_unlock(btr_search_latch);
519 + index = block->index;
520 + ut_a(btr_search_latch == btr_search_get_latch(index->id));
522 + /* btr_search_index_num == 1 */
523 + /* btr_search_latch is only one and able to obtain
524 + before evaluating block->is_hashed. */
525 + rw_lock_s_lock(btr_search_latch_part[0]);
526 + if (UNIV_LIKELY(!block->is_hashed)) {
527 + rw_lock_s_unlock(btr_search_latch_part[0]);
530 + index = block->index;
535 if (UNIV_LIKELY(!block->is_hashed)) {
537 - rw_lock_s_unlock(&btr_search_latch);
538 + rw_lock_s_unlock(btr_search_get_latch(index->id));
543 - table = btr_search_sys->hash_index;
544 + table = btr_search_get_hash_index(index->id);
546 #ifdef UNIV_SYNC_DEBUG
547 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
548 @@ -1076,14 +1141,14 @@
550 n_fields = block->curr_n_fields;
551 n_bytes = block->curr_n_bytes;
552 - index = block->index;
553 + ut_a(index == block->index);
554 ut_a(!dict_index_is_ibuf(index));
556 /* NOTE: The fields of block must not be accessed after
557 releasing btr_search_latch, as the index page might only
560 - rw_lock_s_unlock(&btr_search_latch);
561 + rw_lock_s_unlock(btr_search_get_latch(index->id));
563 ut_a(n_fields + n_bytes > 0);
565 @@ -1133,7 +1198,7 @@
569 - rw_lock_x_lock(&btr_search_latch);
570 + rw_lock_x_lock(btr_search_get_latch(index->id));
572 if (UNIV_UNLIKELY(!block->is_hashed)) {
573 /* Someone else has meanwhile dropped the hash index */
574 @@ -1149,7 +1214,7 @@
575 /* Someone else has meanwhile built a new hash index on the
576 page, with different parameters */
578 - rw_lock_x_unlock(&btr_search_latch);
579 + rw_lock_x_unlock(btr_search_get_latch(index->id));
583 @@ -1165,6 +1230,7 @@
585 block->is_hashed = FALSE;
587 + block->btr_search_latch = NULL;
590 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
591 @@ -1177,14 +1243,14 @@
592 "InnoDB: the hash index to a page of %s,"
593 " still %lu hash nodes remain.\n",
594 index->name, (ulong) block->n_pointers);
595 - rw_lock_x_unlock(&btr_search_latch);
596 + rw_lock_x_unlock(btr_search_get_latch(index->id));
598 btr_search_validate();
600 - rw_lock_x_unlock(&btr_search_latch);
601 + rw_lock_x_unlock(btr_search_get_latch(index->id));
603 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
604 - rw_lock_x_unlock(&btr_search_latch);
605 + rw_lock_x_unlock(btr_search_get_latch(index->id));
606 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
609 @@ -1216,9 +1282,9 @@
611 ibool released_search_latch;
613 - rw_lock_s_lock(&btr_search_latch);
614 + rw_lock_s_lock(btr_search_get_latch(index->id));
616 - table = btr_search_sys->hash_index;
617 + table = btr_search_get_hash_index(index->id);
619 for (j = 0; j < srv_buf_pool_instances; j++) {
620 buf_pool_t* buf_pool;
621 @@ -1252,7 +1318,7 @@
624 /* keeping latch order */
625 - rw_lock_s_unlock(&btr_search_latch);
626 + rw_lock_s_unlock(btr_search_get_latch(index->id));
627 released_search_latch = TRUE;
628 rw_lock_x_lock(&block->lock);
630 @@ -1304,7 +1370,7 @@
631 mem_heap_empty(heap);
634 - rw_lock_x_lock(&btr_search_latch);
635 + rw_lock_x_lock(btr_search_get_latch(index->id));
637 if (UNIV_UNLIKELY(!block->is_hashed)) {
639 @@ -1314,12 +1380,12 @@
641 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
642 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
643 - rw_lock_x_unlock(&btr_search_latch);
644 + rw_lock_x_unlock(btr_search_get_latch(index->id));
645 rw_lock_x_unlock(&block->lock);
649 - rw_lock_s_lock(&btr_search_latch);
650 + rw_lock_s_lock(btr_search_get_latch(index->id));
654 @@ -1333,6 +1399,7 @@
656 block->is_hashed = FALSE;
658 + block->btr_search_latch = NULL;
661 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
662 @@ -1345,18 +1412,18 @@
663 index->name, (ulong) block->n_pointers);
665 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
666 - rw_lock_x_unlock(&btr_search_latch);
667 + rw_lock_x_unlock(btr_search_get_latch(index->id));
668 rw_lock_x_unlock(&block->lock);
672 - rw_lock_s_lock(&btr_search_latch);
673 + rw_lock_s_lock(btr_search_get_latch(index->id));
676 } while (released_search_latch);
679 - rw_lock_s_unlock(&btr_search_latch);
680 + rw_lock_s_unlock(btr_search_get_latch(index->id));
682 if (UNIV_LIKELY_NULL(heap)) {
684 @@ -1403,7 +1470,7 @@
686 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
688 - btr_search_drop_page_hash_index(block);
689 + btr_search_drop_page_hash_index(block, NULL);
693 @@ -1445,26 +1512,26 @@
695 ut_a(!dict_index_is_ibuf(index));
697 - table = btr_search_sys->hash_index;
698 + table = btr_search_get_hash_index(index->id);
699 page = buf_block_get_frame(block);
701 #ifdef UNIV_SYNC_DEBUG
702 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
703 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
704 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
705 || rw_lock_own(&(block->lock), RW_LOCK_EX));
706 #endif /* UNIV_SYNC_DEBUG */
708 - rw_lock_s_lock(&btr_search_latch);
709 + rw_lock_s_lock(btr_search_get_latch(index->id));
711 if (block->is_hashed && ((block->curr_n_fields != n_fields)
712 || (block->curr_n_bytes != n_bytes)
713 || (block->curr_left_side != left_side))) {
715 - rw_lock_s_unlock(&btr_search_latch);
716 + rw_lock_s_unlock(btr_search_get_latch(index->id));
718 - btr_search_drop_page_hash_index(block);
719 + btr_search_drop_page_hash_index(block, index);
721 - rw_lock_s_unlock(&btr_search_latch);
722 + rw_lock_s_unlock(btr_search_get_latch(index->id));
725 n_recs = page_get_n_recs(page);
726 @@ -1558,9 +1625,9 @@
730 - btr_search_check_free_space_in_heap();
731 + btr_search_check_free_space_in_heap(index->id);
733 - rw_lock_x_lock(&btr_search_latch);
734 + rw_lock_x_lock(btr_search_get_latch(index->id));
736 if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
738 @@ -1588,6 +1655,7 @@
739 block->curr_n_bytes = n_bytes;
740 block->curr_left_side = left_side;
741 block->index = index;
742 + block->btr_search_latch = btr_search_get_latch(index->id);
744 for (i = 0; i < n_cached; i++) {
746 @@ -1595,7 +1663,7 @@
750 - rw_lock_x_unlock(&btr_search_latch);
751 + rw_lock_x_unlock(btr_search_get_latch(index->id));
755 @@ -1634,13 +1702,13 @@
756 ut_a(!(new_block->is_hashed || block->is_hashed)
757 || !dict_index_is_ibuf(index));
759 - rw_lock_s_lock(&btr_search_latch);
760 + rw_lock_s_lock(btr_search_get_latch(index->id));
762 if (new_block->is_hashed) {
764 - rw_lock_s_unlock(&btr_search_latch);
765 + rw_lock_s_unlock(btr_search_get_latch(index->id));
767 - btr_search_drop_page_hash_index(block);
768 + btr_search_drop_page_hash_index(block, index);
772 @@ -1655,7 +1723,7 @@
773 new_block->n_bytes = block->curr_n_bytes;
774 new_block->left_side = left_side;
776 - rw_lock_s_unlock(&btr_search_latch);
777 + rw_lock_s_unlock(btr_search_get_latch(index->id));
779 ut_a(n_fields + n_bytes > 0);
781 @@ -1667,7 +1735,7 @@
785 - rw_lock_s_unlock(&btr_search_latch);
786 + rw_lock_s_unlock(btr_search_get_latch(index->id));
789 /********************************************************************//**
790 @@ -1706,7 +1774,7 @@
791 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
792 ut_a(!dict_index_is_ibuf(cursor->index));
794 - table = btr_search_sys->hash_index;
795 + table = btr_search_get_hash_index(cursor->index->id);
797 index_id = cursor->index->id;
798 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
799 @@ -1715,11 +1783,11 @@
800 if (UNIV_LIKELY_NULL(heap)) {
803 - rw_lock_x_lock(&btr_search_latch);
804 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
806 ha_search_and_delete_if_found(table, fold, rec);
808 - rw_lock_x_unlock(&btr_search_latch);
809 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
812 /********************************************************************//**
813 @@ -1753,21 +1821,21 @@
814 ut_a(block->index == cursor->index);
815 ut_a(!dict_index_is_ibuf(cursor->index));
817 - rw_lock_x_lock(&btr_search_latch);
818 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
820 if ((cursor->flag == BTR_CUR_HASH)
821 && (cursor->n_fields == block->curr_n_fields)
822 && (cursor->n_bytes == block->curr_n_bytes)
823 && !block->curr_left_side) {
825 - table = btr_search_sys->hash_index;
826 + table = btr_search_get_hash_index(cursor->index->id);
828 ha_search_and_update_if_found(table, cursor->fold, rec,
829 block, page_rec_get_next(rec));
831 - rw_lock_x_unlock(&btr_search_latch);
832 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
834 - rw_lock_x_unlock(&btr_search_latch);
835 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
837 btr_search_update_hash_on_insert(cursor);
839 @@ -1802,9 +1870,9 @@
840 ulint* offsets = offsets_;
841 rec_offs_init(offsets_);
843 - table = btr_search_sys->hash_index;
844 + table = btr_search_get_hash_index(cursor->index->id);
846 - btr_search_check_free_space_in_heap();
847 + btr_search_check_free_space_in_heap(cursor->index->id);
849 rec = btr_cur_get_rec(cursor);
851 @@ -1849,7 +1917,7 @@
855 - rw_lock_x_lock(&btr_search_latch);
856 + rw_lock_x_lock(btr_search_get_latch(index_id));
860 @@ -1863,7 +1931,7 @@
864 - rw_lock_x_lock(&btr_search_latch);
865 + rw_lock_x_lock(btr_search_get_latch(index_id));
869 @@ -1881,7 +1949,7 @@
873 - rw_lock_x_lock(&btr_search_latch);
874 + rw_lock_x_lock(btr_search_get_latch(index_id));
878 @@ -1896,7 +1964,7 @@
882 - rw_lock_x_lock(&btr_search_latch);
883 + rw_lock_x_lock(btr_search_get_latch(index_id));
887 @@ -1919,7 +1987,7 @@
891 - rw_lock_x_unlock(&btr_search_latch);
892 + rw_lock_x_unlock(btr_search_get_latch(index_id));
896 @@ -1935,7 +2003,7 @@
898 ulint n_page_dumps = 0;
903 mem_heap_t* heap = NULL;
904 ulint offsets_[REC_OFFS_NORMAL_SIZE];
905 @@ -1947,23 +2015,25 @@
907 rec_offs_init(offsets_);
909 - rw_lock_x_lock(&btr_search_latch);
910 + btr_search_x_lock_all();
911 buf_pool_page_hash_x_lock_all();
913 - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
914 + for (j = 0; j < btr_search_index_num; j++) {
916 + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
918 for (i = 0; i < cell_count; i++) {
919 /* We release btr_search_latch every once in a while to
920 give other queries a chance to run. */
921 if ((i != 0) && ((i % chunk_size) == 0)) {
922 buf_pool_page_hash_x_unlock_all();
923 - rw_lock_x_unlock(&btr_search_latch);
924 + btr_search_x_unlock_all();
926 - rw_lock_x_lock(&btr_search_latch);
927 + btr_search_x_lock_all();
928 buf_pool_page_hash_x_lock_all();
931 - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
932 + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
934 for (; node != NULL; node = node->next) {
935 const buf_block_t* block
936 @@ -2072,19 +2142,21 @@
937 give other queries a chance to run. */
939 buf_pool_page_hash_x_unlock_all();
940 - rw_lock_x_unlock(&btr_search_latch);
941 + btr_search_x_unlock_all();
943 - rw_lock_x_lock(&btr_search_latch);
944 + btr_search_x_lock_all();
945 buf_pool_page_hash_x_lock_all();
948 - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
949 + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
954 + } /*for (j = 0; j < btr_search_index_num; j++)*/
956 buf_pool_page_hash_x_unlock_all();
957 - rw_lock_x_unlock(&btr_search_latch);
958 + btr_search_x_unlock_all();
959 if (UNIV_LIKELY_NULL(heap)) {
962 diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
963 --- a/storage/innobase/buf/buf0buf.c 2010-12-04 15:55:21.351597052 +0900
964 +++ b/storage/innobase/buf/buf0buf.c 2010-12-04 16:12:48.654550708 +0900
967 block->check_index_page_at_flush = FALSE;
969 + block->btr_search_latch = NULL;
971 block->is_hashed = FALSE;
973 @@ -1477,7 +1478,7 @@
974 /* To follow the latching order, we
975 have to release btr_search_latch
976 before acquiring block->latch. */
977 - rw_lock_x_unlock(&btr_search_latch);
978 + btr_search_x_unlock_all();
979 /* When we release the search latch,
980 we must rescan all blocks, because
981 some may become hashed again. */
982 @@ -1508,11 +1509,11 @@
983 anything. block->is_hashed can only
984 be set on uncompressed file pages. */
986 - btr_search_drop_page_hash_index(block);
987 + btr_search_drop_page_hash_index(block, NULL);
989 rw_lock_x_unlock(&block->lock);
991 - rw_lock_x_lock(&btr_search_latch);
992 + btr_search_x_lock_all();
994 ut_ad(!btr_search_enabled);
996 @@ -1531,7 +1532,11 @@
997 ibool released_search_latch;
999 #ifdef UNIV_SYNC_DEBUG
1000 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1003 + for (j = 0; j < btr_search_index_num; j++) {
1004 + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
1006 #endif /* UNIV_SYNC_DEBUG */
1007 ut_ad(!btr_search_enabled);
1009 @@ -2635,6 +2640,7 @@
1011 block->check_index_page_at_flush = FALSE;
1012 block->index = NULL;
1013 + block->btr_search_latch = NULL;
1015 block->n_hash_helps = 0;
1016 block->is_hashed = FALSE;
1017 diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
1018 --- a/storage/innobase/buf/buf0lru.c 2010-12-04 15:35:29.137347521 +0900
1019 +++ b/storage/innobase/buf/buf0lru.c 2010-12-04 16:12:48.658550840 +0900
1020 @@ -1775,7 +1775,7 @@
1022 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1024 - btr_search_drop_page_hash_index((buf_block_t*) bpage);
1025 + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1026 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1029 diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
1030 --- a/storage/innobase/dict/dict0dict.c 2010-12-04 15:52:23.398513916 +0900
1031 +++ b/storage/innobase/dict/dict0dict.c 2010-12-04 16:12:48.662550715 +0900
1032 @@ -1806,7 +1806,7 @@
1036 - ulint ref_count = btr_search_info_get_ref_count(info);
1037 + ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1038 if (ref_count == 0) {
1041 diff -ruN a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c
1042 --- a/storage/innobase/ha/ha0ha.c 2010-11-03 07:01:13.000000000 +0900
1043 +++ b/storage/innobase/ha/ha0ha.c 2010-12-04 16:12:48.665593752 +0900
1046 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1047 #ifdef UNIV_SYNC_DEBUG
1048 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1049 + /* cannot identificate which btr_search_latch[i] for now */
1050 + //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1051 #endif /* UNIV_SYNC_DEBUG */
1053 #ifndef UNIV_HOTBACKUP
1054 diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
1055 --- a/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:20.185850734 +0900
1056 +++ b/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:48.674552412 +0900
1057 @@ -11617,6 +11617,11 @@
1058 "Disable with --skip-innodb-adaptive-hash-index.",
1059 NULL, innodb_adaptive_hash_index_update, TRUE);
1061 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1062 + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1063 + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1064 + NULL, NULL, 1, 1, 32, 0);
1066 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1067 PLUGIN_VAR_RQCMDARG,
1068 "Replication thread delay (ms) on the slave server if "
1069 @@ -11964,6 +11969,7 @@
1070 MYSQL_SYSVAR(use_sys_stats_table),
1071 MYSQL_SYSVAR(stats_sample_pages),
1072 MYSQL_SYSVAR(adaptive_hash_index),
1073 + MYSQL_SYSVAR(adaptive_hash_index_partitions),
1074 MYSQL_SYSVAR(replication_delay),
1075 MYSQL_SYSVAR(status_file),
1076 MYSQL_SYSVAR(strict_mode),
1077 diff -ruN a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
1078 --- a/storage/innobase/include/btr0sea.h 2010-12-03 15:48:03.070987226 +0900
1079 +++ b/storage/innobase/include/btr0sea.h 2010-12-04 16:12:48.707551382 +0900
1082 btr_search_info_get_ref_count(
1083 /*==========================*/
1084 - btr_search_t* info); /*!< in: search info. */
1085 + btr_search_t* info, /*!< in: search info. */
1087 /*********************************************************************//**
1088 Updates the search info. */
1090 @@ -136,10 +137,11 @@
1092 btr_search_drop_page_hash_index(
1093 /*============================*/
1094 - buf_block_t* block); /*!< in: block containing index page,
1095 + buf_block_t* block, /*!< in: block containing index page,
1096 s- or x-latched, or an index page
1097 for which we know that
1098 block->buf_fix_count == 0 */
1099 + dict_index_t* index_in);
1100 /************************************************************************
1101 Drops a page hash index based on index */
1103 @@ -199,10 +201,47 @@
1104 # define btr_search_validate() TRUE
1105 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1107 +/********************************************************************//**
1108 +New functions to control split btr_search_index */
1111 +btr_search_get_hash_index(
1112 +/*======================*/
1117 +btr_search_get_latch(
1118 +/*=================*/
1123 +btr_search_x_lock_all(void);
1124 +/*========================*/
1128 +btr_search_x_unlock_all(void);
1129 +/*==========================*/
1133 +btr_search_s_lock_all(void);
1134 +/*========================*/
1138 +btr_search_s_unlock_all(void);
1139 +/*==========================*/
1142 /** Flag: has the search system been enabled?
1143 Protected by btr_search_latch and btr_search_enabled_mutex. */
1144 extern char btr_search_enabled;
1146 +extern ulint btr_search_index_num;
1148 /** Flag: whether the search system has completed its disabling process,
1149 It is set to TRUE right after buf_pool_drop_hash_index() in
1150 btr_search_disable(), indicating hash index entries are cleaned up.
1153 /** The hash index system */
1154 struct btr_search_sys_struct{
1155 - hash_table_t* hash_index; /*!< the adaptive hash index,
1156 + hash_table_t** hash_index; /*!< the adaptive hash index,
1157 mapping dtuple_fold values
1158 to rec_t pointers on index pages */
1160 @@ -290,10 +329,12 @@
1162 Bear in mind (3) and (4) when using the hash index.
1164 -extern rw_lock_t* btr_search_latch_temp;
1165 +//extern rw_lock_t* btr_search_latch_temp;
1167 +extern rw_lock_t** btr_search_latch_part;
1169 /** The latch protecting the adaptive search system */
1170 -#define btr_search_latch (*btr_search_latch_temp)
1171 +//#define btr_search_latch (*btr_search_latch_temp)
1173 #ifdef UNIV_SEARCH_PERF_STAT
1174 /** Number of successful adaptive hash index lookups */
1175 diff -ruN a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic
1176 --- a/storage/innobase/include/btr0sea.ic 2010-11-03 07:01:13.000000000 +0900
1177 +++ b/storage/innobase/include/btr0sea.ic 2010-12-04 16:12:48.709511202 +0900
1181 #ifdef UNIV_SYNC_DEBUG
1182 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1183 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1184 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1185 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1186 #endif /* UNIV_SYNC_DEBUG */
1188 info = btr_search_get_info(index);
1191 btr_search_info_update_slow(info, cursor);
1194 +/*********************************************************************//**
1195 +New functions to control split btr_search_index */
1198 +btr_search_get_hash_index(
1199 +/*======================*/
1202 + return(btr_search_sys->hash_index[key % btr_search_index_num]);
1207 +btr_search_get_latch(
1208 +/*=================*/
1211 + return(btr_search_latch_part[key % btr_search_index_num]);
1216 +btr_search_x_lock_all(void)
1217 +/*=======================*/
1221 + for (i = 0; i < btr_search_index_num; i++) {
1222 + rw_lock_x_lock(btr_search_latch_part[i]);
1228 +btr_search_x_unlock_all(void)
1229 +/*==========================*/
1233 + for (i = 0; i < btr_search_index_num; i++) {
1234 + rw_lock_x_unlock(btr_search_latch_part[i]);
1240 +btr_search_s_lock_all(void)
1241 +/*=======================*/
1245 + for (i = 0; i < btr_search_index_num; i++) {
1246 + rw_lock_s_lock(btr_search_latch_part[i]);
1252 +btr_search_s_unlock_all(void)
1253 +/*=========================*/
1257 + for (i = 0; i < btr_search_index_num; i++) {
1258 + rw_lock_s_unlock(btr_search_latch_part[i]);
1262 diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
1263 --- a/storage/innobase/include/buf0buf.h 2010-12-15 19:00:07.713604580 +0900
1264 +++ b/storage/innobase/include/buf0buf.h 2010-12-15 20:58:03.546839883 +0900
1265 @@ -1544,7 +1544,7 @@
1266 pointers in the adaptive hash index
1267 pointing to this frame */
1268 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1269 - unsigned is_hashed:1; /*!< TRUE if hash index has
1270 + volatile unsigned is_hashed:1; /*!< TRUE if hash index has
1271 already been built on this
1272 page; note that it does not
1273 guarantee that the index is
1274 @@ -1558,6 +1558,7 @@
1275 unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1276 dict_index_t* index; /*!< Index for which the adaptive
1277 hash index has been created. */
1278 + volatile rw_lock_t* btr_search_latch;
1280 # ifdef UNIV_SYNC_DEBUG
1281 /** @name Debug fields */
1282 diff -ruN a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic
1283 --- a/storage/innobase/include/row0upd.ic 2010-11-03 07:01:13.000000000 +0900
1284 +++ b/storage/innobase/include/row0upd.ic 2010-12-04 16:12:48.710551113 +0900
1286 ut_ad(dict_index_is_clust(index));
1287 ut_ad(rec_offs_validate(rec, index, offsets));
1288 #ifdef UNIV_SYNC_DEBUG
1289 - if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
1290 + if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) {
1291 ut_ad(!buf_block_align(rec)->is_hashed);
1293 #endif /* UNIV_SYNC_DEBUG */
1294 diff -ruN a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c
1295 --- a/storage/innobase/page/page0page.c 2010-11-03 07:01:13.000000000 +0900
1296 +++ b/storage/innobase/page/page0page.c 2010-12-04 16:12:48.712550963 +0900
1298 const ibool is_hashed = block->is_hashed;
1301 - rw_lock_x_lock(&btr_search_latch);
1302 + rw_lock_x_lock(btr_search_get_latch(block->index->id));
1305 ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1308 #ifndef UNIV_HOTBACKUP
1310 - rw_lock_x_unlock(&btr_search_latch);
1311 + rw_lock_x_unlock(btr_search_get_latch(block->index->id));
1313 #endif /* !UNIV_HOTBACKUP */
1315 diff -ruN a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
1316 --- a/storage/innobase/page/page0zip.c 2010-12-04 15:57:13.061494433 +0900
1317 +++ b/storage/innobase/page/page0zip.c 2010-12-04 16:12:48.716470334 +0900
1318 @@ -4445,7 +4445,7 @@
1320 #ifndef UNIV_HOTBACKUP
1321 temp_block = buf_block_alloc(buf_pool, 0);
1322 - btr_search_drop_page_hash_index(block);
1323 + btr_search_drop_page_hash_index(block, index);
1324 block->check_index_page_at_flush = TRUE;
1325 #else /* !UNIV_HOTBACKUP */
1326 ut_ad(block == back_block1);
1327 diff -ruN a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
1328 --- a/storage/innobase/row/row0sel.c 2010-12-04 16:09:53.204513572 +0900
1329 +++ b/storage/innobase/row/row0sel.c 2010-12-04 16:12:48.722551273 +0900
1330 @@ -1210,7 +1210,7 @@
1331 ut_ad(plan->unique_search);
1332 ut_ad(!plan->must_get_clust);
1333 #ifdef UNIV_SYNC_DEBUG
1334 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1335 + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1336 #endif /* UNIV_SYNC_DEBUG */
1338 row_sel_open_pcur(plan, TRUE, mtr);
1339 @@ -1381,10 +1381,10 @@
1340 && !plan->must_get_clust
1341 && !plan->table->big_rows) {
1342 if (!search_latch_locked) {
1343 - rw_lock_s_lock(&btr_search_latch);
1344 + rw_lock_s_lock(btr_search_get_latch(index->id));
1346 search_latch_locked = TRUE;
1347 - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1348 + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1350 /* There is an x-latch request waiting: release the
1351 s-latch for a moment; as an s-latch here is often
1352 @@ -1393,8 +1393,8 @@
1353 from acquiring an s-latch for a long time, lowering
1354 performance significantly in multiprocessors. */
1356 - rw_lock_s_unlock(&btr_search_latch);
1357 - rw_lock_s_lock(&btr_search_latch);
1358 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1359 + rw_lock_s_lock(btr_search_get_latch(index->id));
1362 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1363 @@ -1417,7 +1417,7 @@
1366 if (search_latch_locked) {
1367 - rw_lock_s_unlock(&btr_search_latch);
1368 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1370 search_latch_locked = FALSE;
1372 @@ -1993,7 +1993,7 @@
1375 if (search_latch_locked) {
1376 - rw_lock_s_unlock(&btr_search_latch);
1377 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1379 if (UNIV_LIKELY_NULL(heap)) {
1380 mem_heap_free(heap);
1381 @@ -3356,6 +3356,8 @@
1382 /* if the returned record was locked and we did a semi-consistent
1383 read (fetch the newest committed version), then this is set to
1386 + ulint should_release;
1387 #ifdef UNIV_SEARCH_DEBUG
1389 #endif /* UNIV_SEARCH_DEBUG */
1390 @@ -3441,18 +3443,32 @@
1391 /* PHASE 0: Release a possible s-latch we are holding on the
1392 adaptive hash index latch if there is someone waiting behind */
1394 - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1395 - && trx->has_search_latch) {
1396 + should_release = 0;
1397 + for (i = 0; i < btr_search_index_num; i++) {
1398 + if ((trx->has_search_latch & ((ulint)1 << i))
1399 + && rw_lock_get_writer(btr_search_latch_part[i])
1400 + != RW_LOCK_NOT_LOCKED) {
1401 + should_release |= ((ulint)1 << i);
1405 + if (should_release) {
1407 /* There is an x-latch request on the adaptive hash index:
1408 release the s-latch to reduce starvation and wait for
1409 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1412 - rw_lock_s_unlock(&btr_search_latch);
1413 - trx->has_search_latch = FALSE;
1414 + for (i = 0; i < btr_search_index_num; i++) {
1415 + if (should_release & ((ulint)1 << i)) {
1416 + rw_lock_s_unlock(btr_search_latch_part[i]);
1417 + trx->has_search_latch &= ~((ulint)1 << i);
1421 + if (!trx->has_search_latch) {
1422 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1426 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1427 @@ -3603,9 +3619,11 @@
1428 hash index semaphore! */
1430 #ifndef UNIV_SEARCH_DEBUG
1431 - if (!trx->has_search_latch) {
1432 - rw_lock_s_lock(&btr_search_latch);
1433 - trx->has_search_latch = TRUE;
1434 + if (!(trx->has_search_latch
1435 + & ((ulint)1 << (index->id % btr_search_index_num)))) {
1436 + rw_lock_s_lock(btr_search_get_latch(index->id));
1437 + trx->has_search_latch |=
1438 + (ulint)1 << (index->id % btr_search_index_num);
1441 switch (row_sel_try_search_shortcut_for_mysql(
1442 @@ -3666,7 +3684,11 @@
1444 trx->search_latch_timeout--;
1446 - rw_lock_s_unlock(&btr_search_latch);
1447 + for (i = 0; i < btr_search_index_num; i++) {
1448 + if (trx->has_search_latch & ((ulint)1 << i)) {
1449 + rw_lock_s_unlock(btr_search_latch_part[i]);
1452 trx->has_search_latch = FALSE;
1455 @@ -3690,7 +3712,12 @@
1456 /* PHASE 3: Open or restore index cursor position */
1458 if (trx->has_search_latch) {
1459 - rw_lock_s_unlock(&btr_search_latch);
1461 + for (i = 0; i < btr_search_index_num; i++) {
1462 + if (trx->has_search_latch & ((ulint)1 << i)) {
1463 + rw_lock_s_unlock(btr_search_latch_part[i]);
1466 trx->has_search_latch = FALSE;
1469 diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
1470 --- a/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:20.231484679 +0900
1471 +++ b/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:48.726551018 +0900
1472 @@ -2042,7 +2042,9 @@
1473 "-------------------------------------\n", file);
1476 - ha_print_info(file, btr_search_sys->hash_index);
1477 + for (i = 0; i < btr_search_index_num; i++) {
1478 + ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1482 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1483 @@ -2067,14 +2069,15 @@
1484 ut_total_allocated_memory,
1485 mem_pool_get_reserved(mem_comm_pool));
1486 /* Calcurate reserved memories */
1487 - if (btr_search_sys && btr_search_sys->hash_index->heap) {
1488 - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1489 + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1490 + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1492 btr_search_sys_subtotal = 0;
1493 - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1494 - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1495 + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1496 + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1499 + btr_search_sys_subtotal *= btr_search_index_num;
1501 lock_sys_subtotal = 0;
1503 @@ -2101,10 +2104,10 @@
1504 " Threads %lu \t(%lu + %lu)\n",
1506 (ulong) (btr_search_sys
1507 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1508 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1509 + btr_search_sys_subtotal,
1510 (ulong) (btr_search_sys
1511 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1512 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1513 (ulong) btr_search_sys_subtotal,
1515 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1516 diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
1517 --- a/storage/innobase/sync/sync0sync.c 2010-12-03 17:36:44.300986571 +0900
1518 +++ b/storage/innobase/sync/sync0sync.c 2010-12-04 16:12:48.729513564 +0900
1519 @@ -1183,7 +1183,6 @@
1520 case SYNC_ANY_LATCH:
1521 case SYNC_FILE_FORMAT_TAG:
1522 case SYNC_DOUBLEWRITE:
1523 - case SYNC_SEARCH_SYS:
1524 case SYNC_SEARCH_SYS_CONF:
1525 case SYNC_TRX_LOCK_HEAP:
1527 @@ -1204,6 +1203,7 @@
1531 + case SYNC_SEARCH_SYS:
1532 case SYNC_BUF_LRU_LIST:
1533 case SYNC_BUF_FLUSH_LIST:
1534 case SYNC_BUF_PAGE_HASH:
1535 diff -ruN a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
1536 --- a/storage/innobase/trx/trx0trx.c 2010-12-03 17:49:11.623953784 +0900
1537 +++ b/storage/innobase/trx/trx0trx.c 2010-12-04 16:12:48.731513275 +0900
1538 @@ -266,8 +266,14 @@
1539 /*=================================*/
1540 trx_t* trx) /*!< in: transaction */
1544 if (trx->has_search_latch) {
1545 - rw_lock_s_unlock(&btr_search_latch);
1546 + for (i = 0; i < btr_search_index_num; i++) {
1547 + if (trx->has_search_latch & ((ulint)1 << i)) {
1548 + rw_lock_s_unlock(btr_search_latch_part[i]);
1552 trx->has_search_latch = FALSE;