]> git.pld-linux.org Git - packages/mysql.git/blob - innodb_adaptive_hash_index_partitions.patch
- up to 5.5.17
[packages/mysql.git] / innodb_adaptive_hash_index_partitions.patch
1 # name       : innodb_adaptive_hash_index_num.patch
2 # introduced : XtraDB on 5.5 (-13?)
3 # maintainer : Yasufumi
4 #
5 #!!! notice !!!
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
10 @@ -1523,7 +1523,7 @@
11         }
12         ut_a(block);
13  
14 -       btr_search_drop_page_hash_index(block);
15 +       btr_search_drop_page_hash_index(block, NULL);
16  
17         header = buf_block_get_frame(block) + PAGE_HEADER + PAGE_BTR_SEG_TOP;
18  #ifdef UNIV_BTR_DEBUG
19 @@ -1592,7 +1592,7 @@
20  
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);
25         }
26  
27         block->check_index_page_at_flush = TRUE;
28 @@ -1760,7 +1760,7 @@
29         ut_a(!page_zip || page_zip_validate(page_zip, page));
30  #endif /* UNIV_ZIP_DEBUG */
31  
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");
35  
36         /* Recreate the page: note that global data on page (possible
37 @@ -3093,7 +3093,7 @@
38                 mem_heap_free(heap);
39         }
40  
41 -       btr_search_drop_page_hash_index(block);
42 +       btr_search_drop_page_hash_index(block, index);
43  
44         /* Make the father empty */
45         btr_page_empty(father_block, father_page_zip, index, page_level, mtr);
46 @@ -3317,7 +3317,7 @@
47                         goto err_exit;
48                 }
49  
50 -               btr_search_drop_page_hash_index(block);
51 +               btr_search_drop_page_hash_index(block, index);
52  
53                 /* Remove the page from the level list */
54                 btr_level_list_remove(space, zip_size, page, index, mtr);
55 @@ -3358,7 +3358,7 @@
56                         goto err_exit;
57                 }
58  
59 -               btr_search_drop_page_hash_index(block);
60 +               btr_search_drop_page_hash_index(block, index);
61  
62  #ifdef UNIV_BTR_DEBUG
63                 if (UNIV_LIKELY_NULL(merge_page_zip)) {
64 @@ -3473,7 +3473,7 @@
65                 ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
66  
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);
70  
71                 btr_page_get_father(index, block, mtr, &cursor);
72                 father = btr_cur_get_block(&cursor);
73 @@ -3578,7 +3578,7 @@
74  
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);
79  
80         if (left_page_no == FIL_NULL && !page_is_leaf(page)) {
81  
82 --- a/storage/innobase/btr/btr0cur.c
83 +++ b/storage/innobase/btr/btr0cur.c
84 @@ -502,7 +502,7 @@
85  #ifdef UNIV_SEARCH_PERF_STAT
86         info->n_searches++;
87  #endif
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
92             && !estimate
93 @@ -538,7 +538,7 @@
94  
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));
99         }
100  
101         /* Store the position of the tree latch we push to mtr so that we
102 @@ -862,7 +862,7 @@
103  
104         if (has_search_latch) {
105  
106 -               rw_lock_s_lock(&btr_search_latch);
107 +               rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
108         }
109  }
110  
111 @@ -1992,13 +1992,13 @@
112                         btr_search_update_hash_on_delete(cursor);
113                 }
114  
115 -               rw_lock_x_lock(&btr_search_latch);
116 +               rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
117         }
118  
119         row_upd_rec_in_place(rec, index, offsets, update, page_zip);
120  
121         if (is_hashed) {
122 -               rw_lock_x_unlock(&btr_search_latch);
123 +               rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
124         }
125  
126         if (page_zip && !dict_index_is_clust(index)
127 --- a/storage/innobase/btr/btr0sea.c
128 +++ b/storage/innobase/btr/btr0sea.c
129 @@ -48,6 +48,8 @@
130  UNIV_INTERN char               btr_search_enabled      = TRUE;
131  UNIV_INTERN ibool              btr_search_fully_disabled = FALSE;
132  
133 +UNIV_INTERN ulint              btr_search_index_num    = 1;
134 +
135  /** Mutex protecting btr_search_enabled */
136  static mutex_t                 btr_search_enabled_mutex;
137  
138 @@ -79,7 +81,9 @@
139  
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;
144 +
145 +UNIV_INTERN rw_lock_t**                btr_search_latch_part;
146  
147  /** padding to prevent other memory update hotspots from residing on
148  the same memory cache line */
149 @@ -131,18 +135,19 @@
150  will not guarantee success. */
151  static
152  void
153 -btr_search_check_free_space_in_heap(void)
154 +btr_search_check_free_space_in_heap(
155  /*=====================================*/
156 +       index_id_t      key)
157  {
158         hash_table_t*   table;
159         mem_heap_t*     heap;
160  
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 */
167  
168 -       table = btr_search_sys->hash_index;
169 +       table = btr_search_get_hash_index(key);
170  
171         heap = table->heap;
172  
173 @@ -153,7 +158,7 @@
174         if (heap->free_block == NULL) {
175                 buf_block_t*    block = buf_block_alloc(NULL);
176  
177 -               rw_lock_x_lock(&btr_search_latch);
178 +               rw_lock_x_lock(btr_search_get_latch(key));
179  
180                 if (heap->free_block == NULL) {
181                         heap->free_block = block;
182 @@ -161,7 +166,7 @@
183                         buf_block_free(block);
184                 }
185  
186 -               rw_lock_x_unlock(&btr_search_latch);
187 +               rw_lock_x_unlock(btr_search_get_latch(key));
188         }
189  }
190  
191 @@ -173,19 +178,30 @@
192  /*==================*/
193         ulint   hash_size)      /*!< in: hash index hash table size */
194  {
195 +       ulint i;
196         /* We allocate the search latch from dynamic memory:
197         see above at the global variable definition */
198  
199 -       btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
200 +       //btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
201  
202 -       rw_lock_create(btr_search_latch_key, &btr_search_latch,
203 -                      SYNC_SEARCH_SYS);
204 +       //rw_lock_create(btr_search_latch_key, &btr_search_latch,
205 +       //             SYNC_SEARCH_SYS);
206         mutex_create(btr_search_enabled_mutex_key,
207                      &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
208  
209         btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
210  
211 -       btr_search_sys->hash_index = ha_create(hash_size, 0, 0);
212 +       /* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
213 +       btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
214 +       btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
215 +       for (i = 0; i < btr_search_index_num; i++) {
216 +               btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
217 +
218 +               rw_lock_create(btr_search_latch_key,
219 +                               btr_search_latch_part[i], SYNC_SEARCH_SYS);
220 +
221 +               btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
222 +       }
223  }
224  
225  /*****************************************************************//**
226 @@ -195,11 +211,22 @@
227  btr_search_sys_free(void)
228  /*=====================*/
229  {
230 -       rw_lock_free(&btr_search_latch);
231 -       mem_free(btr_search_latch_temp);
232 -       btr_search_latch_temp = NULL;
233 -       mem_heap_free(btr_search_sys->hash_index->heap);
234 -       hash_table_free(btr_search_sys->hash_index);
235 +       ulint i;
236 +
237 +       for (i = 0; i < btr_search_index_num; i++) {
238 +               mem_heap_free(btr_search_sys->hash_index[i]->heap);
239 +               hash_table_free(btr_search_sys->hash_index[i]);
240 +
241 +               rw_lock_free(btr_search_latch_part[i]);
242 +
243 +               mem_free(btr_search_latch_part[i]);
244 +       }
245 +       mem_free(btr_search_sys->hash_index);
246 +       mem_free(btr_search_latch_part);
247 +
248 +       //rw_lock_free(&btr_search_latch);
249 +       //mem_free(btr_search_latch_temp);
250 +       //btr_search_latch_temp = NULL;
251         mem_free(btr_search_sys);
252         btr_search_sys = NULL;
253  }
254 @@ -212,7 +239,7 @@
255  /*====================*/
256  {
257         mutex_enter(&btr_search_enabled_mutex);
258 -       rw_lock_x_lock(&btr_search_latch);
259 +       btr_search_x_lock_all();
260  
261         /* Disable access to hash index, also tell ha_insert_for_fold()
262         stop adding new nodes to hash index, but still allow updating
263 @@ -230,7 +257,7 @@
264         /* btr_search_enabled_mutex should guarantee this. */
265         ut_ad(!btr_search_enabled);
266  
267 -       rw_lock_x_unlock(&btr_search_latch);
268 +       btr_search_x_unlock_all();
269         mutex_exit(&btr_search_enabled_mutex);
270  }
271  
272 @@ -242,12 +269,12 @@
273  /*====================*/
274  {
275         mutex_enter(&btr_search_enabled_mutex);
276 -       rw_lock_x_lock(&btr_search_latch);
277 +       btr_search_x_lock_all();
278  
279         btr_search_enabled = TRUE;
280         btr_search_fully_disabled = FALSE;
281  
282 -       rw_lock_x_unlock(&btr_search_latch);
283 +       btr_search_x_unlock_all();
284         mutex_exit(&btr_search_enabled_mutex);
285  }
286  
287 @@ -300,20 +327,21 @@
288  ulint
289  btr_search_info_get_ref_count(
290  /*==========================*/
291 -       btr_search_t*   info)   /*!< in: search info. */
292 +       btr_search_t*   info,   /*!< in: search info. */
293 +       index_id_t      key)
294  {
295         ulint ret;
296  
297         ut_ad(info);
298  
299  #ifdef UNIV_SYNC_DEBUG
300 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
301 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
302 +       ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
303 +       ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
304  #endif /* UNIV_SYNC_DEBUG */
305  
306 -       rw_lock_s_lock(&btr_search_latch);
307 +       rw_lock_s_lock(btr_search_get_latch(key));
308         ret = info->ref_count;
309 -       rw_lock_s_unlock(&btr_search_latch);
310 +       rw_lock_s_unlock(btr_search_get_latch(key));
311  
312         return(ret);
313  }
314 @@ -334,8 +362,8 @@
315         int             cmp;
316  
317  #ifdef UNIV_SYNC_DEBUG
318 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
319 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
320 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
321 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
322  #endif /* UNIV_SYNC_DEBUG */
323  
324         index = cursor->index;
325 @@ -453,8 +481,8 @@
326                                 /*!< in: cursor */
327  {
328  #ifdef UNIV_SYNC_DEBUG
329 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
330 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
331 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
332 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
333         ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
334               || rw_lock_own(&block->lock, RW_LOCK_EX));
335  #endif /* UNIV_SYNC_DEBUG */
336 @@ -538,7 +566,7 @@
337  
338         ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
339  #ifdef UNIV_SYNC_DEBUG
340 -       ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
341 +       ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
342         ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
343               || rw_lock_own(&(block->lock), RW_LOCK_EX));
344  #endif /* UNIV_SYNC_DEBUG */
345 @@ -578,10 +606,10 @@
346                         mem_heap_free(heap);
347                 }
348  #ifdef UNIV_SYNC_DEBUG
349 -               ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
350 +               ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
351  #endif /* UNIV_SYNC_DEBUG */
352  
353 -               ha_insert_for_fold(btr_search_sys->hash_index, fold,
354 +               ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
355                                    block, rec);
356         }
357  }
358 @@ -601,8 +629,8 @@
359         ulint*          params2;
360  
361  #ifdef UNIV_SYNC_DEBUG
362 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
363 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
364 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
365 +       ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
366  #endif /* UNIV_SYNC_DEBUG */
367  
368         block = btr_cur_get_block(cursor);
369 @@ -623,7 +651,7 @@
370  
371         if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
372  
373 -               btr_search_check_free_space_in_heap();
374 +               btr_search_check_free_space_in_heap(cursor->index->id);
375         }
376  
377         if (cursor->flag == BTR_CUR_HASH_FAIL) {
378 @@ -633,11 +661,11 @@
379                 btr_search_n_hash_fail++;
380  #endif /* UNIV_SEARCH_PERF_STAT */
381  
382 -               rw_lock_x_lock(&btr_search_latch);
383 +               rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
384  
385                 btr_search_update_hash_ref(info, block, cursor);
386  
387 -               rw_lock_x_unlock(&btr_search_latch);
388 +               rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
389         }
390  
391         if (build_index) {
392 @@ -882,17 +910,17 @@
393         cursor->flag = BTR_CUR_HASH;
394  
395         if (UNIV_LIKELY(!has_search_latch)) {
396 -               rw_lock_s_lock(&btr_search_latch);
397 +               rw_lock_s_lock(btr_search_get_latch(index_id));
398  
399                 if (UNIV_UNLIKELY(!btr_search_enabled)) {
400                         goto failure_unlock;
401                 }
402         }
403  
404 -       ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);
405 -       ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);
406 +       ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
407 +       ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
408  
409 -       rec = ha_search_and_get_data(btr_search_sys->hash_index, fold);
410 +       rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
411  
412         if (UNIV_UNLIKELY(!rec)) {
413                 goto failure_unlock;
414 @@ -910,7 +938,7 @@
415                         goto failure_unlock;
416                 }
417  
418 -               rw_lock_s_unlock(&btr_search_latch);
419 +               rw_lock_s_unlock(btr_search_get_latch(index_id));
420  
421                 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
422         }
423 @@ -1007,7 +1035,7 @@
424         /*-------------------------------------------*/
425  failure_unlock:
426         if (UNIV_LIKELY(!has_search_latch)) {
427 -               rw_lock_s_unlock(&btr_search_latch);
428 +               rw_lock_s_unlock(btr_search_get_latch(index_id));
429         }
430  failure:
431         cursor->flag = BTR_CUR_HASH_FAIL;
432 @@ -1030,10 +1058,11 @@
433  void
434  btr_search_drop_page_hash_index(
435  /*============================*/
436 -       buf_block_t*    block)  /*!< in: block containing index page,
437 +       buf_block_t*    block,  /*!< in: block containing index page,
438                                 s- or x-latched, or an index page
439                                 for which we know that
440                                 block->buf_fix_count == 0 */
441 +       dict_index_t*   index_in)
442  {
443         hash_table_t*           table;
444         ulint                   n_fields;
445 @@ -1052,22 +1081,60 @@
446         ulint*                  offsets;
447  
448  #ifdef UNIV_SYNC_DEBUG
449 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
450 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
451 +       if (index_in) {
452 +               ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_SHARED));
453 +               ut_ad(!rw_lock_own(btr_search_get_latch(index_in->id), RW_LOCK_EX));
454 +       }
455  #endif /* UNIV_SYNC_DEBUG */
456  
457  retry:
458 -       rw_lock_s_lock(&btr_search_latch);
459 +       if (index_in) {
460 +               index = index_in;
461 +               rw_lock_s_lock(btr_search_get_latch(index->id));
462 +       } else if (btr_search_index_num > 1) {
463 +               rw_lock_t*      btr_search_latch;
464 +
465 +               /* FIXME: This may be optimistic implementation still. */
466 +               btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
467 +               if (UNIV_LIKELY(!btr_search_latch)) {
468 +                       if (block->is_hashed) {
469 +                               goto retry;
470 +                       }
471 +                       return;
472 +               }
473 +               rw_lock_s_lock(btr_search_latch);
474 +               if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
475 +                       rw_lock_s_unlock(btr_search_latch);
476 +                       goto retry;
477 +               }
478 +               if (UNIV_LIKELY(!block->is_hashed)) {
479 +                       rw_lock_s_unlock(btr_search_latch);
480 +                       goto retry;
481 +               }
482 +               index = block->index;
483 +               ut_a(btr_search_latch == btr_search_get_latch(index->id));
484 +       } else {
485 +               /* btr_search_index_num == 1 */
486 +               /* btr_search_latch is only one and able to obtain
487 +                  before evaluating block->is_hashed. */
488 +               rw_lock_s_lock(btr_search_latch_part[0]);
489 +               if (UNIV_LIKELY(!block->is_hashed)) {
490 +                       rw_lock_s_unlock(btr_search_latch_part[0]);
491 +                       return;
492 +               }
493 +               index = block->index;
494 +       }
495 +
496         page = block->frame;
497  
498         if (UNIV_LIKELY(!block->is_hashed)) {
499  
500 -               rw_lock_s_unlock(&btr_search_latch);
501 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
502  
503                 return;
504         }
505  
506 -       table = btr_search_sys->hash_index;
507 +       table = btr_search_get_hash_index(index->id);
508  
509  #ifdef UNIV_SYNC_DEBUG
510         ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
511 @@ -1077,14 +1144,14 @@
512  
513         n_fields = block->curr_n_fields;
514         n_bytes = block->curr_n_bytes;
515 -       index = block->index;
516 +       ut_a(index == block->index);
517         ut_a(!dict_index_is_ibuf(index));
518  
519         /* NOTE: The fields of block must not be accessed after
520         releasing btr_search_latch, as the index page might only
521         be s-latched! */
522  
523 -       rw_lock_s_unlock(&btr_search_latch);
524 +       rw_lock_s_unlock(btr_search_get_latch(index->id));
525  
526         ut_a(n_fields + n_bytes > 0);
527  
528 @@ -1134,7 +1201,7 @@
529                 mem_heap_free(heap);
530         }
531  
532 -       rw_lock_x_lock(&btr_search_latch);
533 +       rw_lock_x_lock(btr_search_get_latch(index->id));
534  
535         if (UNIV_UNLIKELY(!block->is_hashed)) {
536                 /* Someone else has meanwhile dropped the hash index */
537 @@ -1150,7 +1217,7 @@
538                 /* Someone else has meanwhile built a new hash index on the
539                 page, with different parameters */
540  
541 -               rw_lock_x_unlock(&btr_search_latch);
542 +               rw_lock_x_unlock(btr_search_get_latch(index->id));
543  
544                 mem_free(folds);
545                 goto retry;
546 @@ -1166,6 +1233,7 @@
547  
548         block->is_hashed = FALSE;
549         block->index = NULL;
550 +       block->btr_search_latch = NULL;
551         
552  cleanup:
553  #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
554 @@ -1178,14 +1246,14 @@
555                         "InnoDB: the hash index to a page of %s,"
556                         " still %lu hash nodes remain.\n",
557                         index->name, (ulong) block->n_pointers);
558 -               rw_lock_x_unlock(&btr_search_latch);
559 +               rw_lock_x_unlock(btr_search_get_latch(index->id));
560  
561                 btr_search_validate();
562         } else {
563 -               rw_lock_x_unlock(&btr_search_latch);
564 +               rw_lock_x_unlock(btr_search_get_latch(index->id));
565         }
566  #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
567 -       rw_lock_x_unlock(&btr_search_latch);
568 +       rw_lock_x_unlock(btr_search_get_latch(index->id));
569  #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
570  
571         mem_free(folds);
572 @@ -1217,9 +1285,9 @@
573         ulint*          offsets;
574         ibool           released_search_latch;
575  
576 -       rw_lock_s_lock(&btr_search_latch);
577 +       rw_lock_s_lock(btr_search_get_latch(index->id));
578  
579 -       table = btr_search_sys->hash_index;
580 +       table = btr_search_get_hash_index(index->id);
581  
582         for (j = 0; j < srv_buf_pool_instances; j++) {
583                 buf_pool_t*     buf_pool;
584 @@ -1253,7 +1321,7 @@
585  
586  
587                                         /* keeping latch order */
588 -                                       rw_lock_s_unlock(&btr_search_latch);
589 +                                       rw_lock_s_unlock(btr_search_get_latch(index->id));
590                                         released_search_latch = TRUE;
591                                         rw_lock_x_lock(&block->lock);
592  
593 @@ -1305,7 +1373,7 @@
594                                                 mem_heap_empty(heap);
595                                         }
596  
597 -                                       rw_lock_x_lock(&btr_search_latch);
598 +                                       rw_lock_x_lock(btr_search_get_latch(index->id));
599  
600                                         if (UNIV_UNLIKELY(!block->is_hashed)) {
601                                                 goto cleanup;
602 @@ -1315,12 +1383,12 @@
603  
604                                         if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
605                                             || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
606 -                                               rw_lock_x_unlock(&btr_search_latch);
607 +                                               rw_lock_x_unlock(btr_search_get_latch(index->id));
608                                                 rw_lock_x_unlock(&block->lock);
609  
610                                                 mem_free(folds);
611  
612 -                                               rw_lock_s_lock(&btr_search_latch);
613 +                                               rw_lock_s_lock(btr_search_get_latch(index->id));
614                                                 goto retry;
615                                         }
616  
617 @@ -1334,6 +1402,7 @@
618  
619                                         block->is_hashed = FALSE;
620                                         block->index = NULL;
621 +                                       block->btr_search_latch = NULL;
622  
623  cleanup:
624  #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
625 @@ -1346,18 +1415,18 @@
626                                                         index->name, (ulong) block->n_pointers);
627                                         }
628  #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
629 -                                       rw_lock_x_unlock(&btr_search_latch);
630 +                                       rw_lock_x_unlock(btr_search_get_latch(index->id));
631                                         rw_lock_x_unlock(&block->lock);
632  
633                                         mem_free(folds);
634  
635 -                                       rw_lock_s_lock(&btr_search_latch);
636 +                                       rw_lock_s_lock(btr_search_get_latch(index->id));
637                                 }
638                         }
639                 } while (released_search_latch);
640         }
641  
642 -       rw_lock_s_unlock(&btr_search_latch);
643 +       rw_lock_s_unlock(btr_search_get_latch(index->id));
644  
645         if (UNIV_LIKELY_NULL(heap)) {
646                 mem_heap_free(heap);
647 @@ -1404,7 +1473,7 @@
648  
649                 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
650  
651 -               btr_search_drop_page_hash_index(block);
652 +               btr_search_drop_page_hash_index(block, NULL);
653         }
654  
655         mtr_commit(&mtr);
656 @@ -1446,26 +1515,26 @@
657         ut_ad(index);
658         ut_a(!dict_index_is_ibuf(index));
659  
660 -       table = btr_search_sys->hash_index;
661 +       table = btr_search_get_hash_index(index->id);
662         page = buf_block_get_frame(block);
663  
664  #ifdef UNIV_SYNC_DEBUG
665 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
666 +       ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
667         ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
668               || rw_lock_own(&(block->lock), RW_LOCK_EX));
669  #endif /* UNIV_SYNC_DEBUG */
670  
671 -       rw_lock_s_lock(&btr_search_latch);
672 +       rw_lock_s_lock(btr_search_get_latch(index->id));
673  
674         if (block->is_hashed && ((block->curr_n_fields != n_fields)
675                                  || (block->curr_n_bytes != n_bytes)
676                                  || (block->curr_left_side != left_side))) {
677  
678 -               rw_lock_s_unlock(&btr_search_latch);
679 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
680  
681 -               btr_search_drop_page_hash_index(block);
682 +               btr_search_drop_page_hash_index(block, index);
683         } else {
684 -               rw_lock_s_unlock(&btr_search_latch);
685 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
686         }
687  
688         n_recs = page_get_n_recs(page);
689 @@ -1559,9 +1628,9 @@
690                 fold = next_fold;
691         }
692  
693 -       btr_search_check_free_space_in_heap();
694 +       btr_search_check_free_space_in_heap(index->id);
695  
696 -       rw_lock_x_lock(&btr_search_latch);
697 +       rw_lock_x_lock(btr_search_get_latch(index->id));
698  
699         if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
700                 goto exit_func;
701 @@ -1589,6 +1658,7 @@
702         block->curr_n_bytes = n_bytes;
703         block->curr_left_side = left_side;
704         block->index = index;
705 +       block->btr_search_latch = btr_search_get_latch(index->id);
706  
707         for (i = 0; i < n_cached; i++) {
708  
709 @@ -1596,7 +1666,7 @@
710         }
711  
712  exit_func:
713 -       rw_lock_x_unlock(&btr_search_latch);
714 +       rw_lock_x_unlock(btr_search_get_latch(index->id));
715  
716         mem_free(folds);
717         mem_free(recs);
718 @@ -1635,13 +1705,13 @@
719         ut_a(!(new_block->is_hashed || block->is_hashed)
720              || !dict_index_is_ibuf(index));
721  
722 -       rw_lock_s_lock(&btr_search_latch);
723 +       rw_lock_s_lock(btr_search_get_latch(index->id));
724  
725         if (new_block->is_hashed) {
726  
727 -               rw_lock_s_unlock(&btr_search_latch);
728 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
729  
730 -               btr_search_drop_page_hash_index(block);
731 +               btr_search_drop_page_hash_index(block, index);
732  
733                 return;
734         }
735 @@ -1656,7 +1726,7 @@
736                 new_block->n_bytes = block->curr_n_bytes;
737                 new_block->left_side = left_side;
738  
739 -               rw_lock_s_unlock(&btr_search_latch);
740 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
741  
742                 ut_a(n_fields + n_bytes > 0);
743  
744 @@ -1668,7 +1738,7 @@
745                 return;
746         }
747  
748 -       rw_lock_s_unlock(&btr_search_latch);
749 +       rw_lock_s_unlock(btr_search_get_latch(index->id));
750  }
751  
752  /********************************************************************//**
753 @@ -1707,7 +1777,7 @@
754         ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
755         ut_a(!dict_index_is_ibuf(cursor->index));
756  
757 -       table = btr_search_sys->hash_index;
758 +       table = btr_search_get_hash_index(cursor->index->id);
759  
760         index_id = cursor->index->id;
761         fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
762 @@ -1716,11 +1786,11 @@
763         if (UNIV_LIKELY_NULL(heap)) {
764                 mem_heap_free(heap);
765         }
766 -       rw_lock_x_lock(&btr_search_latch);
767 +       rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
768  
769         ha_search_and_delete_if_found(table, fold, rec);
770  
771 -       rw_lock_x_unlock(&btr_search_latch);
772 +       rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
773  }
774  
775  /********************************************************************//**
776 @@ -1754,21 +1824,21 @@
777         ut_a(block->index == cursor->index);
778         ut_a(!dict_index_is_ibuf(cursor->index));
779  
780 -       rw_lock_x_lock(&btr_search_latch);
781 +       rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
782  
783         if ((cursor->flag == BTR_CUR_HASH)
784             && (cursor->n_fields == block->curr_n_fields)
785             && (cursor->n_bytes == block->curr_n_bytes)
786             && !block->curr_left_side) {
787  
788 -               table = btr_search_sys->hash_index;
789 +               table = btr_search_get_hash_index(cursor->index->id);
790  
791                 ha_search_and_update_if_found(table, cursor->fold, rec,
792                                               block, page_rec_get_next(rec));
793  
794 -               rw_lock_x_unlock(&btr_search_latch);
795 +               rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
796         } else {
797 -               rw_lock_x_unlock(&btr_search_latch);
798 +               rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
799  
800                 btr_search_update_hash_on_insert(cursor);
801         }
802 @@ -1803,9 +1873,9 @@
803         ulint*          offsets         = offsets_;
804         rec_offs_init(offsets_);
805  
806 -       table = btr_search_sys->hash_index;
807 +       table = btr_search_get_hash_index(cursor->index->id);
808  
809 -       btr_search_check_free_space_in_heap();
810 +       btr_search_check_free_space_in_heap(cursor->index->id);
811  
812         rec = btr_cur_get_rec(cursor);
813  
814 @@ -1850,7 +1920,7 @@
815         } else {
816                 if (left_side) {
817  
818 -                       rw_lock_x_lock(&btr_search_latch);
819 +                       rw_lock_x_lock(btr_search_get_latch(index_id));
820  
821                         locked = TRUE;
822  
823 @@ -1864,7 +1934,7 @@
824  
825                 if (!locked) {
826  
827 -                       rw_lock_x_lock(&btr_search_latch);
828 +                       rw_lock_x_lock(btr_search_get_latch(index_id));
829  
830                         locked = TRUE;
831                 }
832 @@ -1882,7 +1952,7 @@
833                 if (!left_side) {
834  
835                         if (!locked) {
836 -                               rw_lock_x_lock(&btr_search_latch);
837 +                               rw_lock_x_lock(btr_search_get_latch(index_id));
838  
839                                 locked = TRUE;
840                         }
841 @@ -1897,7 +1967,7 @@
842  
843                 if (!locked) {
844  
845 -                       rw_lock_x_lock(&btr_search_latch);
846 +                       rw_lock_x_lock(btr_search_get_latch(index_id));
847  
848                         locked = TRUE;
849                 }
850 @@ -1920,7 +1990,7 @@
851                 mem_heap_free(heap);
852         }
853         if (locked) {
854 -               rw_lock_x_unlock(&btr_search_latch);
855 +               rw_lock_x_unlock(btr_search_get_latch(index_id));
856         }
857  }
858  
859 @@ -1936,7 +2006,7 @@
860         ha_node_t*      node;
861         ulint           n_page_dumps    = 0;
862         ibool           ok              = TRUE;
863 -       ulint           i;
864 +       ulint           i,j;
865         ulint           cell_count;
866         mem_heap_t*     heap            = NULL;
867         ulint           offsets_[REC_OFFS_NORMAL_SIZE];
868 @@ -1948,23 +2018,25 @@
869  
870         rec_offs_init(offsets_);
871  
872 -       rw_lock_x_lock(&btr_search_latch);
873 +       btr_search_x_lock_all();
874         buf_pool_page_hash_x_lock_all();
875  
876 -       cell_count = hash_get_n_cells(btr_search_sys->hash_index);
877 +       for (j = 0; j < btr_search_index_num; j++) {
878 +
879 +       cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
880  
881         for (i = 0; i < cell_count; i++) {
882                 /* We release btr_search_latch every once in a while to
883                 give other queries a chance to run. */
884                 if ((i != 0) && ((i % chunk_size) == 0)) {
885                         buf_pool_page_hash_x_unlock_all();
886 -                       rw_lock_x_unlock(&btr_search_latch);
887 +                       btr_search_x_unlock_all();
888                         os_thread_yield();
889 -                       rw_lock_x_lock(&btr_search_latch);
890 +                       btr_search_x_lock_all();
891                         buf_pool_page_hash_x_lock_all();
892                 }
893  
894 -               node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
895 +               node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
896  
897                 for (; node != NULL; node = node->next) {
898                         const buf_block_t*      block
899 @@ -2073,19 +2145,21 @@
900                 give other queries a chance to run. */
901                 if (i != 0) {
902                         buf_pool_page_hash_x_unlock_all();
903 -                       rw_lock_x_unlock(&btr_search_latch);
904 +                       btr_search_x_unlock_all();
905                         os_thread_yield();
906 -                       rw_lock_x_lock(&btr_search_latch);
907 +                       btr_search_x_lock_all();
908                         buf_pool_page_hash_x_lock_all();
909                 }
910  
911 -               if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
912 +               if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
913                         ok = FALSE;
914                 }
915         }
916  
917 +       } /*for (j = 0; j < btr_search_index_num; j++)*/
918 +
919         buf_pool_page_hash_x_unlock_all();
920 -       rw_lock_x_unlock(&btr_search_latch);
921 +       btr_search_x_unlock_all();
922         if (UNIV_LIKELY_NULL(heap)) {
923                 mem_heap_free(heap);
924         }
925 --- a/storage/innobase/buf/buf0buf.c
926 +++ b/storage/innobase/buf/buf0buf.c
927 @@ -950,6 +950,7 @@
928  
929         block->check_index_page_at_flush = FALSE;
930         block->index = NULL;
931 +       block->btr_search_latch = NULL;
932  
933         block->is_hashed = FALSE;
934  
935 @@ -1414,7 +1415,7 @@
936                         /* To follow the latching order, we
937                         have to release btr_search_latch
938                         before acquiring block->latch. */
939 -                       rw_lock_x_unlock(&btr_search_latch);
940 +                       btr_search_x_unlock_all();
941                         /* When we release the search latch,
942                         we must rescan all blocks, because
943                         some may become hashed again. */
944 @@ -1445,11 +1446,11 @@
945                         anything.  block->is_hashed can only
946                         be set on uncompressed file pages. */
947  
948 -                       btr_search_drop_page_hash_index(block);
949 +                       btr_search_drop_page_hash_index(block, NULL);
950  
951                         rw_lock_x_unlock(&block->lock);
952  
953 -                       rw_lock_x_lock(&btr_search_latch);
954 +                       btr_search_x_lock_all();
955  
956                         ut_ad(!btr_search_enabled);
957                 }
958 @@ -1468,7 +1469,11 @@
959         ibool           released_search_latch;
960  
961  #ifdef UNIV_SYNC_DEBUG
962 -       ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
963 +       ulint   j;
964 +
965 +       for (j = 0; j < btr_search_index_num; j++) {
966 +               ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
967 +       }
968  #endif /* UNIV_SYNC_DEBUG */
969         ut_ad(!btr_search_enabled);
970  
971 @@ -2204,6 +2209,7 @@
972  {
973         block->check_index_page_at_flush = FALSE;
974         block->index            = NULL;
975 +       block->btr_search_latch = NULL;
976  
977         block->n_hash_helps     = 0;
978         block->is_hashed        = FALSE;
979 --- a/storage/innobase/buf/buf0lru.c
980 +++ b/storage/innobase/buf/buf0lru.c
981 @@ -560,7 +560,7 @@
982  
983                 mutex_exit(&buf_pool->LRU_list_mutex);
984  
985 -               rw_lock_s_lock(&btr_search_latch);
986 +               btr_search_s_lock_all();
987                 chunk = buf_pool->chunks;
988                 for (j = buf_pool->n_chunks; j--; chunk++) {
989                         buf_block_t*    block   = chunk->blocks;
990 @@ -572,16 +572,16 @@
991                                         continue;
992                                 }
993  
994 -                               rw_lock_s_unlock(&btr_search_latch);
995 +                               btr_search_s_unlock_all();
996  
997                                 rw_lock_x_lock(&block->lock);
998 -                               btr_search_drop_page_hash_index(block);
999 +                               btr_search_drop_page_hash_index(block, NULL);
1000                                 rw_lock_x_unlock(&block->lock);
1001  
1002 -                               rw_lock_s_lock(&btr_search_latch);
1003 +                               btr_search_s_lock_all();
1004                         }
1005                 }
1006 -               rw_lock_s_unlock(&btr_search_latch);
1007 +               btr_search_s_unlock_all();
1008         }
1009  }
1010  
1011 @@ -1744,7 +1744,7 @@
1012  
1013                 UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1014                                UNIV_PAGE_SIZE);
1015 -               btr_search_drop_page_hash_index((buf_block_t*) bpage);
1016 +               btr_search_drop_page_hash_index((buf_block_t*) bpage, NULL);
1017                 UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1018                                  UNIV_PAGE_SIZE);
1019  
1020 --- a/storage/innobase/dict/dict0dict.c
1021 +++ b/storage/innobase/dict/dict0dict.c
1022 @@ -1846,7 +1846,7 @@
1023         zero. */
1024  
1025         for (;;) {
1026 -               ulint ref_count = btr_search_info_get_ref_count(info);
1027 +               ulint ref_count = btr_search_info_get_ref_count(info, index->id);
1028                 if (ref_count == 0) {
1029                         break;
1030                 }
1031 --- a/storage/innobase/ha/ha0ha.c
1032 +++ b/storage/innobase/ha/ha0ha.c
1033 @@ -102,7 +102,8 @@
1034         ut_ad(table);
1035         ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1036  #ifdef UNIV_SYNC_DEBUG
1037 -       ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1038 +       /* cannot identificate which btr_search_latch[i] for now */
1039 +       //ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
1040  #endif /* UNIV_SYNC_DEBUG */
1041  
1042  #ifndef UNIV_HOTBACKUP
1043 --- a/storage/innobase/handler/ha_innodb.cc
1044 +++ b/storage/innobase/handler/ha_innodb.cc
1045 @@ -11824,6 +11824,11 @@
1046    "Disable with --skip-innodb-adaptive-hash-index.",
1047    NULL, innodb_adaptive_hash_index_update, TRUE);
1048  
1049 +static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1050 +  PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1051 +  "Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
1052 +  NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
1053 +
1054  static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
1055    PLUGIN_VAR_RQCMDARG,
1056    "Replication thread delay (ms) on the slave server if "
1057 @@ -12204,6 +12209,7 @@
1058    MYSQL_SYSVAR(use_sys_stats_table),
1059    MYSQL_SYSVAR(stats_sample_pages),
1060    MYSQL_SYSVAR(adaptive_hash_index),
1061 +  MYSQL_SYSVAR(adaptive_hash_index_partitions),
1062    MYSQL_SYSVAR(stats_method),
1063    MYSQL_SYSVAR(replication_delay),
1064    MYSQL_SYSVAR(status_file),
1065 --- a/storage/innobase/include/btr0sea.h
1066 +++ b/storage/innobase/include/btr0sea.h
1067 @@ -85,7 +85,8 @@
1068  ulint
1069  btr_search_info_get_ref_count(
1070  /*==========================*/
1071 -       btr_search_t*   info);  /*!< in: search info. */
1072 +       btr_search_t*   info,   /*!< in: search info. */
1073 +       index_id_t      key);
1074  /*********************************************************************//**
1075  Updates the search info. */
1076  UNIV_INLINE
1077 @@ -136,10 +137,11 @@
1078  void
1079  btr_search_drop_page_hash_index(
1080  /*============================*/
1081 -       buf_block_t*    block); /*!< in: block containing index page,
1082 +       buf_block_t*    block,  /*!< in: block containing index page,
1083                                 s- or x-latched, or an index page
1084                                 for which we know that
1085                                 block->buf_fix_count == 0 */
1086 +       dict_index_t*   index_in);
1087  /************************************************************************
1088  Drops a page hash index based on index */
1089  UNIV_INTERN
1090 @@ -199,10 +201,47 @@
1091  # define btr_search_validate() TRUE
1092  #endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
1093  
1094 +/********************************************************************//**
1095 +New functions to control split btr_search_index */
1096 +UNIV_INLINE
1097 +hash_table_t*
1098 +btr_search_get_hash_index(
1099 +/*======================*/
1100 +       index_id_t      key);
1101 +
1102 +UNIV_INLINE
1103 +rw_lock_t*
1104 +btr_search_get_latch(
1105 +/*=================*/
1106 +       index_id_t      key);
1107 +
1108 +UNIV_INLINE
1109 +void
1110 +btr_search_x_lock_all(void);
1111 +/*========================*/
1112 +
1113 +UNIV_INLINE
1114 +void
1115 +btr_search_x_unlock_all(void);
1116 +/*==========================*/
1117 +
1118 +UNIV_INLINE
1119 +void
1120 +btr_search_s_lock_all(void);
1121 +/*========================*/
1122 +
1123 +UNIV_INLINE
1124 +void
1125 +btr_search_s_unlock_all(void);
1126 +/*==========================*/
1127 +
1128 +
1129  /** Flag: has the search system been enabled?
1130  Protected by btr_search_latch and btr_search_enabled_mutex. */
1131  extern char    btr_search_enabled;
1132  
1133 +extern ulint   btr_search_index_num;
1134 +
1135  /** Flag: whether the search system has completed its disabling process,
1136  It is set to TRUE right after buf_pool_drop_hash_index() in
1137  btr_search_disable(), indicating hash index entries are cleaned up.
1138 @@ -269,7 +308,7 @@
1139  
1140  /** The hash index system */
1141  struct btr_search_sys_struct{
1142 -       hash_table_t*   hash_index;     /*!< the adaptive hash index,
1143 +       hash_table_t**  hash_index;     /*!< the adaptive hash index,
1144                                         mapping dtuple_fold values
1145                                         to rec_t pointers on index pages */
1146  };
1147 @@ -290,10 +329,12 @@
1148  
1149  Bear in mind (3) and (4) when using the hash index.
1150  */
1151 -extern rw_lock_t*      btr_search_latch_temp;
1152 +//extern rw_lock_t*    btr_search_latch_temp;
1153 +
1154 +extern rw_lock_t**     btr_search_latch_part;
1155  
1156  /** The latch protecting the adaptive search system */
1157 -#define btr_search_latch       (*btr_search_latch_temp)
1158 +//#define btr_search_latch     (*btr_search_latch_temp)
1159  
1160  #ifdef UNIV_SEARCH_PERF_STAT
1161  /** Number of successful adaptive hash index lookups */
1162 --- a/storage/innobase/include/btr0sea.ic
1163 +++ b/storage/innobase/include/btr0sea.ic
1164 @@ -62,8 +62,8 @@
1165         btr_search_t*   info;
1166  
1167  #ifdef UNIV_SYNC_DEBUG
1168 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1169 -       ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1170 +       ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1171 +       ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1172  #endif /* UNIV_SYNC_DEBUG */
1173  
1174         info = btr_search_get_info(index);
1175 @@ -82,3 +82,72 @@
1176  
1177         btr_search_info_update_slow(info, cursor);
1178  }
1179 +
1180 +/*********************************************************************//**
1181 +New functions to control split btr_search_index */
1182 +UNIV_INLINE
1183 +hash_table_t*
1184 +btr_search_get_hash_index(
1185 +/*======================*/
1186 +       index_id_t      key)
1187 +{
1188 +       return(btr_search_sys->hash_index[key % btr_search_index_num]);
1189 +}
1190 +
1191 +UNIV_INLINE
1192 +rw_lock_t*
1193 +btr_search_get_latch(
1194 +/*=================*/
1195 +       index_id_t      key)
1196 +{
1197 +       return(btr_search_latch_part[key % btr_search_index_num]);
1198 +}
1199 +
1200 +UNIV_INLINE
1201 +void
1202 +btr_search_x_lock_all(void)
1203 +/*=======================*/
1204 +{
1205 +       ulint   i;
1206 +
1207 +       for (i = 0; i < btr_search_index_num; i++) {
1208 +               rw_lock_x_lock(btr_search_latch_part[i]);
1209 +       }
1210 +}
1211 +
1212 +UNIV_INLINE
1213 +void
1214 +btr_search_x_unlock_all(void)
1215 +/*==========================*/
1216 +{
1217 +       ulint   i;
1218 +
1219 +       for (i = 0; i < btr_search_index_num; i++) {
1220 +               rw_lock_x_unlock(btr_search_latch_part[i]);
1221 +       }
1222 +}
1223 +
1224 +UNIV_INLINE
1225 +void
1226 +btr_search_s_lock_all(void)
1227 +/*=======================*/
1228 +{
1229 +       ulint   i;
1230 +
1231 +       for (i = 0; i < btr_search_index_num; i++) {
1232 +               rw_lock_s_lock(btr_search_latch_part[i]);
1233 +       }
1234 +}
1235 +
1236 +UNIV_INLINE
1237 +void
1238 +btr_search_s_unlock_all(void)
1239 +/*=========================*/
1240 +{
1241 +       ulint   i;
1242 +
1243 +       for (i = 0; i < btr_search_index_num; i++) {
1244 +               rw_lock_s_unlock(btr_search_latch_part[i]);
1245 +       }
1246 +}
1247 +
1248 --- a/storage/innobase/include/buf0buf.h
1249 +++ b/storage/innobase/include/buf0buf.h
1250 @@ -1576,7 +1576,7 @@
1251                                         pointers in the adaptive hash index
1252                                         pointing to this frame */
1253  #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1254 -       unsigned        is_hashed:1;    /*!< TRUE if hash index has
1255 +       volatile unsigned       is_hashed:1;    /*!< TRUE if hash index has
1256                                         already been built on this
1257                                         page; note that it does not
1258                                         guarantee that the index is
1259 @@ -1590,6 +1590,7 @@
1260         unsigned        curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1261         dict_index_t*   index;          /*!< Index for which the adaptive
1262                                         hash index has been created. */
1263 +       volatile rw_lock_t*     btr_search_latch;
1264         /* @} */
1265  # ifdef UNIV_SYNC_DEBUG
1266         /** @name Debug fields */
1267 --- a/storage/innobase/page/page0page.c
1268 +++ b/storage/innobase/page/page0page.c
1269 @@ -218,7 +218,7 @@
1270         const ibool     is_hashed       = block->is_hashed;
1271  
1272         if (is_hashed) {
1273 -               rw_lock_x_lock(&btr_search_latch);
1274 +               rw_lock_x_lock(btr_search_get_latch(block->index->id));
1275         }
1276  
1277         ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
1278 @@ -244,7 +244,7 @@
1279  
1280  #ifndef UNIV_HOTBACKUP
1281         if (is_hashed) {
1282 -               rw_lock_x_unlock(&btr_search_latch);
1283 +               rw_lock_x_unlock(btr_search_get_latch(block->index->id));
1284         }
1285  #endif /* !UNIV_HOTBACKUP */
1286  }
1287 --- a/storage/innobase/page/page0zip.c
1288 +++ b/storage/innobase/page/page0zip.c
1289 @@ -4456,7 +4456,7 @@
1290  
1291  #ifndef UNIV_HOTBACKUP
1292         temp_block = buf_block_alloc(buf_pool);
1293 -       btr_search_drop_page_hash_index(block);
1294 +       btr_search_drop_page_hash_index(block, index);
1295         block->check_index_page_at_flush = TRUE;
1296  #else /* !UNIV_HOTBACKUP */
1297         ut_ad(block == back_block1);
1298 --- a/storage/innobase/row/row0mysql.c
1299 +++ b/storage/innobase/row/row0mysql.c
1300 @@ -2594,7 +2594,7 @@
1301                         /* check adaptive hash entries */
1302                         index = dict_table_get_first_index(table);
1303                         while (index) {
1304 -                               ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1305 +                               ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1306                                 if (ref_count) {
1307                                         fprintf(stderr, "InnoDB: Warning:"
1308                                                 " hash index ref_count (%lu) is not zero"
1309 @@ -2955,7 +2955,7 @@
1310                         table->space = space;
1311                         index = dict_table_get_first_index(table);
1312                         do {
1313 -                               ulint ref_count = btr_search_info_get_ref_count(index->search_info);
1314 +                               ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
1315                                 /* check adaptive hash entries */
1316                                 if (ref_count) {
1317                                         fprintf(stderr, "InnoDB: Warning:"
1318 --- a/storage/innobase/row/row0sel.c
1319 +++ b/storage/innobase/row/row0sel.c
1320 @@ -1222,7 +1222,7 @@
1321         ut_ad(plan->unique_search);
1322         ut_ad(!plan->must_get_clust);
1323  #ifdef UNIV_SYNC_DEBUG
1324 -       ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
1325 +       ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1326  #endif /* UNIV_SYNC_DEBUG */
1327  
1328         row_sel_open_pcur(plan, TRUE, mtr);
1329 @@ -1393,10 +1393,10 @@
1330             && !plan->must_get_clust
1331             && !plan->table->big_rows) {
1332                 if (!search_latch_locked) {
1333 -                       rw_lock_s_lock(&btr_search_latch);
1334 +                       rw_lock_s_lock(btr_search_get_latch(index->id));
1335  
1336                         search_latch_locked = TRUE;
1337 -               } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {
1338 +               } else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
1339  
1340                         /* There is an x-latch request waiting: release the
1341                         s-latch for a moment; as an s-latch here is often
1342 @@ -1405,8 +1405,8 @@
1343                         from acquiring an s-latch for a long time, lowering
1344                         performance significantly in multiprocessors. */
1345  
1346 -                       rw_lock_s_unlock(&btr_search_latch);
1347 -                       rw_lock_s_lock(&btr_search_latch);
1348 +                       rw_lock_s_unlock(btr_search_get_latch(index->id));
1349 +                       rw_lock_s_lock(btr_search_get_latch(index->id));
1350                 }
1351  
1352                 found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
1353 @@ -1429,7 +1429,7 @@
1354         }
1355  
1356         if (search_latch_locked) {
1357 -               rw_lock_s_unlock(&btr_search_latch);
1358 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
1359  
1360                 search_latch_locked = FALSE;
1361         }
1362 @@ -2005,7 +2005,7 @@
1363  
1364  func_exit:
1365         if (search_latch_locked) {
1366 -               rw_lock_s_unlock(&btr_search_latch);
1367 +               rw_lock_s_unlock(btr_search_get_latch(index->id));
1368         }
1369         if (UNIV_LIKELY_NULL(heap)) {
1370                 mem_heap_free(heap);
1371 @@ -3408,6 +3408,8 @@
1372         /* if the returned record was locked and we did a semi-consistent
1373         read (fetch the newest committed version), then this is set to
1374         TRUE */
1375 +       ulint           i;
1376 +       ulint           should_release;
1377  #ifdef UNIV_SEARCH_DEBUG
1378         ulint           cnt                             = 0;
1379  #endif /* UNIV_SEARCH_DEBUG */
1380 @@ -3505,18 +3507,33 @@
1381         /* PHASE 0: Release a possible s-latch we are holding on the
1382         adaptive hash index latch if there is someone waiting behind */
1383  
1384 -       if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)
1385 -           && trx->has_search_latch) {
1386 +       should_release = 0;
1387 +       for (i = 0; i < btr_search_index_num; i++) {
1388 +               /* we should check all latches (fix Bug#791030) */
1389 +               if (rw_lock_get_writer(btr_search_latch_part[i])
1390 +                   != RW_LOCK_NOT_LOCKED) {
1391 +                       should_release |= ((ulint)1 << i);
1392 +               }
1393 +       }
1394 +
1395 +       if (should_release) {
1396  
1397                 /* There is an x-latch request on the adaptive hash index:
1398                 release the s-latch to reduce starvation and wait for
1399                 BTR_SEA_TIMEOUT rounds before trying to keep it again over
1400                 calls from MySQL */
1401  
1402 -               rw_lock_s_unlock(&btr_search_latch);
1403 -               trx->has_search_latch = FALSE;
1404 +               for (i = 0; i < btr_search_index_num; i++) {
1405 +                       /* we should release all s-latches (fix Bug#791030) */
1406 +                       if (trx->has_search_latch & ((ulint)1 << i)) {
1407 +                               rw_lock_s_unlock(btr_search_latch_part[i]);
1408 +                               trx->has_search_latch &= (~((ulint)1 << i));
1409 +                       }
1410 +               }
1411  
1412 +               if (!trx->has_search_latch) {
1413                 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1414 +               }
1415         }
1416  
1417         /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1418 @@ -3667,9 +3684,28 @@
1419                         hash index semaphore! */
1420  
1421  #ifndef UNIV_SEARCH_DEBUG
1422 -                       if (!trx->has_search_latch) {
1423 -                               rw_lock_s_lock(&btr_search_latch);
1424 -                               trx->has_search_latch = TRUE;
1425 +                       if (!(trx->has_search_latch
1426 +                             & ((ulint)1 << (index->id % btr_search_index_num)))) {
1427 +                               if (trx->has_search_latch
1428 +                                   < ((ulint)1 << (index->id % btr_search_index_num))) {
1429 +                                       rw_lock_s_lock(btr_search_get_latch(index->id));
1430 +                                       trx->has_search_latch |=
1431 +                                               ((ulint)1 << (index->id % btr_search_index_num));
1432 +                               } else {
1433 +                                       /* should re-lock to obay latch-order */
1434 +                                       for (i = 0; i < btr_search_index_num; i++) {
1435 +                                               if (trx->has_search_latch & ((ulint)1 << i)) {
1436 +                                                       rw_lock_s_unlock(btr_search_latch_part[i]);
1437 +                                               }
1438 +                                       }
1439 +                                       trx->has_search_latch |=
1440 +                                               ((ulint)1 << (index->id % btr_search_index_num));
1441 +                                       for (i = 0; i < btr_search_index_num; i++) {
1442 +                                               if (trx->has_search_latch & ((ulint)1 << i)) {
1443 +                                                       rw_lock_s_lock(btr_search_latch_part[i]);
1444 +                                               }
1445 +                                       }
1446 +                               }
1447                         }
1448  #endif
1449                         switch (row_sel_try_search_shortcut_for_mysql(
1450 @@ -3730,7 +3766,11 @@
1451  
1452                                         trx->search_latch_timeout--;
1453  
1454 -                                       rw_lock_s_unlock(&btr_search_latch);
1455 +                                       for (i = 0; i < btr_search_index_num; i++) {
1456 +                                               if (trx->has_search_latch & ((ulint)1 << i)) {
1457 +                                                       rw_lock_s_unlock(btr_search_latch_part[i]);
1458 +                                               }
1459 +                                       }
1460                                         trx->has_search_latch = FALSE;
1461                                 }
1462  
1463 @@ -3754,7 +3794,12 @@
1464         /* PHASE 3: Open or restore index cursor position */
1465  
1466         if (trx->has_search_latch) {
1467 -               rw_lock_s_unlock(&btr_search_latch);
1468 +
1469 +               for (i = 0; i < btr_search_index_num; i++) {
1470 +                       if (trx->has_search_latch & ((ulint)1 << i)) {
1471 +                               rw_lock_s_unlock(btr_search_latch_part[i]);
1472 +                       }
1473 +               }
1474                 trx->has_search_latch = FALSE;
1475         }
1476  
1477 --- a/storage/innobase/srv/srv0srv.c
1478 +++ b/storage/innobase/srv/srv0srv.c
1479 @@ -2051,7 +2051,9 @@
1480               "-------------------------------------\n", file);
1481         ibuf_print(file);
1482  
1483 -       ha_print_info(file, btr_search_sys->hash_index);
1484 +       for (i = 0; i < btr_search_index_num; i++) {
1485 +               ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
1486 +       }
1487  
1488         fprintf(file,
1489                 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1490 @@ -2076,14 +2078,15 @@
1491                         ut_total_allocated_memory,
1492                         mem_pool_get_reserved(mem_comm_pool));
1493         /* Calcurate reserved memories */
1494 -       if (btr_search_sys && btr_search_sys->hash_index->heap) {
1495 -               btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);
1496 +       if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1497 +               btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
1498         } else {
1499                 btr_search_sys_subtotal = 0;
1500 -               for (i=0; i < btr_search_sys->hash_index->n_mutexes; i++) {
1501 -                       btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);
1502 +               for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
1503 +                       btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
1504                 }
1505         }
1506 +       btr_search_sys_subtotal *= btr_search_index_num;
1507  
1508         lock_sys_subtotal = 0;
1509         if (trx_sys) {
1510 @@ -2109,10 +2112,10 @@
1511                         "    Recovery system     %lu \t(%lu + %lu)\n",
1512  
1513                         (ulong) (btr_search_sys
1514 -                               ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0)
1515 +                               ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
1516                         + btr_search_sys_subtotal,
1517                         (ulong) (btr_search_sys
1518 -                               ? (btr_search_sys->hash_index->n_cells * sizeof(hash_cell_t)) : 0),
1519 +                               ? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
1520                         (ulong) btr_search_sys_subtotal,
1521  
1522                         (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1523 --- a/storage/innobase/sync/sync0sync.c
1524 +++ b/storage/innobase/sync/sync0sync.c
1525 @@ -1222,7 +1222,6 @@
1526         case SYNC_OUTER_ANY_LATCH:
1527         case SYNC_FILE_FORMAT_TAG:
1528         case SYNC_DOUBLEWRITE:
1529 -       case SYNC_SEARCH_SYS:
1530         case SYNC_SEARCH_SYS_CONF:
1531         case SYNC_TRX_LOCK_HEAP:
1532         case SYNC_KERNEL:
1533 @@ -1244,6 +1243,7 @@
1534                         ut_error;
1535                 }
1536                 break;
1537 +       case SYNC_SEARCH_SYS:
1538         case SYNC_BUF_LRU_LIST:
1539         case SYNC_BUF_FLUSH_LIST:
1540         case SYNC_BUF_PAGE_HASH:
1541 --- a/storage/innobase/trx/trx0trx.c
1542 +++ b/storage/innobase/trx/trx0trx.c
1543 @@ -265,8 +265,14 @@
1544  /*=================================*/
1545         trx_t*     trx) /*!< in: transaction */
1546  {
1547 +       ulint   i;
1548 +
1549         if (trx->has_search_latch) {
1550 -               rw_lock_s_unlock(&btr_search_latch);
1551 +               for (i = 0; i < btr_search_index_num; i++) {
1552 +                       if (trx->has_search_latch & ((ulint)1 << i)) {
1553 +                               rw_lock_s_unlock(btr_search_latch_part[i]);
1554 +                       }
1555 +               }
1556  
1557                 trx->has_search_latch = FALSE;
1558         }
This page took 0.153595 seconds and 4 git commands to generate.