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);
35 btr_blob_dbg_remove(page, index, "btr_page_empty");
37 /* Recreate the page: note that global data on page (possible
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 @@ -1971,7 +1971,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 @@ -1985,7 +1985,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 @@ -2763,7 +2763,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 @@ -2779,7 +2779,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 @@ -2906,13 +2906,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);
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,22 @@
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]);
284 + mem_free(btr_search_sys->hash_index);
285 + mem_free(btr_search_latch_part);
287 + //rw_lock_free(&btr_search_latch);
288 + //mem_free(btr_search_latch_temp);
289 + //btr_search_latch_temp = NULL;
290 mem_free(btr_search_sys);
291 btr_search_sys = NULL;
294 /*====================*/
296 mutex_enter(&btr_search_enabled_mutex);
297 - rw_lock_x_lock(&btr_search_latch);
298 + btr_search_x_lock_all();
300 /* Disable access to hash index, also tell ha_insert_for_fold()
301 stop adding new nodes to hash index, but still allow updating
303 /* btr_search_enabled_mutex should guarantee this. */
304 ut_ad(!btr_search_enabled);
306 - rw_lock_x_unlock(&btr_search_latch);
307 + btr_search_x_unlock_all();
308 mutex_exit(&btr_search_enabled_mutex);
311 @@ -242,12 +269,12 @@
312 /*====================*/
314 mutex_enter(&btr_search_enabled_mutex);
315 - rw_lock_x_lock(&btr_search_latch);
316 + btr_search_x_lock_all();
318 btr_search_enabled = TRUE;
319 btr_search_fully_disabled = FALSE;
321 - rw_lock_x_unlock(&btr_search_latch);
322 + btr_search_x_unlock_all();
323 mutex_exit(&btr_search_enabled_mutex);
326 @@ -300,20 +327,21 @@
328 btr_search_info_get_ref_count(
329 /*==========================*/
330 - btr_search_t* info) /*!< in: search info. */
331 + btr_search_t* info, /*!< in: search info. */
338 #ifdef UNIV_SYNC_DEBUG
339 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
340 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
341 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
342 + ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
343 #endif /* UNIV_SYNC_DEBUG */
345 - rw_lock_s_lock(&btr_search_latch);
346 + rw_lock_s_lock(btr_search_get_latch(key));
347 ret = info->ref_count;
348 - rw_lock_s_unlock(&btr_search_latch);
349 + rw_lock_s_unlock(btr_search_get_latch(key));
356 #ifdef UNIV_SYNC_DEBUG
357 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
358 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
359 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
360 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
361 #endif /* UNIV_SYNC_DEBUG */
363 index = cursor->index;
367 #ifdef UNIV_SYNC_DEBUG
368 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
369 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
370 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
371 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
372 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
373 || rw_lock_own(&block->lock, RW_LOCK_EX));
374 #endif /* UNIV_SYNC_DEBUG */
377 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
378 #ifdef UNIV_SYNC_DEBUG
379 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
380 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
381 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
382 || rw_lock_own(&(block->lock), RW_LOCK_EX));
383 #endif /* UNIV_SYNC_DEBUG */
384 @@ -578,10 +606,10 @@
387 #ifdef UNIV_SYNC_DEBUG
388 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
389 + ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
390 #endif /* UNIV_SYNC_DEBUG */
392 - ha_insert_for_fold(btr_search_sys->hash_index, fold,
393 + ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
400 #ifdef UNIV_SYNC_DEBUG
401 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
402 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
403 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
404 + ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
405 #endif /* UNIV_SYNC_DEBUG */
407 block = btr_cur_get_block(cursor);
410 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
412 - btr_search_check_free_space_in_heap();
413 + btr_search_check_free_space_in_heap(cursor->index->id);
416 if (cursor->flag == BTR_CUR_HASH_FAIL) {
417 @@ -633,11 +661,11 @@
418 btr_search_n_hash_fail++;
419 #endif /* UNIV_SEARCH_PERF_STAT */
421 - rw_lock_x_lock(&btr_search_latch);
422 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
424 btr_search_update_hash_ref(info, block, cursor);
426 - rw_lock_x_unlock(&btr_search_latch);
427 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
431 @@ -881,17 +909,17 @@
432 cursor->flag = BTR_CUR_HASH;
434 if (UNIV_LIKELY(!has_search_latch)) {
435 - rw_lock_s_lock(&btr_search_latch);
436 + rw_lock_s_lock(btr_search_get_latch(index_id));
438 if (UNIV_UNLIKELY(!btr_search_enabled)) {
443 - ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
444 - ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
445 + ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
446 + ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
448 - rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
449 + rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
451 if (UNIV_UNLIKELY(!rec)) {
457 - rw_lock_s_unlock(&btr_search_latch);
458 + rw_lock_s_unlock(btr_search_get_latch(index_id));
460 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
462 @@ -1006,7 +1034,7 @@
463 /*-------------------------------------------*/
465 if (UNIV_LIKELY(!has_search_latch)) {
466 - rw_lock_s_unlock(&btr_search_latch);
467 + rw_lock_s_unlock(btr_search_get_latch(index_id));
470 cursor->flag = BTR_CUR_HASH_FAIL;
471 @@ -1029,10 +1057,11 @@
473 btr_search_drop_page_hash_index(
474 /*============================*/
475 - buf_block_t* block) /*!< in: block containing index page,
476 + buf_block_t* block, /*!< in: block containing index page,
477 s- or x-latched, or an index page
478 for which we know that
479 block->buf_fix_count == 0 */
480 + dict_index_t* index_in)
484 @@ -1051,22 +1080,60 @@
487 #ifdef UNIV_SYNC_DEBUG
488 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
489 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
491 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
492 + ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
494 #endif /* UNIV_SYNC_DEBUG */
497 - rw_lock_s_lock(&btr_search_latch);
500 + rw_lock_s_lock(btr_search_get_latch(index->id));
501 + } else if (btr_search_index_num > 1) {
502 + rw_lock_t* btr_search_latch;
504 + /* FIXME: This may be optimistic implementation still. */
505 + btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
506 + if (UNIV_LIKELY(!btr_search_latch)) {
507 + if (block->is_hashed) {
512 + rw_lock_s_lock(btr_search_latch);
513 + if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
514 + rw_lock_s_unlock(btr_search_latch);
517 + if (UNIV_LIKELY(!block->is_hashed)) {
518 + rw_lock_s_unlock(btr_search_latch);
521 + index = block->index;
522 + ut_a(btr_search_latch == btr_search_get_latch(index->id));
524 + /* btr_search_index_num == 1 */
525 + /* btr_search_latch is only one and able to obtain
526 + before evaluating block->is_hashed. */
527 + rw_lock_s_lock(btr_search_latch_part[0]);
528 + if (UNIV_LIKELY(!block->is_hashed)) {
529 + rw_lock_s_unlock(btr_search_latch_part[0]);
532 + index = block->index;
537 if (UNIV_LIKELY(!block->is_hashed)) {
539 - rw_lock_s_unlock(&btr_search_latch);
540 + rw_lock_s_unlock(btr_search_get_latch(index->id));
545 - table = btr_search_sys->hash_index;
546 + table = btr_search_get_hash_index(index->id);
548 #ifdef UNIV_SYNC_DEBUG
549 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
550 @@ -1076,14 +1143,14 @@
552 n_fields = block->curr_n_fields;
553 n_bytes = block->curr_n_bytes;
554 - index = block->index;
555 + ut_a(index == block->index);
556 ut_a(!dict_index_is_ibuf(index));
558 /* NOTE: The fields of block must not be accessed after
559 releasing btr_search_latch, as the index page might only
562 - rw_lock_s_unlock(&btr_search_latch);
563 + rw_lock_s_unlock(btr_search_get_latch(index->id));
565 ut_a(n_fields + n_bytes > 0);
567 @@ -1133,7 +1200,7 @@
571 - rw_lock_x_lock(&btr_search_latch);
572 + rw_lock_x_lock(btr_search_get_latch(index->id));
574 if (UNIV_UNLIKELY(!block->is_hashed)) {
575 /* Someone else has meanwhile dropped the hash index */
576 @@ -1149,7 +1216,7 @@
577 /* Someone else has meanwhile built a new hash index on the
578 page, with different parameters */
580 - rw_lock_x_unlock(&btr_search_latch);
581 + rw_lock_x_unlock(btr_search_get_latch(index->id));
585 @@ -1165,6 +1232,7 @@
587 block->is_hashed = FALSE;
589 + block->btr_search_latch = NULL;
592 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
593 @@ -1177,14 +1245,14 @@
594 "InnoDB: the hash index to a page of %s,"
595 " still %lu hash nodes remain.\n",
596 index->name, (ulong) block->n_pointers);
597 - rw_lock_x_unlock(&btr_search_latch);
598 + rw_lock_x_unlock(btr_search_get_latch(index->id));
600 btr_search_validate();
602 - rw_lock_x_unlock(&btr_search_latch);
603 + rw_lock_x_unlock(btr_search_get_latch(index->id));
605 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
606 - rw_lock_x_unlock(&btr_search_latch);
607 + rw_lock_x_unlock(btr_search_get_latch(index->id));
608 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
611 @@ -1216,9 +1284,9 @@
613 ibool released_search_latch;
615 - rw_lock_s_lock(&btr_search_latch);
616 + rw_lock_s_lock(btr_search_get_latch(index->id));
618 - table = btr_search_sys->hash_index;
619 + table = btr_search_get_hash_index(index->id);
621 for (j = 0; j < srv_buf_pool_instances; j++) {
622 buf_pool_t* buf_pool;
623 @@ -1252,7 +1320,7 @@
626 /* keeping latch order */
627 - rw_lock_s_unlock(&btr_search_latch);
628 + rw_lock_s_unlock(btr_search_get_latch(index->id));
629 released_search_latch = TRUE;
630 rw_lock_x_lock(&block->lock);
632 @@ -1304,7 +1372,7 @@
633 mem_heap_empty(heap);
636 - rw_lock_x_lock(&btr_search_latch);
637 + rw_lock_x_lock(btr_search_get_latch(index->id));
639 if (UNIV_UNLIKELY(!block->is_hashed)) {
641 @@ -1314,12 +1382,12 @@
643 if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
644 || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
645 - rw_lock_x_unlock(&btr_search_latch);
646 + rw_lock_x_unlock(btr_search_get_latch(index->id));
647 rw_lock_x_unlock(&block->lock);
651 - rw_lock_s_lock(&btr_search_latch);
652 + rw_lock_s_lock(btr_search_get_latch(index->id));
656 @@ -1333,6 +1401,7 @@
658 block->is_hashed = FALSE;
660 + block->btr_search_latch = NULL;
663 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
664 @@ -1345,18 +1414,18 @@
665 index->name, (ulong) block->n_pointers);
667 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
668 - rw_lock_x_unlock(&btr_search_latch);
669 + rw_lock_x_unlock(btr_search_get_latch(index->id));
670 rw_lock_x_unlock(&block->lock);
674 - rw_lock_s_lock(&btr_search_latch);
675 + rw_lock_s_lock(btr_search_get_latch(index->id));
678 } while (released_search_latch);
681 - rw_lock_s_unlock(&btr_search_latch);
682 + rw_lock_s_unlock(btr_search_get_latch(index->id));
684 if (UNIV_LIKELY_NULL(heap)) {
686 @@ -1403,7 +1472,7 @@
688 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
690 - btr_search_drop_page_hash_index(block);
691 + btr_search_drop_page_hash_index(block, NULL);
695 @@ -1445,26 +1514,26 @@
697 ut_a(!dict_index_is_ibuf(index));
699 - table = btr_search_sys->hash_index;
700 + table = btr_search_get_hash_index(index->id);
701 page = buf_block_get_frame(block);
703 #ifdef UNIV_SYNC_DEBUG
704 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
705 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
706 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
707 || rw_lock_own(&(block->lock), RW_LOCK_EX));
708 #endif /* UNIV_SYNC_DEBUG */
710 - rw_lock_s_lock(&btr_search_latch);
711 + rw_lock_s_lock(btr_search_get_latch(index->id));
713 if (block->is_hashed && ((block->curr_n_fields != n_fields)
714 || (block->curr_n_bytes != n_bytes)
715 || (block->curr_left_side != left_side))) {
717 - rw_lock_s_unlock(&btr_search_latch);
718 + rw_lock_s_unlock(btr_search_get_latch(index->id));
720 - btr_search_drop_page_hash_index(block);
721 + btr_search_drop_page_hash_index(block, index);
723 - rw_lock_s_unlock(&btr_search_latch);
724 + rw_lock_s_unlock(btr_search_get_latch(index->id));
727 n_recs = page_get_n_recs(page);
728 @@ -1558,9 +1627,9 @@
732 - btr_search_check_free_space_in_heap();
733 + btr_search_check_free_space_in_heap(index->id);
735 - rw_lock_x_lock(&btr_search_latch);
736 + rw_lock_x_lock(btr_search_get_latch(index->id));
738 if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
740 @@ -1588,6 +1657,7 @@
741 block->curr_n_bytes = n_bytes;
742 block->curr_left_side = left_side;
743 block->index = index;
744 + block->btr_search_latch = btr_search_get_latch(index->id);
746 for (i = 0; i < n_cached; i++) {
748 @@ -1595,7 +1665,7 @@
752 - rw_lock_x_unlock(&btr_search_latch);
753 + rw_lock_x_unlock(btr_search_get_latch(index->id));
757 @@ -1634,13 +1704,13 @@
758 ut_a(!(new_block->is_hashed || block->is_hashed)
759 || !dict_index_is_ibuf(index));
761 - rw_lock_s_lock(&btr_search_latch);
762 + rw_lock_s_lock(btr_search_get_latch(index->id));
764 if (new_block->is_hashed) {
766 - rw_lock_s_unlock(&btr_search_latch);
767 + rw_lock_s_unlock(btr_search_get_latch(index->id));
769 - btr_search_drop_page_hash_index(block);
770 + btr_search_drop_page_hash_index(block, index);
774 @@ -1655,7 +1725,7 @@
775 new_block->n_bytes = block->curr_n_bytes;
776 new_block->left_side = left_side;
778 - rw_lock_s_unlock(&btr_search_latch);
779 + rw_lock_s_unlock(btr_search_get_latch(index->id));
781 ut_a(n_fields + n_bytes > 0);
783 @@ -1667,7 +1737,7 @@
787 - rw_lock_s_unlock(&btr_search_latch);
788 + rw_lock_s_unlock(btr_search_get_latch(index->id));
791 /********************************************************************//**
792 @@ -1706,7 +1776,7 @@
793 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
794 ut_a(!dict_index_is_ibuf(cursor->index));
796 - table = btr_search_sys->hash_index;
797 + table = btr_search_get_hash_index(cursor->index->id);
799 index_id = cursor->index->id;
800 fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
801 @@ -1715,11 +1785,11 @@
802 if (UNIV_LIKELY_NULL(heap)) {
805 - rw_lock_x_lock(&btr_search_latch);
806 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
808 ha_search_and_delete_if_found(table, fold, rec);
810 - rw_lock_x_unlock(&btr_search_latch);
811 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
814 /********************************************************************//**
815 @@ -1753,21 +1823,21 @@
816 ut_a(block->index == cursor->index);
817 ut_a(!dict_index_is_ibuf(cursor->index));
819 - rw_lock_x_lock(&btr_search_latch);
820 + rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
822 if ((cursor->flag == BTR_CUR_HASH)
823 && (cursor->n_fields == block->curr_n_fields)
824 && (cursor->n_bytes == block->curr_n_bytes)
825 && !block->curr_left_side) {
827 - table = btr_search_sys->hash_index;
828 + table = btr_search_get_hash_index(cursor->index->id);
830 ha_search_and_update_if_found(table, cursor->fold, rec,
831 block, page_rec_get_next(rec));
833 - rw_lock_x_unlock(&btr_search_latch);
834 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
836 - rw_lock_x_unlock(&btr_search_latch);
837 + rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
839 btr_search_update_hash_on_insert(cursor);
841 @@ -1802,9 +1872,9 @@
842 ulint* offsets = offsets_;
843 rec_offs_init(offsets_);
845 - table = btr_search_sys->hash_index;
846 + table = btr_search_get_hash_index(cursor->index->id);
848 - btr_search_check_free_space_in_heap();
849 + btr_search_check_free_space_in_heap(cursor->index->id);
851 rec = btr_cur_get_rec(cursor);
853 @@ -1849,7 +1919,7 @@
857 - rw_lock_x_lock(&btr_search_latch);
858 + rw_lock_x_lock(btr_search_get_latch(index_id));
862 @@ -1863,7 +1933,7 @@
866 - rw_lock_x_lock(&btr_search_latch);
867 + rw_lock_x_lock(btr_search_get_latch(index_id));
871 @@ -1881,7 +1951,7 @@
875 - rw_lock_x_lock(&btr_search_latch);
876 + rw_lock_x_lock(btr_search_get_latch(index_id));
880 @@ -1896,7 +1966,7 @@
884 - rw_lock_x_lock(&btr_search_latch);
885 + rw_lock_x_lock(btr_search_get_latch(index_id));
889 @@ -1919,7 +1989,7 @@
893 - rw_lock_x_unlock(&btr_search_latch);
894 + rw_lock_x_unlock(btr_search_get_latch(index_id));
898 @@ -1935,7 +2005,7 @@
900 ulint n_page_dumps = 0;
905 mem_heap_t* heap = NULL;
906 ulint offsets_[REC_OFFS_NORMAL_SIZE];
907 @@ -1947,23 +2017,25 @@
909 rec_offs_init(offsets_);
911 - rw_lock_x_lock(&btr_search_latch);
912 + btr_search_x_lock_all();
913 buf_pool_page_hash_x_lock_all();
915 - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
916 + for (j = 0; j < btr_search_index_num; j++) {
918 + cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
920 for (i = 0; i < cell_count; i++) {
921 /* We release btr_search_latch every once in a while to
922 give other queries a chance to run. */
923 if ((i != 0) && ((i % chunk_size) == 0)) {
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 - node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
934 + node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
936 for (; node != NULL; node = node->next) {
937 const buf_block_t* block
938 @@ -2072,19 +2144,21 @@
939 give other queries a chance to run. */
941 buf_pool_page_hash_x_unlock_all();
942 - rw_lock_x_unlock(&btr_search_latch);
943 + btr_search_x_unlock_all();
945 - rw_lock_x_lock(&btr_search_latch);
946 + btr_search_x_lock_all();
947 buf_pool_page_hash_x_lock_all();
950 - if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
951 + if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
956 + } /*for (j = 0; j < btr_search_index_num; j++)*/
958 buf_pool_page_hash_x_unlock_all();
959 - rw_lock_x_unlock(&btr_search_latch);
960 + btr_search_x_unlock_all();
961 if (UNIV_LIKELY_NULL(heap)) {
964 diff -ruN a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
965 --- a/storage/innobase/buf/buf0buf.c 2010-12-04 15:55:21.351597052 +0900
966 +++ b/storage/innobase/buf/buf0buf.c 2010-12-04 16:12:48.654550708 +0900
969 block->check_index_page_at_flush = FALSE;
971 + block->btr_search_latch = NULL;
973 block->is_hashed = FALSE;
975 @@ -1481,7 +1482,7 @@
976 /* To follow the latching order, we
977 have to release btr_search_latch
978 before acquiring block->latch. */
979 - rw_lock_x_unlock(&btr_search_latch);
980 + btr_search_x_unlock_all();
981 /* When we release the search latch,
982 we must rescan all blocks, because
983 some may become hashed again. */
984 @@ -1512,11 +1513,11 @@
985 anything. block->is_hashed can only
986 be set on uncompressed file pages. */
988 - btr_search_drop_page_hash_index(block);
989 + btr_search_drop_page_hash_index(block, NULL);
991 rw_lock_x_unlock(&block->lock);
993 - rw_lock_x_lock(&btr_search_latch);
994 + btr_search_x_lock_all();
996 ut_ad(!btr_search_enabled);
998 @@ -1535,7 +1536,11 @@
999 ibool released_search_latch;
1001 #ifdef UNIV_SYNC_DEBUG
1002 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1005 + for (j = 0; j < btr_search_index_num; j++) {
1006 + ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
1008 #endif /* UNIV_SYNC_DEBUG */
1009 ut_ad(!btr_search_enabled);
1011 @@ -2636,6 +2641,7 @@
1013 block->check_index_page_at_flush = FALSE;
1014 block->index = NULL;
1015 + block->btr_search_latch = NULL;
1017 block->n_hash_helps = 0;
1018 block->is_hashed = FALSE;
1019 diff -ruN a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c
1020 --- a/storage/innobase/buf/buf0lru.c 2010-12-04 15:35:29.137347521 +0900
1021 +++ b/storage/innobase/buf/buf0lru.c 2010-12-04 16:12:48.658550840 +0900
1022 @@ -1798,7 +1798,7 @@
1024 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1026 - btr_search_drop_page_hash_index((buf_block_t*) bpage);
1027 + btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1028 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1031 diff -ruN a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c
1032 --- a/storage/innobase/dict/dict0dict.c 2010-12-04 15:52:23.398513916 +0900
1033 +++ b/storage/innobase/dict/dict0dict.c 2010-12-04 16:12:48.662550715 +0900
1034 @@ -1811,7 +1811,7 @@
1038 - ulint ref_count = btr_search_info_get_ref_count(info);
1039 + ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1040 if (ref_count == 0) {
1043 diff -ruN a/storage/innobase/ha/ha0ha.c b/storage/innobase/ha/ha0ha.c
1044 --- a/storage/innobase/ha/ha0ha.c 2010-11-03 07:01:13.000000000 +0900
1045 +++ b/storage/innobase/ha/ha0ha.c 2010-12-04 16:12:48.665593752 +0900
1048 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1049 #ifdef UNIV_SYNC_DEBUG
1050 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1051 + /* cannot identificate which btr_search_latch[i] for now */
1052 + //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1053 #endif /* UNIV_SYNC_DEBUG */
1055 #ifndef UNIV_HOTBACKUP
1056 diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
1057 --- a/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:20.185850734 +0900
1058 +++ b/storage/innobase/handler/ha_innodb.cc 2010-12-04 16:12:48.674552412 +0900
1059 @@ -11702,6 +11702,11 @@
1060 "Disable with --skip-innodb-adaptive-hash-index.",
1061 NULL, innodb_adaptive_hash_index_update, TRUE);
1063 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1064 + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1065 + "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1066 + NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
1068 static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1069 PLUGIN_VAR_RQCMDARG,
1070 "Replication thread delay (ms) on the slave server if "
1071 @@ -12068,6 +12073,7 @@
1072 MYSQL_SYSVAR(use_sys_stats_table),
1073 MYSQL_SYSVAR(stats_sample_pages),
1074 MYSQL_SYSVAR(adaptive_hash_index),
1075 + MYSQL_SYSVAR(adaptive_hash_index_partitions),
1076 MYSQL_SYSVAR(stats_method),
1077 MYSQL_SYSVAR(replication_delay),
1078 MYSQL_SYSVAR(status_file),
1079 diff -ruN a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
1080 --- a/storage/innobase/include/btr0sea.h 2010-12-03 15:48:03.070987226 +0900
1081 +++ b/storage/innobase/include/btr0sea.h 2010-12-04 16:12:48.707551382 +0900
1084 btr_search_info_get_ref_count(
1085 /*==========================*/
1086 - btr_search_t* info); /*!< in: search info. */
1087 + btr_search_t* info, /*!< in: search info. */
1089 /*********************************************************************//**
1090 Updates the search info. */
1092 @@ -136,10 +137,11 @@
1094 btr_search_drop_page_hash_index(
1095 /*============================*/
1096 - buf_block_t* block); /*!< in: block containing index page,
1097 + buf_block_t* block, /*!< in: block containing index page,
1098 s- or x-latched, or an index page
1099 for which we know that
1100 block->buf_fix_count == 0 */
1101 + dict_index_t* index_in);
1102 /************************************************************************
1103 Drops a page hash index based on index */
1105 @@ -199,10 +201,47 @@
1106 # define btr_search_validate() TRUE
1107 #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1109 +/********************************************************************//**
1110 +New functions to control split btr_search_index */
1113 +btr_search_get_hash_index(
1114 +/*======================*/
1119 +btr_search_get_latch(
1120 +/*=================*/
1125 +btr_search_x_lock_all(void);
1126 +/*========================*/
1130 +btr_search_x_unlock_all(void);
1131 +/*==========================*/
1135 +btr_search_s_lock_all(void);
1136 +/*========================*/
1140 +btr_search_s_unlock_all(void);
1141 +/*==========================*/
1144 /** Flag: has the search system been enabled?
1145 Protected by btr_search_latch and btr_search_enabled_mutex. */
1146 extern char btr_search_enabled;
1148 +extern ulint btr_search_index_num;
1150 /** Flag: whether the search system has completed its disabling process,
1151 It is set to TRUE right after buf_pool_drop_hash_index() in
1152 btr_search_disable(), indicating hash index entries are cleaned up.
1155 /** The hash index system */
1156 struct btr_search_sys_struct{
1157 - hash_table_t* hash_index; /*!< the adaptive hash index,
1158 + hash_table_t** hash_index; /*!< the adaptive hash index,
1159 mapping dtuple_fold values
1160 to rec_t pointers on index pages */
1162 @@ -290,10 +329,12 @@
1164 Bear in mind (3) and (4) when using the hash index.
1166 -extern rw_lock_t* btr_search_latch_temp;
1167 +//extern rw_lock_t* btr_search_latch_temp;
1169 +extern rw_lock_t** btr_search_latch_part;
1171 /** The latch protecting the adaptive search system */
1172 -#define btr_search_latch (*btr_search_latch_temp)
1173 +//#define btr_search_latch (*btr_search_latch_temp)
1175 #ifdef UNIV_SEARCH_PERF_STAT
1176 /** Number of successful adaptive hash index lookups */
1177 diff -ruN a/storage/innobase/include/btr0sea.ic b/storage/innobase/include/btr0sea.ic
1178 --- a/storage/innobase/include/btr0sea.ic 2010-11-03 07:01:13.000000000 +0900
1179 +++ b/storage/innobase/include/btr0sea.ic 2010-12-04 16:12:48.709511202 +0900
1183 #ifdef UNIV_SYNC_DEBUG
1184 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1185 - ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1186 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1187 + ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1188 #endif /* UNIV_SYNC_DEBUG */
1190 info = btr_search_get_info(index);
1193 btr_search_info_update_slow(info, cursor);
1196 +/*********************************************************************//**
1197 +New functions to control split btr_search_index */
1200 +btr_search_get_hash_index(
1201 +/*======================*/
1204 + return(btr_search_sys->hash_index[key % btr_search_index_num]);
1209 +btr_search_get_latch(
1210 +/*=================*/
1213 + return(btr_search_latch_part[key % btr_search_index_num]);
1218 +btr_search_x_lock_all(void)
1219 +/*=======================*/
1223 + for (i = 0; i < btr_search_index_num; i++) {
1224 + rw_lock_x_lock(btr_search_latch_part[i]);
1230 +btr_search_x_unlock_all(void)
1231 +/*==========================*/
1235 + for (i = 0; i < btr_search_index_num; i++) {
1236 + rw_lock_x_unlock(btr_search_latch_part[i]);
1242 +btr_search_s_lock_all(void)
1243 +/*=======================*/
1247 + for (i = 0; i < btr_search_index_num; i++) {
1248 + rw_lock_s_lock(btr_search_latch_part[i]);
1254 +btr_search_s_unlock_all(void)
1255 +/*=========================*/
1259 + for (i = 0; i < btr_search_index_num; i++) {
1260 + rw_lock_s_unlock(btr_search_latch_part[i]);
1264 diff -ruN a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
1265 --- a/storage/innobase/include/buf0buf.h 2010-12-15 19:00:07.713604580 +0900
1266 +++ b/storage/innobase/include/buf0buf.h 2010-12-15 20:58:03.546839883 +0900
1267 @@ -1546,7 +1546,7 @@
1268 pointers in the adaptive hash index
1269 pointing to this frame */
1270 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1271 - unsigned is_hashed:1; /*!< TRUE if hash index has
1272 + volatile unsigned is_hashed:1; /*!< TRUE if hash index has
1273 already been built on this
1274 page; note that it does not
1275 guarantee that the index is
1276 @@ -1560,6 +1560,7 @@
1277 unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1278 dict_index_t* index; /*!< Index for which the adaptive
1279 hash index has been created. */
1280 + volatile rw_lock_t* btr_search_latch;
1282 # ifdef UNIV_SYNC_DEBUG
1283 /** @name Debug fields */
1284 diff -ruN a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic
1285 --- a/storage/innobase/include/row0upd.ic 2010-11-03 07:01:13.000000000 +0900
1286 +++ b/storage/innobase/include/row0upd.ic 2010-12-04 16:12:48.710551113 +0900
1288 ut_ad(dict_index_is_clust(index));
1289 ut_ad(rec_offs_validate(rec, index, offsets));
1290 #ifdef UNIV_SYNC_DEBUG
1291 - if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
1292 + if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) {
1293 ut_ad(!buf_block_align(rec)->is_hashed);
1295 #endif /* UNIV_SYNC_DEBUG */
1296 diff -ruN a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c
1297 --- a/storage/innobase/page/page0page.c 2010-11-03 07:01:13.000000000 +0900
1298 +++ b/storage/innobase/page/page0page.c 2010-12-04 16:12:48.712550963 +0900
1300 const ibool is_hashed = block->is_hashed;
1303 - rw_lock_x_lock(&btr_search_latch);
1304 + rw_lock_x_lock(btr_search_get_latch(block->index->id));
1307 ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1310 #ifndef UNIV_HOTBACKUP
1312 - rw_lock_x_unlock(&btr_search_latch);
1313 + rw_lock_x_unlock(btr_search_get_latch(block->index->id));
1315 #endif /* !UNIV_HOTBACKUP */
1317 diff -ruN a/storage/innobase/page/page0zip.c b/storage/innobase/page/page0zip.c
1318 --- a/storage/innobase/page/page0zip.c 2010-12-04 15:57:13.061494433 +0900
1319 +++ b/storage/innobase/page/page0zip.c 2010-12-04 16:12:48.716470334 +0900
1320 @@ -4444,7 +4444,7 @@
1322 #ifndef UNIV_HOTBACKUP
1323 temp_block = buf_block_alloc(buf_pool);
1324 - btr_search_drop_page_hash_index(block);
1325 + btr_search_drop_page_hash_index(block, index);
1326 block->check_index_page_at_flush = TRUE;
1327 #else /* !UNIV_HOTBACKUP */
1328 ut_ad(block == back_block1);
1329 diff -ruN a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
1330 --- a/storage/innobase/row/row0sel.c 2010-12-04 16:09:53.204513572 +0900
1331 +++ b/storage/innobase/row/row0sel.c 2010-12-04 16:12:48.722551273 +0900
1332 @@ -1210,7 +1210,7 @@
1333 ut_ad(plan->unique_search);
1334 ut_ad(!plan->must_get_clust);
1335 #ifdef UNIV_SYNC_DEBUG
1336 - ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1337 + ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1338 #endif /* UNIV_SYNC_DEBUG */
1340 row_sel_open_pcur(plan, TRUE, mtr);
1341 @@ -1381,10 +1381,10 @@
1342 && !plan->must_get_clust
1343 && !plan->table->big_rows) {
1344 if (!search_latch_locked) {
1345 - rw_lock_s_lock(&btr_search_latch);
1346 + rw_lock_s_lock(btr_search_get_latch(index->id));
1348 search_latch_locked = TRUE;
1349 - } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1350 + } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1352 /* There is an x-latch request waiting: release the
1353 s-latch for a moment; as an s-latch here is often
1354 @@ -1393,8 +1393,8 @@
1355 from acquiring an s-latch for a long time, lowering
1356 performance significantly in multiprocessors. */
1358 - rw_lock_s_unlock(&btr_search_latch);
1359 - rw_lock_s_lock(&btr_search_latch);
1360 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1361 + rw_lock_s_lock(btr_search_get_latch(index->id));
1364 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1365 @@ -1417,7 +1417,7 @@
1368 if (search_latch_locked) {
1369 - rw_lock_s_unlock(&btr_search_latch);
1370 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1372 search_latch_locked = FALSE;
1374 @@ -1993,7 +1993,7 @@
1377 if (search_latch_locked) {
1378 - rw_lock_s_unlock(&btr_search_latch);
1379 + rw_lock_s_unlock(btr_search_get_latch(index->id));
1381 if (UNIV_LIKELY_NULL(heap)) {
1382 mem_heap_free(heap);
1383 @@ -3356,6 +3356,8 @@
1384 /* if the returned record was locked and we did a semi-consistent
1385 read (fetch the newest committed version), then this is set to
1388 + ulint should_release;
1389 #ifdef UNIV_SEARCH_DEBUG
1391 #endif /* UNIV_SEARCH_DEBUG */
1392 @@ -3446,18 +3448,33 @@
1393 /* PHASE 0: Release a possible s-latch we are holding on the
1394 adaptive hash index latch if there is someone waiting behind */
1396 - if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1397 - && trx->has_search_latch) {
1398 + should_release = 0;
1399 + for (i = 0; i < btr_search_index_num; i++) {
1400 + /* we should check all latches (fix Bug#791030) */
1401 + if (rw_lock_get_writer(btr_search_latch_part[i])
1402 + != RW_LOCK_NOT_LOCKED) {
1403 + should_release |= ((ulint)1 << i);
1407 + if (should_release) {
1409 /* There is an x-latch request on the adaptive hash index:
1410 release the s-latch to reduce starvation and wait for
1411 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1414 - rw_lock_s_unlock(&btr_search_latch);
1415 - trx->has_search_latch = FALSE;
1416 + for (i = 0; i < btr_search_index_num; i++) {
1417 + /* we should release all s-latches (fix Bug#791030) */
1418 + if (trx->has_search_latch & ((ulint)1 << i)) {
1419 + rw_lock_s_unlock(btr_search_latch_part[i]);
1420 + trx->has_search_latch &= (~((ulint)1 << i));
1424 + if (!trx->has_search_latch) {
1425 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1429 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1430 @@ -3608,9 +3625,28 @@
1431 hash index semaphore! */
1433 #ifndef UNIV_SEARCH_DEBUG
1434 - if (!trx->has_search_latch) {
1435 - rw_lock_s_lock(&btr_search_latch);
1436 - trx->has_search_latch = TRUE;
1437 + if (!(trx->has_search_latch
1438 + & ((ulint)1 << (index->id % btr_search_index_num)))) {
1439 + if (trx->has_search_latch
1440 + < ((ulint)1 << (index->id % btr_search_index_num))) {
1441 + rw_lock_s_lock(btr_search_get_latch(index->id));
1442 + trx->has_search_latch |=
1443 + ((ulint)1 << (index->id % btr_search_index_num));
1445 + /* should re-lock to obay latch-order */
1446 + for (i = 0; i < btr_search_index_num; i++) {
1447 + if (trx->has_search_latch & ((ulint)1 << i)) {
1448 + rw_lock_s_unlock(btr_search_latch_part[i]);
1451 + trx->has_search_latch |=
1452 + ((ulint)1 << (index->id % btr_search_index_num));
1453 + for (i = 0; i < btr_search_index_num; i++) {
1454 + if (trx->has_search_latch & ((ulint)1 << i)) {
1455 + rw_lock_s_lock(btr_search_latch_part[i]);
1461 switch (row_sel_try_search_shortcut_for_mysql(
1462 @@ -3671,7 +3707,11 @@
1464 trx->search_latch_timeout--;
1466 - rw_lock_s_unlock(&btr_search_latch);
1467 + for (i = 0; i < btr_search_index_num; i++) {
1468 + if (trx->has_search_latch & ((ulint)1 << i)) {
1469 + rw_lock_s_unlock(btr_search_latch_part[i]);
1472 trx->has_search_latch = FALSE;
1475 @@ -3695,7 +3735,12 @@
1476 /* PHASE 3: Open or restore index cursor position */
1478 if (trx->has_search_latch) {
1479 - rw_lock_s_unlock(&btr_search_latch);
1481 + for (i = 0; i < btr_search_index_num; i++) {
1482 + if (trx->has_search_latch & ((ulint)1 << i)) {
1483 + rw_lock_s_unlock(btr_search_latch_part[i]);
1486 trx->has_search_latch = FALSE;
1489 diff -ruN a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c
1490 --- a/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:20.231484679 +0900
1491 +++ b/storage/innobase/srv/srv0srv.c 2010-12-04 16:12:48.726551018 +0900
1492 @@ -2045,7 +2045,9 @@
1493 "-------------------------------------\n", file);
1496 - ha_print_info(file, btr_search_sys->hash_index);
1497 + for (i = 0; i < btr_search_index_num; i++) {
1498 + ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1502 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1503 @@ -2070,14 +2072,15 @@
1504 ut_total_allocated_memory,
1505 mem_pool_get_reserved(mem_comm_pool));
1506 /* Calcurate reserved memories */
1507 - if (btr_search_sys && btr_search_sys->hash_index->heap) {
1508 - btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1509 + if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1510 + btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1512 btr_search_sys_subtotal = 0;
1513 - for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1514 - btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1515 + for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1516 + btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1519 + btr_search_sys_subtotal *= btr_search_index_num;
1521 lock_sys_subtotal = 0;
1523 @@ -2103,10 +2106,10 @@
1524 " Recovery system %lu \t(%lu + %lu)\n",
1526 (ulong) (btr_search_sys
1527 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1528 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1529 + btr_search_sys_subtotal,
1530 (ulong) (btr_search_sys
1531 - ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1532 + ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1533 (ulong) btr_search_sys_subtotal,
1535 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1536 diff -ruN a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c
1537 --- a/storage/innobase/sync/sync0sync.c 2010-12-03 17:36:44.300986571 +0900
1538 +++ b/storage/innobase/sync/sync0sync.c 2010-12-04 16:12:48.729513564 +0900
1539 @@ -1223,7 +1223,6 @@
1540 case SYNC_OUTER_ANY_LATCH:
1541 case SYNC_FILE_FORMAT_TAG:
1542 case SYNC_DOUBLEWRITE:
1543 - case SYNC_SEARCH_SYS:
1544 case SYNC_SEARCH_SYS_CONF:
1545 case SYNC_TRX_LOCK_HEAP:
1547 @@ -1244,6 +1243,7 @@
1551 + case SYNC_SEARCH_SYS:
1552 case SYNC_BUF_LRU_LIST:
1553 case SYNC_BUF_FLUSH_LIST:
1554 case SYNC_BUF_PAGE_HASH:
1555 diff -ruN a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
1556 --- a/storage/innobase/trx/trx0trx.c 2010-12-03 17:49:11.623953784 +0900
1557 +++ b/storage/innobase/trx/trx0trx.c 2010-12-04 16:12:48.731513275 +0900
1558 @@ -265,8 +265,14 @@
1559 /*=================================*/
1560 trx_t* trx) /*!< in: transaction */
1564 if (trx->has_search_latch) {
1565 - rw_lock_s_unlock(&btr_search_latch);
1566 + for (i = 0; i < btr_search_index_num; i++) {
1567 + if (trx->has_search_latch & ((ulint)1 << i)) {
1568 + rw_lock_s_unlock(btr_search_latch_part[i]);
1572 trx->has_search_latch = FALSE;