Merge lp:~akopytov/percona-server/ahi-fixes-5.6 into lp:percona-server/5.6

Proposed by Alexey Kopytov on 2013-09-02
Status: Merged
Approved by: Laurynas Biveinis on 2013-09-06
Approved revision: 423
Merged at revision: 421
Proposed branch: lp:~akopytov/percona-server/ahi-fixes-5.6
Merge into: lp:percona-server/5.6
Diff against target: 1957 lines (+482/-381)
25 files modified
Percona-Server/mysql-test/r/percona_bug1218330.result (+14/-0)
Percona-Server/mysql-test/t/percona_bug1218330-master.opt (+1/-0)
Percona-Server/mysql-test/t/percona_bug1218330.test (+72/-0)
Percona-Server/storage/innobase/btr/btr0cur.cc (+7/-7)
Percona-Server/storage/innobase/btr/btr0sea.cc (+109/-132)
Percona-Server/storage/innobase/buf/buf0buf.cc (+0/-2)
Percona-Server/storage/innobase/dict/dict0boot.cc (+6/-0)
Percona-Server/storage/innobase/dict/dict0dict.cc (+5/-3)
Percona-Server/storage/innobase/dict/dict0load.cc (+1/-0)
Percona-Server/storage/innobase/ha/ha0ha.cc (+2/-2)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+21/-19)
Percona-Server/storage/innobase/handler/xtradb_i_s.cc (+35/-33)
Percona-Server/storage/innobase/ibuf/ibuf0ibuf.cc (+2/-0)
Percona-Server/storage/innobase/include/btr0sea.h (+35/-9)
Percona-Server/storage/innobase/include/btr0sea.ic (+66/-11)
Percona-Server/storage/innobase/include/btr0types.h (+7/-6)
Percona-Server/storage/innobase/include/buf0buf.h (+0/-2)
Percona-Server/storage/innobase/include/dict0mem.h (+4/-0)
Percona-Server/storage/innobase/include/trx0trx.h (+7/-5)
Percona-Server/storage/innobase/include/trx0trx.ic (+5/-12)
Percona-Server/storage/innobase/row/row0ftsort.cc (+3/-0)
Percona-Server/storage/innobase/row/row0sel.cc (+32/-91)
Percona-Server/storage/innobase/srv/srv0srv.cc (+42/-44)
Percona-Server/storage/innobase/sync/sync0sync.cc (+3/-3)
Percona-Server/storage/innobase/trx/trx0trx.cc (+3/-0)
To merge this branch: bzr merge lp:~akopytov/percona-server/ahi-fixes-5.6
Reviewer Review Type Date Requested Status
Laurynas Biveinis 2013-09-02 Approve on 2013-09-06
Review via email: mp+183473@code.launchpad.net
To post a comment you must log in.

    - Same comments as for the 5.5 MP.
    - Diff line 182--185: missing arg comment, and, uhm, why add more
      "=====" ?
    - Diff line 385--391 drops MONITOR_INC call.

review: Needs Fixing
Alexey Kopytov (akopytov) wrote :

Hi Laurynas,

On Wed, 04 Sep 2013 15:00:11 -0000, Laurynas Biveinis wrote:
> Review: Needs Fixing
>
> - Same comments as for the 5.5 MP.
> - Diff line 182--185: missing arg comment, and, uhm, why add more
> "=====" ?

Oh noes :)

> - Diff line 385--391 drops MONITOR_INC call.
>

This is a good catch, will fix.

Alexey Kopytov (akopytov) wrote :

Hi Laurynas,

On Wed, 04 Sep 2013 15:00:11 -0000, Laurynas Biveinis wrote:
> Review: Needs Fixing
>
> - Same comments as for the 5.5 MP.
> - Diff line 182--185: missing arg comment, and, uhm, why add more
> "=====" ?

Actually, this is how the diff looks in my tree:

@@ -133,17 +130,17 @@
  void
  btr_search_check_free_space_in_heap(
  /*=====================================*/
- index_id_t key)
+ dict_index_t* index)

I.e. it doesn't touch the comment part. But will fix anyway.

Alexey Kopytov (akopytov) wrote :

Hi Laurynas,

On Wed, 04 Sep 2013 15:00:11 -0000, Laurynas Biveinis wrote:
> - Diff line 385--391 drops MONITOR_INC call.
>

Same here. It appears to be some bogus change. This is how rev. diff
looks in my tree:

  #ifdef UNIV_SYNC_DEBUG
- ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
+ RW_LOCK_EX));
  #endif /* UNIV_SYNC_DEBUG */

- ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
- block, rec);
+ ha_insert_for_fold(btr_search_get_hash_table(cursor->index),
+ fold, block, rec);
   }
  }

I.e. there was simply no MONITOR_INC call. Not sure whom to blame here,
bzr or LP diff viewer.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'Percona-Server/mysql-test/r/percona_bug1218330.result'
2--- Percona-Server/mysql-test/r/percona_bug1218330.result 1970-01-01 00:00:00 +0000
3+++ Percona-Server/mysql-test/r/percona_bug1218330.result 2013-09-02 14:08:46 +0000
4@@ -0,0 +1,14 @@
5+CREATE TABLE t1 (
6+a INT PRIMARY KEY, b INT,
7+c CHAR(200),
8+UNIQUE INDEX b(b)) ENGINE=InnoDB;
9+INSERT INTO t1 VALUES (1, 1, REPEAT("a", 200));
10+should_be_1
11+1
12+should_be_1
13+1
14+should_be_1
15+1
16+should_be_1
17+1
18+DROP TABLE t1;
19
20=== added file 'Percona-Server/mysql-test/t/percona_bug1218330-master.opt'
21--- Percona-Server/mysql-test/t/percona_bug1218330-master.opt 1970-01-01 00:00:00 +0000
22+++ Percona-Server/mysql-test/t/percona_bug1218330-master.opt 2013-09-02 14:08:46 +0000
23@@ -0,0 +1,1 @@
24+--innodb-adaptive-hash-index-partitions=32
25
26=== added file 'Percona-Server/mysql-test/t/percona_bug1218330.test'
27--- Percona-Server/mysql-test/t/percona_bug1218330.test 1970-01-01 00:00:00 +0000
28+++ Percona-Server/mysql-test/t/percona_bug1218330.test 2013-09-02 14:08:46 +0000
29@@ -0,0 +1,72 @@
30+############################################################################
31+# Bug #1218330: Adaptive hash index memory is incorrectly calculated in SHOW
32+# ENGINE INNODB STATUS and I_S
33+############################################################################
34+
35+--source include/have_innodb.inc
36+
37+let $adaptive_hash_mem_1=`SELECT VARIABLE_VALUE FROM
38+ INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
39+ VARIABLE_NAME='Innodb_mem_adaptive_hash'`;
40+
41+let $is_adaptive_hash_mem_constant_1=`SELECT CONSTANT_MEMORY FROM
42+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
43+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
44+
45+let $is_adaptive_hash_mem_variable_1=`SELECT VARIABLE_MEMORY FROM
46+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
47+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
48+
49+let $is_adaptive_hash_mem_total_1=`SELECT TOTAL_MEMORY FROM
50+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
51+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
52+
53+CREATE TABLE t1 (
54+ a INT PRIMARY KEY, b INT,
55+ c CHAR(200),
56+ UNIQUE INDEX b(b)) ENGINE=InnoDB;
57+
58+INSERT INTO t1 VALUES (1, 1, REPEAT("a", 200));
59+
60+--disable_query_log
61+
62+--let $i=200
63+--disable_result_log
64+while ($i)
65+{
66+ SELECT a FROM t1 WHERE a=1;
67+ SELECT b FROM t1 WHERE b=1;
68+ --dec $i
69+}
70+--enable_result_log
71+
72+let $adaptive_hash_mem_2=`SELECT VARIABLE_VALUE FROM
73+ INFORMATION_SCHEMA.GLOBAL_STATUS WHERE
74+ VARIABLE_NAME='Innodb_mem_adaptive_hash'`;
75+
76+let $is_adaptive_hash_mem_constant_2=`SELECT CONSTANT_MEMORY FROM
77+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
78+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
79+
80+let $is_adaptive_hash_mem_variable_2=`SELECT VARIABLE_MEMORY FROM
81+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
82+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
83+
84+let $is_adaptive_hash_mem_total_2=`SELECT TOTAL_MEMORY FROM
85+ INFORMATION_SCHEMA.XTRADB_INTERNAL_HASH_TABLES WHERE
86+ INTERNAL_HASH_TABLE_NAME='Adaptive hash index'`;
87+
88+# The original implementation would should identical values in
89+# adaptive_hash_mem_1 and adaptive_hash_mem_2
90+
91+--eval SELECT $adaptive_hash_mem_1 != $adaptive_hash_mem_2 as should_be_1
92+
93+# Should show identical constant, but different variable parts
94+
95+--eval SELECT $is_adaptive_hash_mem_total_1 != $is_adaptive_hash_mem_total_2 as should_be_1
96+--eval SELECT $is_adaptive_hash_mem_constant_1 = $is_adaptive_hash_mem_constant_2 as should_be_1
97+--eval SELECT $is_adaptive_hash_mem_variable_1 != $is_adaptive_hash_mem_variable_2 as should_be_1
98+
99+--enable_query_log
100+
101+DROP TABLE t1;
102
103=== modified file 'Percona-Server/storage/innobase/btr/btr0cur.cc'
104--- Percona-Server/storage/innobase/btr/btr0cur.cc 2013-08-29 17:05:40 +0000
105+++ Percona-Server/storage/innobase/btr/btr0cur.cc 2013-09-02 14:08:46 +0000
106@@ -535,9 +535,9 @@
107
108 # ifdef UNIV_SEARCH_PERF_STAT
109 info->n_searches++;
110-# endif
111- if ((rw_lock_get_writer(btr_search_get_latch(cursor->index->id))
112- == RW_LOCK_NOT_LOCKED)
113+#endif
114+ if (rw_lock_get_writer(btr_search_get_latch(cursor->index)) ==
115+ RW_LOCK_NOT_LOCKED
116 && latch_mode <= BTR_MODIFY_LEAF
117 && info->last_hash_succ
118 && !estimate
119@@ -573,7 +573,7 @@
120
121 if (has_search_latch) {
122 /* Release possible search latch to obey latching order */
123- rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
124+ rw_lock_s_unlock(btr_search_get_latch(cursor->index));
125 }
126
127 /* Store the position of the tree latch we push to mtr so that we
128@@ -896,7 +896,7 @@
129
130 if (has_search_latch) {
131
132- rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
133+ rw_lock_s_lock(btr_search_get_latch(cursor->index));
134 }
135 }
136
137@@ -2163,13 +2163,13 @@
138 btr_search_update_hash_on_delete(cursor);
139 }
140
141- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
142+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
143 }
144
145 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
146
147 if (is_hashed) {
148- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
149+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
150 }
151
152 btr_cur_update_in_place_log(flags, rec, index, update,
153
154=== modified file 'Percona-Server/storage/innobase/btr/btr0sea.cc'
155--- Percona-Server/storage/innobase/btr/btr0sea.cc 2013-08-29 17:05:40 +0000
156+++ Percona-Server/storage/innobase/btr/btr0sea.cc 2013-09-02 14:08:46 +0000
157@@ -65,15 +65,14 @@
158 cache line as btr_search_latch */
159 UNIV_INTERN byte btr_sea_pad1[64];
160
161-/** The latch protecting the adaptive search system: this latch protects the
162-(1) positions of records on those pages where a hash index has been built.
163-NOTE: It does not protect values of non-ordering fields within a record from
164+/** Array of latches protecting individual AHI partitions. The latches
165+protect: (1) positions of records on those pages where a hash index from the
166+corresponding AHI partition has been built.
167+NOTE: They do not protect values of non-ordering fields within a record from
168 being updated in-place! We can use fact (1) to perform unique searches to
169 indexes. */
170
171-/* We will allocate the latches from dynamic memory to get them to the
172-same DRAM page as other hotspot semaphores */
173-UNIV_INTERN rw_lock_t** btr_search_latch_arr;
174+UNIV_INTERN rw_lock_t* btr_search_latch_arr;
175
176 /** padding to prevent other memory update hotspots from residing on
177 the same memory cache line */
178@@ -126,18 +125,18 @@
179 static
180 void
181 btr_search_check_free_space_in_heap(
182-/*================================*/
183- index_id_t key) /*!<in: id of the hashed index tree */
184+/*=====================================*/
185+ dict_index_t* index)
186 {
187 hash_table_t* table;
188 mem_heap_t* heap;
189
190 #ifdef UNIV_SYNC_DEBUG
191- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
192- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
193+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
194+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
195 #endif /* UNIV_SYNC_DEBUG */
196
197- table = btr_search_get_hash_index(key);
198+ table = btr_search_get_hash_table(index);
199
200 heap = table->heap;
201
202@@ -148,7 +147,7 @@
203 if (heap->free_block == NULL) {
204 buf_block_t* block = buf_block_alloc(NULL);
205
206- rw_lock_x_lock(btr_search_get_latch(key));
207+ rw_lock_x_lock(btr_search_get_latch(index));
208
209 if (heap->free_block == NULL) {
210 heap->free_block = block;
211@@ -156,7 +155,7 @@
212 buf_block_free(block);
213 }
214
215- rw_lock_x_unlock(btr_search_get_latch(key));
216+ rw_lock_x_unlock(btr_search_get_latch(index));
217 }
218 }
219
220@@ -182,31 +181,28 @@
221 /* We allocate the search latch from dynamic memory:
222 see above at the global variable definition */
223
224- /* btr_search_index_num should be no greater than bits of
225- trx->has_search_latch, which is ulint. */
226- ut_ad(btr_search_index_num <= sizeof(ulint));
227+ /* btr_search_index_num is constrained to machine word size for
228+ historical reasons. This limitation can be easily removed later. */
229
230- btr_search_latch_arr = (rw_lock_t**)
231- mem_alloc(sizeof(rw_lock_t *) * btr_search_index_num);
232+ btr_search_latch_arr = (rw_lock_t *)
233+ mem_alloc(sizeof(rw_lock_t) * btr_search_index_num);
234
235 btr_search_sys = (btr_search_sys_t*)
236 mem_alloc(sizeof(btr_search_sys_t));
237
238- btr_search_sys->hash_index = (hash_table_t **)
239+ btr_search_sys->hash_tables = (hash_table_t **)
240 mem_alloc(sizeof(hash_table_t *) * btr_search_index_num);
241
242 for (i = 0; i < btr_search_index_num; i++) {
243- btr_search_latch_arr[i] = (rw_lock_t *)
244- mem_alloc(sizeof(rw_lock_t));
245-
246- rw_lock_create(btr_search_latch_key, btr_search_latch_arr[i],
247- SYNC_SEARCH_SYS);
248-
249- btr_search_sys->hash_index[i]
250+
251+ rw_lock_create(btr_search_latch_key,
252+ &btr_search_latch_arr[i], SYNC_SEARCH_SYS);
253+
254+ btr_search_sys->hash_tables[i]
255 = ha_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
256
257 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
258- btr_search_sys->hash_index[i]->adaptive = TRUE;
259+ btr_search_sys->hash_tables[i]->adaptive = TRUE;
260 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
261 }
262 }
263@@ -222,20 +218,18 @@
264
265 for (i = 0; i < btr_search_index_num; i++) {
266
267- rw_lock_free(btr_search_latch_arr[i]);
268-
269- mem_free(btr_search_latch_arr[i]);
270-
271- mem_heap_free(btr_search_sys->hash_index[i]->heap);
272-
273- hash_table_free(btr_search_sys->hash_index[i]);
274+ rw_lock_free(&btr_search_latch_arr[i]);
275+
276+ mem_heap_free(btr_search_sys->hash_tables[i]->heap);
277+
278+ hash_table_free(btr_search_sys->hash_tables[i]);
279
280 }
281
282 mem_free(btr_search_latch_arr);
283 btr_search_latch_arr = NULL;
284
285- mem_free(btr_search_sys->hash_index);
286+ mem_free(btr_search_sys->hash_tables);
287
288 mem_free(btr_search_sys);
289 btr_search_sys = NULL;
290@@ -257,7 +251,7 @@
291 index = dict_table_get_next_index(index)) {
292
293 #ifdef UNIV_SYNC_DEBUG
294- ut_ad(rw_lock_own(btr_search_get_latch(index->id),
295+ ut_ad(rw_lock_own(btr_search_get_latch(index),
296 RW_LOCK_EX));
297 #endif /* UNIV_SYNC_DEBUG */
298 index->search_info->ref_count = 0;
299@@ -300,8 +294,8 @@
300
301 /* Clear the adaptive hash index. */
302 for (i = 0; i < btr_search_index_num; i++) {
303- hash_table_clear(btr_search_sys->hash_index[i]);
304- mem_heap_empty(btr_search_sys->hash_index[i]->heap);
305+ hash_table_clear(btr_search_sys->hash_tables[i]);
306+ mem_heap_empty(btr_search_sys->hash_tables[i]->heap);
307 }
308
309 btr_search_x_unlock_all();
310@@ -364,27 +358,27 @@
311
312 /*****************************************************************//**
313 Returns the value of ref_count. The value is protected by
314-btr_search_latch.
315+the .
316 @return ref_count value. */
317 UNIV_INTERN
318 ulint
319 btr_search_info_get_ref_count(
320 /*==========================*/
321 btr_search_t* info, /*!< in: search info. */
322- index_id_t key) /*!< in: id of the index owning search info */
323+ dict_index_t* index) /*!< in: index */
324 {
325 ulint ret;
326
327 ut_ad(info);
328
329 #ifdef UNIV_SYNC_DEBUG
330- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
331- ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
332+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
333+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
334 #endif /* UNIV_SYNC_DEBUG */
335
336- rw_lock_s_lock(btr_search_get_latch(key));
337+ rw_lock_s_lock(btr_search_get_latch(index));
338 ret = info->ref_count;
339- rw_lock_s_unlock(btr_search_get_latch(key));
340+ rw_lock_s_unlock(btr_search_get_latch(index));
341
342 return(ret);
343 }
344@@ -405,8 +399,8 @@
345 int cmp;
346
347 #ifdef UNIV_SYNC_DEBUG
348- ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
349- ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
350+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
351+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
352 #endif /* UNIV_SYNC_DEBUG */
353
354 if (dict_index_is_ibuf(index)) {
355@@ -522,9 +516,9 @@
356 /*!< in: cursor */
357 {
358 #ifdef UNIV_SYNC_DEBUG
359- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
360+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index),
361 RW_LOCK_SHARED));
362- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
363+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index),
364 RW_LOCK_EX));
365 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
366 || rw_lock_own(&block->lock, RW_LOCK_EX));
367@@ -609,7 +603,7 @@
368
369 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
370 #ifdef UNIV_SYNC_DEBUG
371- ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id),
372+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
373 RW_LOCK_EX));
374 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
375 || rw_lock_own(&(block->lock), RW_LOCK_EX));
376@@ -651,15 +645,12 @@
377 mem_heap_free(heap);
378 }
379 #ifdef UNIV_SYNC_DEBUG
380- ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id),
381+ ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
382 RW_LOCK_EX));
383 #endif /* UNIV_SYNC_DEBUG */
384
385- ha_insert_for_fold(
386- btr_search_get_hash_index(cursor->index->id), fold,
387- block, rec);
388-
389- MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
390+ ha_insert_for_fold(btr_search_get_hash_table(cursor->index),
391+ fold, block, rec);
392 }
393 }
394
395@@ -678,9 +669,9 @@
396 ulint* params2;
397
398 #ifdef UNIV_SYNC_DEBUG
399- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
400+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index),
401 RW_LOCK_SHARED));
402- ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
403+ ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index),
404 RW_LOCK_EX));
405 #endif /* UNIV_SYNC_DEBUG */
406
407@@ -699,7 +690,7 @@
408
409 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
410
411- btr_search_check_free_space_in_heap(cursor->index->id);
412+ btr_search_check_free_space_in_heap(cursor->index);
413 }
414
415 if (cursor->flag == BTR_CUR_HASH_FAIL) {
416@@ -709,11 +700,11 @@
417 btr_search_n_hash_fail++;
418 #endif /* UNIV_SEARCH_PERF_STAT */
419
420- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
421+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
422
423 btr_search_update_hash_ref(info, block, cursor);
424
425- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
426+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
427 }
428
429 if (build_index) {
430@@ -958,19 +949,18 @@
431 cursor->flag = BTR_CUR_HASH;
432
433 if (UNIV_LIKELY(!has_search_latch)) {
434- rw_lock_s_lock(btr_search_get_latch(index_id));
435+ rw_lock_s_lock(btr_search_get_latch(index));
436
437 if (UNIV_UNLIKELY(!btr_search_enabled)) {
438 goto failure_unlock;
439 }
440 }
441
442- ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id))
443- != RW_LOCK_EX);
444- ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
445+ ut_ad(rw_lock_get_writer(btr_search_get_latch(index)) != RW_LOCK_EX);
446+ ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index)) > 0);
447
448 rec = (rec_t*) ha_search_and_get_data(
449- btr_search_get_hash_index(index_id), fold);
450+ btr_search_get_hash_table(index), fold);
451
452 if (UNIV_UNLIKELY(!rec)) {
453 goto failure_unlock;
454@@ -988,7 +978,7 @@
455 goto failure_unlock;
456 }
457
458- rw_lock_s_unlock(btr_search_get_latch(index_id));
459+ rw_lock_s_unlock(btr_search_get_latch(index));
460
461 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
462 }
463@@ -1085,7 +1075,7 @@
464 /*-------------------------------------------*/
465 failure_unlock:
466 if (UNIV_LIKELY(!has_search_latch)) {
467- rw_lock_s_unlock(btr_search_get_latch(index_id));
468+ rw_lock_s_unlock(btr_search_get_latch(index));
469 }
470 failure:
471 cursor->flag = BTR_CUR_HASH_FAIL;
472@@ -1133,41 +1123,31 @@
473 const dict_index_t* index;
474 ulint* offsets;
475 btr_search_t* info;
476- rw_lock_t* btr_search_latch;
477
478 retry:
479- /* Do a dirty check on block->index, return if the block is
480- not in the adaptive hash index. This is to avoid acquiring
481- shared btr_search_latch for performance consideration. */
482- if (!block->index) {
483- return;
484- }
485-
486- btr_search_latch = block->btr_search_latch;
487-
488- if (UNIV_UNLIKELY(!btr_search_latch)) {
489+ /* Do a dirty check on block->index, return if the block is not in the
490+ adaptive hash index. This is to avoid acquiring an AHI latch for
491+ performance considerations. */
492+
493+ index = block->index;
494+ if (!index) {
495+
496 return;
497 }
498
499 #ifdef UNIV_SYNC_DEBUG
500- ut_ad(!rw_lock_own(btr_search_latch, RW_LOCK_SHARED));
501- ut_ad(!rw_lock_own(btr_search_latch, RW_LOCK_EX));
502+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
503+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
504 #endif /* UNIV_SYNC_DEBUG */
505-
506- rw_lock_s_lock(btr_search_latch);
507- if (UNIV_UNLIKELY(btr_search_latch != block->btr_search_latch)) {
508- rw_lock_s_unlock(btr_search_latch);
509+ rw_lock_s_lock(btr_search_get_latch(index));
510+
511+ if (UNIV_UNLIKELY(index != block->index)) {
512+
513+ rw_lock_s_unlock(btr_search_get_latch(index));
514+
515 goto retry;
516 }
517
518- index = block->index;
519- if (UNIV_UNLIKELY(!index)) {
520- rw_lock_s_unlock(btr_search_latch);
521- return;
522- }
523-
524- ut_ad(btr_search_latch == btr_search_get_latch(index->id));
525-
526 ut_a(!dict_index_is_ibuf(index));
527 #ifdef UNIV_DEBUG
528 switch (dict_index_get_online_status(index)) {
529@@ -1190,7 +1170,7 @@
530 }
531 #endif /* UNIV_DEBUG */
532
533- table = btr_search_get_hash_index(index->id);
534+ table = btr_search_get_hash_table(index);
535
536 #ifdef UNIV_SYNC_DEBUG
537 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
538@@ -1206,7 +1186,7 @@
539 releasing btr_search_latch, as the index page might only
540 be s-latched! */
541
542- rw_lock_s_unlock(btr_search_latch);
543+ rw_lock_s_unlock(btr_search_get_latch(index));
544
545 ut_a(n_fields + n_bytes > 0);
546
547@@ -1257,7 +1237,7 @@
548 mem_heap_free(heap);
549 }
550
551- rw_lock_x_lock(btr_search_get_latch(index->id));
552+ rw_lock_x_lock(btr_search_get_latch(index));
553
554 if (UNIV_UNLIKELY(!block->index)) {
555 /* Someone else has meanwhile dropped the hash index */
556@@ -1273,7 +1253,7 @@
557 /* Someone else has meanwhile built a new hash index on the
558 page, with different parameters */
559
560- rw_lock_x_unlock(btr_search_get_latch(index->id));
561+ rw_lock_x_unlock(btr_search_get_latch(index));
562
563 mem_free(folds);
564 goto retry;
565@@ -1289,7 +1269,6 @@
566 info->ref_count--;
567
568 block->index = NULL;
569- block->btr_search_latch = NULL;
570
571 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_REMOVED);
572 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_REMOVED, n_cached);
573@@ -1305,14 +1284,14 @@
574 "InnoDB: the hash index to a page of %s,"
575 " still %lu hash nodes remain.\n",
576 index->name, (ulong) block->n_pointers);
577- rw_lock_x_unlock(btr_search_get_latch(index->id));
578+ rw_lock_x_unlock(btr_search_get_latch(index));
579
580 ut_ad(btr_search_validate());
581 } else {
582- rw_lock_x_unlock(btr_search_get_latch(index->id));
583+ rw_lock_x_unlock(btr_search_get_latch(index));
584 }
585 #else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
586- rw_lock_x_unlock(btr_search_get_latch(index->id));
587+ rw_lock_x_unlock(btr_search_get_latch(index));
588 #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
589
590 mem_free(folds);
591@@ -1391,30 +1370,30 @@
592 ut_a(!dict_index_is_ibuf(index));
593
594 #ifdef UNIV_SYNC_DEBUG
595- ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
596+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
597 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
598 || rw_lock_own(&(block->lock), RW_LOCK_EX));
599 #endif /* UNIV_SYNC_DEBUG */
600
601- rw_lock_s_lock(btr_search_get_latch(index->id));
602+ rw_lock_s_lock(btr_search_get_latch(index));
603
604 if (!btr_search_enabled) {
605- rw_lock_s_unlock(btr_search_get_latch(index->id));
606+ rw_lock_s_unlock(btr_search_get_latch(index));
607 return;
608 }
609
610- table = btr_search_get_hash_index(index->id);
611+ table = btr_search_get_hash_table(index);
612 page = buf_block_get_frame(block);
613
614 if (block->index && ((block->curr_n_fields != n_fields)
615 || (block->curr_n_bytes != n_bytes)
616 || (block->curr_left_side != left_side))) {
617
618- rw_lock_s_unlock(btr_search_get_latch(index->id));
619+ rw_lock_s_unlock(btr_search_get_latch(index));
620
621 btr_search_drop_page_hash_index(block);
622 } else {
623- rw_lock_s_unlock(btr_search_get_latch(index->id));
624+ rw_lock_s_unlock(btr_search_get_latch(index));
625 }
626
627 n_recs = page_get_n_recs(page);
628@@ -1508,9 +1487,9 @@
629 fold = next_fold;
630 }
631
632- btr_search_check_free_space_in_heap(index->id);
633+ btr_search_check_free_space_in_heap(index);
634
635- rw_lock_x_lock(btr_search_get_latch(index->id));
636+ rw_lock_x_lock(btr_search_get_latch(index));
637
638 if (UNIV_UNLIKELY(!btr_search_enabled)) {
639 goto exit_func;
640@@ -1537,7 +1516,6 @@
641 block->curr_n_bytes = n_bytes;
642 block->curr_left_side = left_side;
643 block->index = index;
644- block->btr_search_latch = btr_search_get_latch(index->id);
645
646 for (i = 0; i < n_cached; i++) {
647
648@@ -1547,7 +1525,7 @@
649 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);
650 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
651 exit_func:
652- rw_lock_x_unlock(btr_search_get_latch(index->id));
653+ rw_lock_x_unlock(btr_search_get_latch(index));
654
655 mem_free(folds);
656 mem_free(recs);
657@@ -1582,7 +1560,7 @@
658 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
659 #endif /* UNIV_SYNC_DEBUG */
660
661- rw_lock_s_lock(btr_search_get_latch(index->id));
662+ rw_lock_s_lock(btr_search_get_latch(index));
663
664 ut_a(!new_block->index || new_block->index == index);
665 ut_a(!block->index || block->index == index);
666@@ -1591,7 +1569,7 @@
667
668 if (new_block->index) {
669
670- rw_lock_s_unlock(btr_search_get_latch(index->id));
671+ rw_lock_s_unlock(btr_search_get_latch(index));
672
673 btr_search_drop_page_hash_index(block);
674
675@@ -1608,7 +1586,7 @@
676 new_block->n_bytes = block->curr_n_bytes;
677 new_block->left_side = left_side;
678
679- rw_lock_s_unlock(btr_search_get_latch(index->id));
680+ rw_lock_s_unlock(btr_search_get_latch(index));
681
682 ut_a(n_fields + n_bytes > 0);
683
684@@ -1620,7 +1598,7 @@
685 return;
686 }
687
688- rw_lock_s_unlock(btr_search_get_latch(index->id));
689+ rw_lock_s_unlock(btr_search_get_latch(index));
690 }
691
692 /********************************************************************//**
693@@ -1659,7 +1637,7 @@
694 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
695 ut_a(!dict_index_is_ibuf(index));
696
697- table = btr_search_get_hash_index(cursor->index->id);
698+ table = btr_search_get_hash_table(cursor->index);
699
700 rec = btr_cur_get_rec(cursor);
701
702@@ -1670,7 +1648,7 @@
703 mem_heap_free(heap);
704 }
705
706- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
707+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
708
709 if (block->index) {
710 ut_a(block->index == index);
711@@ -1683,7 +1661,7 @@
712 }
713 }
714
715- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
716+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
717 }
718
719 /********************************************************************//**
720@@ -1720,7 +1698,7 @@
721 ut_a(cursor->index == index);
722 ut_a(!dict_index_is_ibuf(index));
723
724- rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
725+ rw_lock_x_lock(btr_search_get_latch(cursor->index));
726
727 if (!block->index) {
728
729@@ -1734,7 +1712,7 @@
730 && (cursor->n_bytes == block->curr_n_bytes)
731 && !block->curr_left_side) {
732
733- table = btr_search_get_hash_index(cursor->index->id);
734+ table = btr_search_get_hash_table(cursor->index);
735
736 if (ha_search_and_update_if_found(
737 table, cursor->fold, rec, block,
738@@ -1743,9 +1721,9 @@
739 }
740
741 func_exit:
742- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
743+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
744 } else {
745- rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
746+ rw_lock_x_unlock(btr_search_get_latch(cursor->index));
747
748 btr_search_update_hash_on_insert(cursor);
749 }
750@@ -1793,9 +1771,9 @@
751 return;
752 }
753
754- btr_search_check_free_space_in_heap(cursor->index->id);
755+ btr_search_check_free_space_in_heap(cursor->index);
756
757- table = btr_search_get_hash_index(cursor->index->id);
758+ table = btr_search_get_hash_table(cursor->index);
759
760 rec = btr_cur_get_rec(cursor);
761
762@@ -1827,7 +1805,7 @@
763 } else {
764 if (left_side) {
765
766- rw_lock_x_lock(btr_search_get_latch(index->id));
767+ rw_lock_x_lock(btr_search_get_latch(index));
768
769 locked = TRUE;
770
771@@ -1845,7 +1823,7 @@
772
773 if (!locked) {
774
775- rw_lock_x_lock(btr_search_get_latch(index->id));
776+ rw_lock_x_lock(btr_search_get_latch(index));
777
778 locked = TRUE;
779
780@@ -1867,8 +1845,7 @@
781 if (!left_side) {
782
783 if (!locked) {
784- rw_lock_x_lock(btr_search_get_latch(
785- index->id));
786+ rw_lock_x_lock(btr_search_get_latch(index));
787
788 locked = TRUE;
789
790@@ -1887,7 +1864,7 @@
791
792 if (!locked) {
793
794- rw_lock_x_lock(btr_search_get_latch(index->id));
795+ rw_lock_x_lock(btr_search_get_latch(index));
796
797 locked = TRUE;
798
799@@ -1914,7 +1891,7 @@
800 mem_heap_free(heap);
801 }
802 if (locked) {
803- rw_lock_x_unlock(btr_search_get_latch(index->id));
804+ rw_lock_x_unlock(btr_search_get_latch(index));
805 }
806 }
807
808@@ -1945,7 +1922,7 @@
809
810 buf_pool_mutex_enter_all();
811
812- cell_count = hash_get_n_cells(btr_search_sys->hash_index[t]);
813+ cell_count = hash_get_n_cells(btr_search_sys->hash_tables[t]);
814
815 for (i = 0; i < cell_count; i++) {
816 /* We release btr_search_latch every once in a while to
817@@ -1959,7 +1936,7 @@
818 }
819
820 node = (ha_node_t*)
821- hash_get_nth_cell(btr_search_sys->hash_index[t],
822+ hash_get_nth_cell(btr_search_sys->hash_tables[t],
823 i)->node;
824
825 for (; node != NULL; node = node->next) {
826@@ -2075,7 +2052,7 @@
827 buf_pool_mutex_enter_all();
828 }
829
830- if (!ha_validate(btr_search_sys->hash_index[t], i,
831+ if (!ha_validate(btr_search_sys->hash_tables[t], i,
832 end_index)) {
833 ok = FALSE;
834 }
835
836=== modified file 'Percona-Server/storage/innobase/buf/buf0buf.cc'
837--- Percona-Server/storage/innobase/buf/buf0buf.cc 2013-08-29 17:46:30 +0000
838+++ Percona-Server/storage/innobase/buf/buf0buf.cc 2013-09-02 14:08:46 +0000
839@@ -1013,7 +1013,6 @@
840
841 block->check_index_page_at_flush = FALSE;
842 block->index = NULL;
843- block->btr_search_latch = NULL;
844
845 #ifdef UNIV_DEBUG
846 block->page.in_page_hash = FALSE;
847@@ -2209,7 +2208,6 @@
848 {
849 block->check_index_page_at_flush = FALSE;
850 block->index = NULL;
851- block->btr_search_latch = NULL;
852
853 block->n_hash_helps = 0;
854 block->n_fields = 1;
855
856=== modified file 'Percona-Server/storage/innobase/dict/dict0boot.cc'
857--- Percona-Server/storage/innobase/dict/dict0boot.cc 2013-08-06 15:16:34 +0000
858+++ Percona-Server/storage/innobase/dict/dict0boot.cc 2013-09-02 14:08:46 +0000
859@@ -31,6 +31,7 @@
860
861 #include "dict0crea.h"
862 #include "btr0btr.h"
863+#include "btr0sea.h"
864 #include "dict0load.h"
865 #include "trx0trx.h"
866 #include "srv0srv.h"
867@@ -331,6 +332,7 @@
868 dict_mem_index_add_field(index, "NAME", 0);
869
870 index->id = DICT_TABLES_ID;
871+ btr_search_index_init(index);
872
873 error = dict_index_add_to_cache(table, index,
874 mtr_read_ulint(dict_hdr
875@@ -345,6 +347,7 @@
876 dict_mem_index_add_field(index, "ID", 0);
877
878 index->id = DICT_TABLE_IDS_ID;
879+ btr_search_index_init(index);
880 error = dict_index_add_to_cache(table, index,
881 mtr_read_ulint(dict_hdr
882 + DICT_HDR_TABLE_IDS,
883@@ -377,6 +380,7 @@
884 dict_mem_index_add_field(index, "POS", 0);
885
886 index->id = DICT_COLUMNS_ID;
887+ btr_search_index_init(index);
888 error = dict_index_add_to_cache(table, index,
889 mtr_read_ulint(dict_hdr
890 + DICT_HDR_COLUMNS,
891@@ -409,6 +413,7 @@
892 dict_mem_index_add_field(index, "ID", 0);
893
894 index->id = DICT_INDEXES_ID;
895+ btr_search_index_init(index);
896 error = dict_index_add_to_cache(table, index,
897 mtr_read_ulint(dict_hdr
898 + DICT_HDR_INDEXES,
899@@ -437,6 +442,7 @@
900 dict_mem_index_add_field(index, "POS", 0);
901
902 index->id = DICT_FIELDS_ID;
903+ btr_search_index_init(index);
904 error = dict_index_add_to_cache(table, index,
905 mtr_read_ulint(dict_hdr
906 + DICT_HDR_FIELDS,
907
908=== modified file 'Percona-Server/storage/innobase/dict/dict0dict.cc'
909--- Percona-Server/storage/innobase/dict/dict0dict.cc 2013-08-29 17:05:40 +0000
910+++ Percona-Server/storage/innobase/dict/dict0dict.cc 2013-09-02 14:08:46 +0000
911@@ -1208,8 +1208,7 @@
912
913 See also: dict_index_remove_from_cache_low() */
914
915- if (btr_search_info_get_ref_count(info, index->id)
916- > 0) {
917+ if (btr_search_info_get_ref_count(info, index) > 0) {
918 return(FALSE);
919 }
920 }
921@@ -2485,7 +2484,7 @@
922
923 do {
924 ulint ref_count = btr_search_info_get_ref_count(info,
925- index->id);
926+ index);
927
928 if (ref_count == 0) {
929 break;
930@@ -2777,6 +2776,7 @@
931 new_index->n_user_defined_cols = index->n_fields;
932
933 new_index->id = index->id;
934+ btr_search_index_init(new_index);
935
936 /* Copy the fields of index */
937 dict_index_copy(new_index, index, table, 0, index->n_fields);
938@@ -2948,6 +2948,7 @@
939 new_index->n_user_defined_cols = index->n_fields;
940
941 new_index->id = index->id;
942+ btr_search_index_init(new_index);
943
944 /* Copy fields from index to new_index */
945 dict_index_copy(new_index, index, table, 0, index->n_fields);
946@@ -3031,6 +3032,7 @@
947 new_index->n_user_defined_cols = index->n_fields;
948
949 new_index->id = index->id;
950+ btr_search_index_init(new_index);
951
952 /* Copy fields from index to new_index */
953 dict_index_copy(new_index, index, table, 0, index->n_fields);
954
955=== modified file 'Percona-Server/storage/innobase/dict/dict0load.cc'
956--- Percona-Server/storage/innobase/dict/dict0load.cc 2013-08-14 03:57:21 +0000
957+++ Percona-Server/storage/innobase/dict/dict0load.cc 2013-09-02 14:08:46 +0000
958@@ -1748,6 +1748,7 @@
959
960 (*index)->id = id;
961 (*index)->page = mach_read_from_4(field);
962+ btr_search_index_init(*index);
963 ut_ad((*index)->page);
964
965 return(NULL);
966
967=== modified file 'Percona-Server/storage/innobase/ha/ha0ha.cc'
968--- Percona-Server/storage/innobase/ha/ha0ha.cc 2013-08-29 17:05:40 +0000
969+++ Percona-Server/storage/innobase/ha/ha0ha.cc 2013-09-02 14:08:46 +0000
970@@ -113,13 +113,13 @@
971 ut_ad(table->adaptive);
972
973 for (i = 0; i < btr_search_index_num; i++) {
974- if (btr_search_sys->hash_index[i] == table) {
975+ if (btr_search_sys->hash_tables[i] == table) {
976 break;
977 }
978 }
979
980 ut_ad(i < btr_search_index_num);
981- ut_ad(rw_lock_own(btr_search_latch_arr[i], RW_LOCK_EX));
982+ ut_ad(rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_EX));
983
984 return(true);
985 }
986
987=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
988--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-29 17:46:30 +0000
989+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-09-02 14:08:46 +0000
990@@ -1473,20 +1473,21 @@
991 }
992
993 /********************************************************************//**
994-Call this function when mysqld passes control to the client. That is to
995-avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
996-documentation, see handler.cc.
997-@return 0 */
998+In XtraDB it is impossible for a transaction to own a search latch outside of
999+InnoDB code, so there is nothing to release on demand. We keep this function to
1000+simplify maintenance.
1001+@return 0 */
1002 static
1003 int
1004 innobase_release_temporary_latches(
1005 /*===============================*/
1006- handlerton* hton, /*!< in: handlerton */
1007- THD* thd) /*!< in: MySQL thread */
1008+ handlerton* hton __attribute__((unused)), /*!< in: handlerton */
1009+ THD* thd __attribute__((unused))) /*!< in: MySQL thread */
1010 {
1011+#ifdef UNIV_DEBUG
1012 DBUG_ASSERT(hton == innodb_hton_ptr);
1013
1014- if (!innodb_inited) {
1015+ if (!innodb_inited || thd == NULL) {
1016
1017 return(0);
1018 }
1019@@ -1494,8 +1495,12 @@
1020 trx_t* trx = thd_to_trx(thd);
1021
1022 if (trx != NULL) {
1023+#ifdef UNIV_SYNC_DEBUG
1024+ ut_ad(!btr_search_own_any());
1025+#endif
1026 trx_search_latch_release_if_reserved(trx);
1027 }
1028+#endif
1029
1030 return(0);
1031 }
1032@@ -3772,9 +3777,8 @@
1033 /* Since we will reserve the trx_sys->mutex, we have to release
1034 the search system latch first to obey the latching order. */
1035
1036- if (trx->has_search_latch) {
1037- trx_search_latch_release_if_reserved(trx);
1038- }
1039+ /* No-op in XtraDB */
1040+ trx_search_latch_release_if_reserved(trx);
1041
1042 if (trx->fake_changes &&
1043 (commit_trx ||
1044@@ -4972,12 +4976,8 @@
1045
1046 thd = ha_thd();
1047
1048- /* Under some cases MySQL seems to call this function while
1049- holding btr_search_latch. This breaks the latching order as
1050- we acquire dict_sys->mutex below and leads to a deadlock. */
1051- if (thd != NULL) {
1052- innobase_release_temporary_latches(ht, thd);
1053- }
1054+ /* No-op in XtraDB */
1055+ innobase_release_temporary_latches(ht, thd);
1056
1057 normalize_table_name(norm_name, name);
1058
1059@@ -5398,9 +5398,9 @@
1060 DBUG_ENTER("ha_innobase::close");
1061
1062 thd = ha_thd();
1063- if (thd != NULL) {
1064- innobase_release_temporary_latches(ht, thd);
1065- }
1066+
1067+ /* No-op in XtraDB */
1068+ innobase_release_temporary_latches(ht, thd);
1069
1070 row_prebuilt_free(prebuilt, FALSE);
1071
1072@@ -16398,6 +16398,8 @@
1073 "Disable with --skip-innodb-adaptive-hash-index.",
1074 NULL, innodb_adaptive_hash_index_update, TRUE);
1075
1076+/* btr_search_index_num is constrained to machine word size for historical
1077+reasons. This limitation can be easily removed later. */
1078 static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
1079 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1080 "Number of InnoDB adaptive hash index partitions (default 1: disable "
1081
1082=== modified file 'Percona-Server/storage/innobase/handler/xtradb_i_s.cc'
1083--- Percona-Server/storage/innobase/handler/xtradb_i_s.cc 2013-08-29 17:05:40 +0000
1084+++ Percona-Server/storage/innobase/handler/xtradb_i_s.cc 2013-09-02 14:08:46 +0000
1085@@ -309,9 +309,11 @@
1086
1087 static int xtradb_internal_hash_tables_fill_table(THD* thd, TABLE_LIST* tables, Item*)
1088 {
1089- const char* table_name;
1090- Field** fields;
1091- TABLE* table;
1092+ const char* table_name;
1093+ Field** fields;
1094+ TABLE* table;
1095+ ulong btr_search_sys_constant;
1096+ ulong btr_search_sys_variable;
1097
1098 DBUG_ENTER("xtradb_internal_hash_tables_fill_table");
1099
1100@@ -327,38 +329,38 @@
1101
1102 RETURN_IF_INNODB_NOT_STARTED(table_name);
1103
1104- if (btr_search_sys)
1105- {
1106- ulint btr_search_sys_subtotal;
1107- const hash_table_t* hash_index_0
1108- = btr_search_sys->hash_index[0];
1109-
1110- if (hash_index_0->heap) {
1111- btr_search_sys_subtotal
1112- = mem_heap_get_size(hash_index_0->heap);
1113- } else {
1114- for (ulint i = 0; i < hash_index_0->n_sync_obj; i++) {
1115- btr_search_sys_subtotal
1116- += mem_heap_get_size(hash_index_0
1117- ->heaps[i]);
1118- }
1119- }
1120- btr_search_sys_subtotal *= btr_search_index_num;
1121-
1122- OK(field_store_string(fields[INT_HASH_TABLES_NAME],
1123- "Adaptive hash index"));
1124- OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
1125- btr_search_sys_subtotal
1126- + (hash_index_0->n_cells
1127- * sizeof(hash_cell_t))));
1128- OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
1129- (hash_index_0->n_cells
1130- * sizeof(hash_cell_t))));
1131- OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
1132- btr_search_sys_subtotal));
1133- OK(schema_table_store_record(thd, table));
1134+ /* Calculate AHI constant and variable memory allocations */
1135+
1136+ btr_search_sys_constant = 0;
1137+ btr_search_sys_variable = 0;
1138+
1139+ ut_ad(btr_search_sys->hash_tables);
1140+
1141+ for (ulint i = 0; i < btr_search_index_num; i++) {
1142+ hash_table_t* ht = btr_search_sys->hash_tables[i];
1143+
1144+ ut_ad(ht);
1145+ ut_ad(ht->heap);
1146+
1147+ /* Multiple mutexes/heaps are currently never used for adaptive
1148+ hash index tables. */
1149+ ut_ad(!ht->n_sync_obj);
1150+ ut_ad(!ht->heaps);
1151+
1152+ btr_search_sys_variable += mem_heap_get_size(ht->heap);
1153+ btr_search_sys_constant += ht->n_cells * sizeof(hash_cell_t);
1154 }
1155
1156+ OK(field_store_string(fields[INT_HASH_TABLES_NAME],
1157+ "Adaptive hash index"));
1158+ OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
1159+ btr_search_sys_variable + btr_search_sys_constant));
1160+ OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
1161+ btr_search_sys_constant));
1162+ OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
1163+ btr_search_sys_variable));
1164+ OK(schema_table_store_record(thd, table));
1165+
1166 {
1167 OK(field_store_string(fields[INT_HASH_TABLES_NAME],
1168 "Page hash (buffer pool 0 only)"));
1169
1170=== modified file 'Percona-Server/storage/innobase/ibuf/ibuf0ibuf.cc'
1171--- Percona-Server/storage/innobase/ibuf/ibuf0ibuf.cc 2013-08-14 03:57:21 +0000
1172+++ Percona-Server/storage/innobase/ibuf/ibuf0ibuf.cc 2013-09-02 14:08:46 +0000
1173@@ -52,6 +52,7 @@
1174 #include "btr0cur.h"
1175 #include "btr0pcur.h"
1176 #include "btr0btr.h"
1177+#include "btr0sea.h"
1178 #include "row0upd.h"
1179 #include "sync0sync.h"
1180 #include "dict0boot.h"
1181@@ -626,6 +627,7 @@
1182 dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
1183
1184 index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
1185+ btr_search_index_init(index);
1186
1187 error = dict_index_add_to_cache(table, index,
1188 FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
1189
1190=== modified file 'Percona-Server/storage/innobase/include/btr0sea.h'
1191--- Percona-Server/storage/innobase/include/btr0sea.h 2013-08-29 17:05:40 +0000
1192+++ Percona-Server/storage/innobase/include/btr0sea.h 2013-09-02 14:08:46 +0000
1193@@ -87,7 +87,7 @@
1194 btr_search_info_get_ref_count(
1195 /*==========================*/
1196 btr_search_t* info, /*!< in: search info. */
1197- index_id_t key); /*!< in: id of the index owning search info */
1198+ dict_index_t* index); /*!< in: index */
1199 /*********************************************************************//**
1200 Updates the search info. */
1201 UNIV_INLINE
1202@@ -199,9 +199,9 @@
1203 @return the adaptive hash index table for a given index key */
1204 UNIV_INLINE
1205 hash_table_t*
1206-btr_search_get_hash_index(
1207+btr_search_get_hash_table(
1208 /*======================*/
1209- index_id_t key) /*!< in: index key */
1210+ const dict_index_t* index) /*!< in: index */
1211 __attribute__((pure,warn_unused_result));
1212
1213 /********************************************************************//**
1214@@ -211,8 +211,26 @@
1215 rw_lock_t*
1216 btr_search_get_latch(
1217 /*=================*/
1218- index_id_t key) /*!< in: index key */
1219- __attribute__((pure,warn_unused_result));
1220+ const dict_index_t* index) /*!< in: index */
1221+ __attribute__((pure,warn_unused_result));
1222+
1223+/*********************************************************************//**
1224+Returns the AHI partition number corresponding to a give index ID. */
1225+UNIV_INLINE
1226+ulint
1227+btr_search_get_key(
1228+/*===============*/
1229+ index_id_t index_id) /*!< in: index ID */
1230+ __attribute__((pure,warn_unused_result));
1231+
1232+/*********************************************************************//**
1233+Initializes AHI-related fields in a newly created index. */
1234+UNIV_INLINE
1235+void
1236+btr_search_index_init(
1237+/*===============*/
1238+ dict_index_t* index) /*!< in: index */
1239+ __attribute__((nonnull));
1240
1241 /********************************************************************//**
1242 Latches all adaptive hash index latches in exclusive mode. */
1243@@ -241,7 +259,15 @@
1244 /*===============*/
1245 ulint lock_type)
1246 __attribute__((warn_unused_result));
1247-#endif /* UNIV_SYNC_DEBUG */
1248+/********************************************************************//**
1249+Checks if the thread owns any adaptive hash latches in either S or X mode.
1250+@return true if the thread owns at least one latch in any mode. */
1251+UNIV_INLINE
1252+bool
1253+btr_search_own_any(void)
1254+/*=====================*/
1255+ __attribute__((warn_unused_result));
1256+#endif
1257
1258 /** The search info struct in an index */
1259 struct btr_search_t{
1260@@ -300,9 +326,9 @@
1261
1262 /** The hash index system */
1263 struct btr_search_sys_t{
1264- hash_table_t** hash_index; /*!< the adaptive hash index,
1265- mapping dtuple_fold values
1266- to rec_t pointers on index pages */
1267+ hash_table_t** hash_tables; /*!< the array of adaptive hash index
1268+ tables, mapping dtuple_fold values to
1269+ rec_t pointers on index pages */
1270 };
1271
1272 /** The adaptive hash index */
1273
1274=== modified file 'Percona-Server/storage/innobase/include/btr0sea.ic'
1275--- Percona-Server/storage/innobase/include/btr0sea.ic 2013-08-29 17:05:40 +0000
1276+++ Percona-Server/storage/innobase/include/btr0sea.ic 2013-09-02 14:08:46 +0000
1277@@ -60,8 +60,8 @@
1278 btr_search_t* info;
1279
1280 #ifdef UNIV_SYNC_DEBUG
1281- ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
1282- ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1283+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
1284+ ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
1285 #endif /* UNIV_SYNC_DEBUG */
1286
1287 info = btr_search_get_info(index);
1288@@ -86,11 +86,14 @@
1289 @return the adaptive hash index table for a given index key */
1290 UNIV_INLINE
1291 hash_table_t*
1292-btr_search_get_hash_index(
1293+btr_search_get_hash_table(
1294 /*======================*/
1295- index_id_t key) /*!< in: index key */
1296+ const dict_index_t* index) /*!< in: index */
1297 {
1298- return(btr_search_sys->hash_index[key % btr_search_index_num]);
1299+ ut_ad(index);
1300+ ut_ad(index->search_table);
1301+
1302+ return(index->search_table);
1303 }
1304
1305 /********************************************************************//**
1306@@ -100,9 +103,41 @@
1307 rw_lock_t*
1308 btr_search_get_latch(
1309 /*=================*/
1310- index_id_t key) /*!< in: index key */
1311-{
1312- return(btr_search_latch_arr[key % btr_search_index_num]);
1313+ const dict_index_t* index) /*!< in: index */
1314+{
1315+ ut_ad(index);
1316+ ut_ad(index->search_latch >= btr_search_latch_arr &&
1317+ index->search_latch < btr_search_latch_arr +
1318+ btr_search_index_num);
1319+
1320+ return(index->search_latch);
1321+}
1322+
1323+/*********************************************************************//**
1324+Returns the AHI partition number corresponding to a give index ID. */
1325+UNIV_INLINE
1326+ulint
1327+btr_search_get_key(
1328+/*===============*/
1329+ index_id_t index_id) /*!< in: index ID */
1330+{
1331+ return(index_id % btr_search_index_num);
1332+}
1333+
1334+/*********************************************************************//**
1335+Initializes AHI-related fields in a newly created index. */
1336+UNIV_INLINE
1337+void
1338+btr_search_index_init(
1339+/*===============*/
1340+ dict_index_t* index) /*!< in: index */
1341+{
1342+ ut_ad(index);
1343+
1344+ index->search_latch =
1345+ &btr_search_latch_arr[btr_search_get_key(index->id)];
1346+ index->search_table =
1347+ btr_search_sys->hash_tables[btr_search_get_key(index->id)];
1348 }
1349
1350 /********************************************************************//**
1351@@ -115,7 +150,7 @@
1352 ulint i;
1353
1354 for (i = 0; i < btr_search_index_num; i++) {
1355- rw_lock_x_lock(btr_search_latch_arr[i]);
1356+ rw_lock_x_lock(&btr_search_latch_arr[i]);
1357 }
1358 }
1359
1360@@ -129,7 +164,7 @@
1361 ulint i;
1362
1363 for (i = 0; i < btr_search_index_num; i++) {
1364- rw_lock_x_unlock(btr_search_latch_arr[i]);
1365+ rw_lock_x_unlock(&btr_search_latch_arr[i]);
1366 }
1367 }
1368
1369@@ -149,11 +184,31 @@
1370 ulint i;
1371
1372 for (i = 0; i < btr_search_index_num; i++) {
1373- if (!rw_lock_own(btr_search_latch_arr[i], lock_type)) {
1374+ if (!rw_lock_own(&btr_search_latch_arr[i], lock_type)) {
1375 return(false);
1376 }
1377 }
1378
1379 return(true);
1380 }
1381+
1382+/********************************************************************//**
1383+Checks if the thread owns any adaptive hash latches in either S or X mode.
1384+@return true if the thread owns at least one latch in any mode. */
1385+UNIV_INLINE
1386+bool
1387+btr_search_own_any(void)
1388+/*====================*/
1389+{
1390+ ulint i;
1391+
1392+ for (i = 0; i < btr_search_index_num; i++) {
1393+ if (rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_SHARED) ||
1394+ rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_EX)) {
1395+ return(true);
1396+ }
1397+ }
1398+
1399+ return(false);
1400+}
1401 #endif /* UNIV_SYNC_DEBUG */
1402
1403=== modified file 'Percona-Server/storage/innobase/include/btr0types.h'
1404--- Percona-Server/storage/innobase/include/btr0types.h 2013-08-29 17:05:40 +0000
1405+++ Percona-Server/storage/innobase/include/btr0types.h 2013-09-02 14:08:46 +0000
1406@@ -41,20 +41,21 @@
1407
1408 #ifndef UNIV_HOTBACKUP
1409
1410-/** @brief The latch protecting the adaptive search system
1411+/** @brief The array of latches protecting the adaptive search partitions
1412
1413-This latch protects the
1414-(1) hash index;
1415+These latch protect the
1416+(1) hash index from the corresponding AHI partition;
1417 (2) columns of a record to which we have a pointer in the hash index;
1418
1419-but does NOT protect:
1420+but do NOT protect:
1421
1422 (3) next record offset field in a record;
1423 (4) next or previous records on the same page.
1424
1425-Bear in mind (3) and (4) when using the hash index.
1426+Bear in mind (3) and (4) when using the hash indexes.
1427 */
1428-extern rw_lock_t** btr_search_latch_arr;
1429+
1430+extern rw_lock_t* btr_search_latch_arr;
1431
1432 #endif /* UNIV_HOTBACKUP */
1433
1434
1435=== modified file 'Percona-Server/storage/innobase/include/buf0buf.h'
1436--- Percona-Server/storage/innobase/include/buf0buf.h 2013-08-29 17:46:30 +0000
1437+++ Percona-Server/storage/innobase/include/buf0buf.h 2013-09-02 14:08:46 +0000
1438@@ -1700,8 +1700,6 @@
1439 complete, though: there may
1440 have been hash collisions,
1441 record deletions, etc. */
1442- rw_lock_t* btr_search_latch;/*!< Adaptive hash index latch for the
1443- index this block belongs to or NULL */
1444 /* @} */
1445 # ifdef UNIV_SYNC_DEBUG
1446 /** @name Debug fields */
1447
1448=== modified file 'Percona-Server/storage/innobase/include/dict0mem.h'
1449--- Percona-Server/storage/innobase/include/dict0mem.h 2013-08-14 03:57:21 +0000
1450+++ Percona-Server/storage/innobase/include/dict0mem.h 2013-09-02 14:08:46 +0000
1451@@ -544,6 +544,10 @@
1452 initialized to 0, NULL or FALSE in dict_mem_index_create(). */
1453 struct dict_index_t{
1454 index_id_t id; /*!< id of the index */
1455+ rw_lock_t* search_latch; /*!< latch protecting the AHI partition
1456+ corresponding to this index */
1457+ hash_table_t* search_table; /*!< hash table protected by
1458+ search_latch */
1459 mem_heap_t* heap; /*!< memory heap */
1460 const char* name; /*!< index name */
1461 const char* table_name;/*!< table name */
1462
1463=== modified file 'Percona-Server/storage/innobase/include/trx0trx.h'
1464--- Percona-Server/storage/innobase/include/trx0trx.h 2013-08-29 17:05:40 +0000
1465+++ Percona-Server/storage/innobase/include/trx0trx.h 2013-09-02 14:08:46 +0000
1466@@ -44,12 +44,14 @@
1467 extern sess_t* trx_dummy_sess;
1468
1469 /********************************************************************//**
1470-Releases the search latch if trx has reserved it. */
1471+In XtraDB it is impossible for a transaction to own a search latch outside of
1472+InnoDB code, so there is nothing to release on demand. We keep this function to
1473+simplify maintenance.*/
1474 UNIV_INLINE
1475 void
1476 trx_search_latch_release_if_reserved(
1477 /*=================================*/
1478- trx_t* trx); /*!< in: transaction */
1479+ trx_t* trx __attribute__((unused))); /*!< in: transaction */
1480 /******************************************************************//**
1481 Set detailed error message for the transaction. */
1482 UNIV_INTERN
1483@@ -815,8 +817,8 @@
1484 flush the log in
1485 trx_commit_complete_for_mysql() */
1486 ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
1487- ulint has_search_latch;
1488- /*!< TRUE if this trx has latched the
1489+ bool has_search_latch;
1490+ /*!< true if this trx has latched any
1491 search system latch in S-mode */
1492 ulint search_latch_timeout;
1493 /*!< If we notice that someone is
1494@@ -1136,7 +1138,7 @@
1495
1496 Bear in mind (3) and (4) when using the hash index.
1497 */
1498-extern rw_lock_t** btr_search_latch_arr;
1499+extern rw_lock_t* btr_search_latch_arr;
1500
1501 #ifndef UNIV_NONINL
1502 #include "trx0trx.ic"
1503
1504=== modified file 'Percona-Server/storage/innobase/include/trx0trx.ic'
1505--- Percona-Server/storage/innobase/include/trx0trx.ic 2013-08-29 17:05:40 +0000
1506+++ Percona-Server/storage/innobase/include/trx0trx.ic 2013-09-02 14:08:46 +0000
1507@@ -164,21 +164,14 @@
1508 }
1509
1510 /********************************************************************//**
1511-Releases the search latches if trx has reserved them. */
1512+In XtraDB it is impossible for a transaction to own a search latch outside of
1513+InnoDB code, so there is nothing to release on demand. We keep this function to
1514+simplify maintenance.*/
1515 UNIV_INLINE
1516 void
1517 trx_search_latch_release_if_reserved(
1518 /*=================================*/
1519- trx_t* trx) /*!< in: transaction */
1520+ trx_t* trx __attribute__((unused))) /*!< in: transaction */
1521 {
1522- ulint i;
1523-
1524- for (i = 0; i < btr_search_index_num; i++) {
1525- if (trx->has_search_latch & (1UL << i)) {
1526- rw_lock_s_unlock(btr_search_latch_arr[i]);
1527- }
1528- }
1529-
1530- trx->has_search_latch = 0;
1531+ ut_ad(!trx->has_search_latch);
1532 }
1533-
1534
1535=== modified file 'Percona-Server/storage/innobase/row/row0ftsort.cc'
1536--- Percona-Server/storage/innobase/row/row0ftsort.cc 2013-02-12 07:47:19 +0000
1537+++ Percona-Server/storage/innobase/row/row0ftsort.cc 2013-09-02 14:08:46 +0000
1538@@ -30,6 +30,7 @@
1539 #include "row0merge.h"
1540 #include "row0row.h"
1541 #include "btr0cur.h"
1542+#include "btr0sea.h"
1543
1544 /** Read the next record to buffer N.
1545 @param N index into array of merge info structure */
1546@@ -87,6 +88,8 @@
1547 new_index->n_def = FTS_NUM_FIELDS_SORT;
1548 new_index->cached = TRUE;
1549
1550+ btr_search_index_init(new_index);
1551+
1552 idx_field = dict_index_get_nth_field(index, 0);
1553 charset = fts_index_get_charset(index);
1554
1555
1556=== modified file 'Percona-Server/storage/innobase/row/row0sel.cc'
1557--- Percona-Server/storage/innobase/row/row0sel.cc 2013-08-29 17:05:40 +0000
1558+++ Percona-Server/storage/innobase/row/row0sel.cc 2013-09-02 14:08:46 +0000
1559@@ -1233,7 +1233,7 @@
1560 ut_ad(!plan->must_get_clust);
1561 #ifdef UNIV_SYNC_DEBUG
1562 if (search_latch_locked) {
1563- ut_ad(rw_lock_own(btr_search_get_latch(index->id),
1564+ ut_ad(rw_lock_own(btr_search_get_latch(index),
1565 RW_LOCK_SHARED));
1566 }
1567 #endif /* UNIV_SYNC_DEBUG */
1568@@ -1406,10 +1406,10 @@
1569 && !plan->must_get_clust
1570 && !plan->table->big_rows) {
1571 if (!search_latch_locked) {
1572- rw_lock_s_lock(btr_search_get_latch(index->id));
1573+ rw_lock_s_lock(btr_search_get_latch(index));
1574
1575 search_latch_locked = TRUE;
1576- } else if (rw_lock_get_writer(btr_search_get_latch(index->id))
1577+ } else if (rw_lock_get_writer(btr_search_get_latch(index))
1578 == RW_LOCK_WAIT_EX) {
1579
1580 /* There is an x-latch request waiting: release the
1581@@ -1419,8 +1419,8 @@
1582 from acquiring an s-latch for a long time, lowering
1583 performance significantly in multiprocessors. */
1584
1585- rw_lock_s_unlock(btr_search_get_latch(index->id));
1586- rw_lock_s_lock(btr_search_get_latch(index->id));
1587+ rw_lock_s_unlock(btr_search_get_latch(index));
1588+ rw_lock_s_lock(btr_search_get_latch(index));
1589 }
1590
1591 found_flag = row_sel_try_search_shortcut(node, plan,
1592@@ -1445,7 +1445,7 @@
1593 }
1594
1595 if (search_latch_locked) {
1596- rw_lock_s_unlock(btr_search_get_latch(index->id));
1597+ rw_lock_s_unlock(btr_search_get_latch(index));
1598
1599 search_latch_locked = FALSE;
1600 }
1601@@ -2021,7 +2021,7 @@
1602
1603 func_exit:
1604 if (search_latch_locked) {
1605- rw_lock_s_unlock(btr_search_get_latch(index->id));
1606+ rw_lock_s_unlock(btr_search_get_latch(index));
1607 }
1608 if (UNIV_LIKELY_NULL(heap)) {
1609 mem_heap_free(heap);
1610@@ -2796,6 +2796,9 @@
1611 /* Copy an externally stored field to a temporary heap */
1612
1613 ut_a(!prebuilt->trx->has_search_latch);
1614+#ifdef UNIV_SYNC_DEBUG
1615+ ut_ad(!btr_search_own_any());
1616+#endif
1617 ut_ad(field_no == templ->clust_rec_field_no);
1618
1619 if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
1620@@ -3468,11 +3471,11 @@
1621 ut_ad(!prebuilt->templ_contains_blob);
1622
1623 #ifndef UNIV_SEARCH_DEBUG
1624+ ut_ad(trx->has_search_latch);
1625+
1626 btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
1627 BTR_SEARCH_LEAF, pcur,
1628- (trx->has_search_latch)
1629- ? RW_S_LATCH
1630- : 0,
1631+ RW_S_LATCH,
1632 mtr);
1633 #else /* UNIV_SEARCH_DEBUG */
1634 btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
1635@@ -3599,47 +3602,6 @@
1636 }
1637
1638 /********************************************************************//**
1639-Acquires an S latch for the adaptive hash index for a given index tree if is
1640-not acquired already. If the current transaction already owns a latch with
1641-a higher index in the latch array, release all the already-held S latches
1642-and reacquire them together with the desired latch to honor the latching
1643-order. */
1644-static
1645-void
1646-trx_search_latch_lock(
1647-/*==================*/
1648- trx_t* trx, /*!< in: latching transcation */
1649- ulint index_id) /*!< in: index to latch AHI for */
1650-{
1651- ulint latch_mask = 1UL << (index_id % btr_search_index_num);
1652-
1653- if (!(trx->has_search_latch & latch_mask)) {
1654-
1655- if (trx->has_search_latch < latch_mask) {
1656-
1657- rw_lock_s_lock(btr_search_get_latch(index_id));
1658- trx->has_search_latch |= latch_mask;
1659- } else {
1660-
1661- ulint taken_latches = trx->has_search_latch;
1662-
1663- trx_search_latch_release_if_reserved(trx);
1664-
1665- trx->has_search_latch = taken_latches | latch_mask;
1666-
1667- for (ulint i = 0; i < btr_search_index_num; i++) {
1668- if (trx->has_search_latch & (1UL << i)) {
1669-
1670- rw_lock_s_lock(
1671- btr_search_latch_arr[i]);
1672- }
1673- }
1674- }
1675- }
1676-}
1677-
1678-
1679-/********************************************************************//**
1680 Searches for rows in the database. This is used in the interface to
1681 MySQL. This function opens a cursor, and also implements fetch next
1682 and fetch prev. NOTE that if we do a search with a full key value
1683@@ -3701,7 +3663,6 @@
1684 ulint* offsets = offsets_;
1685 ibool table_lock_waited = FALSE;
1686 byte* next_buf = 0;
1687- bool should_release;
1688
1689 rec_offs_init(offsets_);
1690
1691@@ -3715,7 +3676,9 @@
1692 return(DB_END_OF_INDEX);
1693 }
1694
1695+ ut_ad(!trx->has_search_latch);
1696 #ifdef UNIV_SYNC_DEBUG
1697+ ut_ad(!btr_search_own_any());
1698 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1699 #endif /* UNIV_SYNC_DEBUG */
1700
1701@@ -3776,33 +3739,6 @@
1702 fprintf(stderr, "N tables locked %lu\n",
1703 (ulong) trx->mysql_n_tables_locked);
1704 #endif
1705- /*-------------------------------------------------------------*/
1706- /* PHASE 0: Release possible latches we are holding on the
1707- adaptive hash index latches if there is someone waiting behind */
1708-
1709- should_release = false;
1710- for (ulint i = 0; i < btr_search_index_num; i++) {
1711- /* we should check all latches (fix Bug#791030) */
1712- if (UNIV_UNLIKELY(rw_lock_get_writer(btr_search_latch_arr[i])
1713- != RW_LOCK_NOT_LOCKED)) {
1714- should_release = true;
1715- break;
1716- }
1717- }
1718-
1719- if (UNIV_UNLIKELY(should_release)) {
1720-
1721- /* There is an x-latch request on the adaptive hash index:
1722- release the s-latch to reduce starvation and wait for
1723- BTR_SEA_TIMEOUT rounds before trying to keep it again over
1724- calls from MySQL */
1725-
1726- /* We should release all s-latches (fix Bug#791030) */
1727- trx_search_latch_release_if_reserved(trx);
1728-
1729- trx->search_latch_timeout = BTR_SEA_TIMEOUT;
1730- }
1731-
1732 /* Reset the new record lock info if srv_locks_unsafe_for_binlog
1733 is set or session is using a READ COMMITED isolation level. Then
1734 we are able to remove the record locks set here on an individual
1735@@ -3949,7 +3885,9 @@
1736 hash index semaphore! */
1737
1738 #ifndef UNIV_SEARCH_DEBUG
1739- trx_search_latch_lock(trx, index->id);
1740+ ut_ad(!trx->has_search_latch);
1741+ rw_lock_s_lock(btr_search_get_latch(index));
1742+ trx->has_search_latch = TRUE;
1743 #endif
1744 switch (row_sel_try_search_shortcut_for_mysql(
1745 &rec, prebuilt, &offsets, &heap,
1746@@ -4003,7 +3941,7 @@
1747 fputs(" shortcut\n", stderr); */
1748
1749 err = DB_SUCCESS;
1750- goto release_search_latch_if_needed;
1751+ goto release_search_latch;
1752
1753 case SEL_EXHAUSTED:
1754 shortcut_mismatch:
1755@@ -4013,15 +3951,10 @@
1756 fputs(" record not found 2\n", stderr); */
1757
1758 err = DB_RECORD_NOT_FOUND;
1759-release_search_latch_if_needed:
1760- if (trx->search_latch_timeout > 0
1761- && trx->has_search_latch) {
1762-
1763- trx->search_latch_timeout--;
1764-
1765- trx_search_latch_release_if_reserved(
1766- trx);
1767- }
1768+release_search_latch:
1769+ rw_lock_s_unlock(
1770+ btr_search_get_latch(index));
1771+ trx->has_search_latch = FALSE;
1772
1773 /* NOTE that we do NOT store the cursor
1774 position */
1775@@ -4036,13 +3969,19 @@
1776
1777 mtr_commit(&mtr);
1778 mtr_start(&mtr);
1779+
1780+ rw_lock_s_unlock(btr_search_get_latch(index));
1781+ trx->has_search_latch = FALSE;
1782 }
1783 }
1784
1785 /*-------------------------------------------------------------*/
1786 /* PHASE 3: Open or restore index cursor position */
1787
1788- trx_search_latch_release_if_reserved(trx);
1789+ ut_ad(!trx->has_search_latch);
1790+#ifdef UNIV_SYNC_DEBUG
1791+ ut_ad(!btr_search_own_any());
1792+#endif
1793
1794 /* The state of a running trx can only be changed by the
1795 thread that is currently serving the transaction. Because we
1796@@ -5184,7 +5123,9 @@
1797 }
1798 }
1799
1800+ ut_ad(!trx->has_search_latch);
1801 #ifdef UNIV_SYNC_DEBUG
1802+ ut_ad(!btr_search_own_any());
1803 ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
1804 #endif /* UNIV_SYNC_DEBUG */
1805
1806
1807=== modified file 'Percona-Server/storage/innobase/srv/srv0srv.cc'
1808--- Percona-Server/storage/innobase/srv/srv0srv.cc 2013-08-29 17:05:40 +0000
1809+++ Percona-Server/storage/innobase/srv/srv0srv.cc 2013-09-02 14:08:46 +0000
1810@@ -1182,7 +1182,8 @@
1811 ulint n_reserved;
1812 ibool ret;
1813
1814- ulint btr_search_sys_subtotal;
1815+ ulong btr_search_sys_constant;
1816+ ulong btr_search_sys_variable;
1817 ulint lock_sys_subtotal;
1818 ulint recv_sys_subtotal;
1819
1820@@ -1307,21 +1308,27 @@
1821 "Total memory allocated by read views " ULINTPF "\n",
1822 os_atomic_increment_lint(&srv_read_views_memory, 0));
1823
1824- /* Calculate reserved memories */
1825- if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1826- btr_search_sys_subtotal
1827- = mem_heap_get_size(btr_search_sys->hash_index[0]
1828- ->heap);
1829- } else {
1830- btr_search_sys_subtotal = 0;
1831- for (i=0; i < btr_search_sys->hash_index[0]->n_sync_obj; i++) {
1832- btr_search_sys_subtotal
1833- += mem_heap_get_size(
1834- btr_search_sys->hash_index[0]
1835- ->heaps[i]);
1836- }
1837+ /* Calculate AHI constant and variable memory allocations */
1838+
1839+ btr_search_sys_constant = 0;
1840+ btr_search_sys_variable = 0;
1841+
1842+ ut_ad(btr_search_sys->hash_tables);
1843+
1844+ for (i = 0; i < btr_search_index_num; i++) {
1845+ hash_table_t* ht = btr_search_sys->hash_tables[i];
1846+
1847+ ut_ad(ht);
1848+ ut_ad(ht->heap);
1849+
1850+ /* Multiple mutexes/heaps are currently never used for adaptive
1851+ hash index tables. */
1852+ ut_ad(!ht->n_sync_obj);
1853+ ut_ad(!ht->heaps);
1854+
1855+ btr_search_sys_variable += mem_heap_get_size(ht->heap);
1856+ btr_search_sys_constant += ht->n_cells * sizeof(hash_cell_t);
1857 }
1858- btr_search_sys_subtotal *= btr_search_index_num;
1859
1860 lock_sys_subtotal = 0;
1861 if (trx_sys) {
1862@@ -1349,18 +1356,9 @@
1863 " Lock system %lu \t(%lu + " ULINTPF ")\n"
1864 " Recovery system %lu \t(%lu + " ULINTPF ")\n",
1865
1866- (ulong) (btr_search_sys
1867- ? (btr_search_sys->hash_index[0]->n_cells
1868- * sizeof(hash_cell_t)
1869- * btr_search_index_num)
1870- : 0)
1871- + btr_search_sys_subtotal,
1872- (ulong) (btr_search_sys
1873- ? (btr_search_sys->hash_index[0]->n_cells
1874- * sizeof(hash_cell_t)
1875- * btr_search_index_num)
1876- : 0),
1877- btr_search_sys_subtotal,
1878+ btr_search_sys_constant + btr_search_sys_variable,
1879+ btr_search_sys_constant,
1880+ btr_search_sys_variable,
1881
1882 (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
1883
1884@@ -1509,23 +1507,23 @@
1885 buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
1886 buf_get_total_list_size_in_bytes(&buf_pools_list_size);
1887
1888- if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1889- mem_adaptive_hash
1890- = mem_heap_get_size(btr_search_sys
1891- ->hash_index[0]->heap);
1892- } else {
1893- mem_adaptive_hash = 0;
1894- for (i=0; i < btr_search_sys->hash_index[0]->n_sync_obj; i++) {
1895- mem_adaptive_hash
1896- += mem_heap_get_size
1897- (btr_search_sys->hash_index[0]->heaps[i]);
1898- }
1899- }
1900- if (btr_search_sys) {
1901- mem_adaptive_hash += (btr_search_sys->hash_index[0]->n_cells
1902- * sizeof(hash_cell_t));
1903- }
1904- mem_adaptive_hash *= btr_search_index_num;
1905+ mem_adaptive_hash = 0;
1906+
1907+ ut_ad(btr_search_sys->hash_tables);
1908+
1909+ for (i = 0; i < btr_search_index_num; i++) {
1910+ hash_table_t* ht = btr_search_sys->hash_tables[i];
1911+
1912+ ut_ad(ht);
1913+ ut_ad(ht->heap);
1914+ /* Multiple mutexes/heaps are currently never used for adaptive
1915+ hash index tables. */
1916+ ut_ad(!ht->n_sync_obj);
1917+ ut_ad(!ht->heaps);
1918+
1919+ mem_adaptive_hash += mem_heap_get_size(ht->heap);
1920+ mem_adaptive_hash += ht->n_cells * sizeof(hash_cell_t);
1921+ }
1922
1923 mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
1924 + dict_sys->table_id_hash->n_cells
1925
1926=== modified file 'Percona-Server/storage/innobase/sync/sync0sync.cc'
1927--- Percona-Server/storage/innobase/sync/sync0sync.cc 2013-08-29 17:05:40 +0000
1928+++ Percona-Server/storage/innobase/sync/sync0sync.cc 2013-09-02 14:08:46 +0000
1929@@ -1187,12 +1187,12 @@
1930 array */
1931 bool found_current = false;
1932 for (ulint i = 0; i < btr_search_index_num; i++) {
1933- if (btr_search_latch_arr[i] == latch) {
1934+ if (&btr_search_latch_arr[i] == latch) {
1935 found_current = true;
1936 } else if (found_current) {
1937- ut_ad(!rw_lock_own(btr_search_latch_arr[i],
1938+ ut_ad(!rw_lock_own(&btr_search_latch_arr[i],
1939 RW_LOCK_SHARED));
1940- ut_ad(!rw_lock_own(btr_search_latch_arr[i],
1941+ ut_ad(!rw_lock_own(&btr_search_latch_arr[i],
1942 RW_LOCK_EX));
1943 }
1944 }
1945
1946=== modified file 'Percona-Server/storage/innobase/trx/trx0trx.cc'
1947--- Percona-Server/storage/innobase/trx/trx0trx.cc 2013-08-29 17:05:40 +0000
1948+++ Percona-Server/storage/innobase/trx/trx0trx.cc 2013-09-02 14:08:46 +0000
1949@@ -360,6 +360,9 @@
1950 ut_a(trx->lock.wait_thr == NULL);
1951
1952 ut_a(!trx->has_search_latch);
1953+#ifdef UNIV_SYNC_DEBUG
1954+ ut_ad(!btr_search_own_any());
1955+#endif
1956
1957 ut_a(trx->dict_operation_lock_mode == 0);
1958

Subscribers

People subscribed via source and target branches