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