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