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