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