Merge lp:~laurynas-biveinis/percona-server/ahi-partitions-5.6-5.6 into lp:percona-server/5.6

Proposed by Laurynas Biveinis
Status: Superseded
Proposed branch: lp:~laurynas-biveinis/percona-server/ahi-partitions-5.6-5.6
Merge into: lp:percona-server/5.6
Diff against target: 1918 lines (+699/-212)
30 files modified
Percona-Server/mysql-test/suite/innodb/r/percona_ahi_partitions.result (+33/-0)
Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions-master.opt (+1/-0)
Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions.test (+67/-0)
Percona-Server/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_partitions_basic.result (+9/-0)
Percona-Server/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_partitions_basic.test (+14/-0)
Percona-Server/storage/innobase/btr/btr0cur.cc (+6/-5)
Percona-Server/storage/innobase/btr/btr0sea.cc (+212/-117)
Percona-Server/storage/innobase/buf/buf0buf.cc (+3/-1)
Percona-Server/storage/innobase/dict/dict0dict.cc (+4/-2)
Percona-Server/storage/innobase/ha/ha0ha.cc (+30/-4)
Percona-Server/storage/innobase/handler/ha_innodb.cc (+7/-0)
Percona-Server/storage/innobase/handler/xtradb_i_s.cc (+28/-28)
Percona-Server/storage/innobase/include/btr0sea.h (+59/-2)
Percona-Server/storage/innobase/include/btr0sea.ic (+93/-2)
Percona-Server/storage/innobase/include/btr0types.h (+4/-4)
Percona-Server/storage/innobase/include/buf0buf.h (+2/-0)
Percona-Server/storage/innobase/include/mtr0log.ic (+1/-0)
Percona-Server/storage/innobase/include/que0que.h (+1/-0)
Percona-Server/storage/innobase/include/read0read.h (+1/-0)
Percona-Server/storage/innobase/include/trx0roll.h (+1/-0)
Percona-Server/storage/innobase/include/trx0trx.h (+1/-4)
Percona-Server/storage/innobase/include/trx0trx.ic (+8/-4)
Percona-Server/storage/innobase/include/univ.i (+0/-1)
Percona-Server/storage/innobase/os/os0file.cc (+1/-0)
Percona-Server/storage/innobase/row/row0sel.cc (+71/-24)
Percona-Server/storage/innobase/srv/srv0conc.cc (+1/-0)
Percona-Server/storage/innobase/srv/srv0srv.cc (+20/-13)
Percona-Server/storage/innobase/sync/sync0sync.cc (+19/-1)
Percona-Server/storage/innobase/trx/trx0trx.cc (+1/-0)
Percona-Server/storage/innobase/ut/ut0ut.cc (+1/-0)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/ahi-partitions-5.6-5.6
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Needs Fixing
Review via email: mp+182579@code.launchpad.net

This proposal supersedes a proposal from 2013-08-26.

This proposal has been superseded by a proposal from 2013-08-29.

Description of the change

2nd MP:

Review comments addressed.
http://jenkins.percona.com/job/percona-server-5.6-param/238/
Testsuite changes only, no new MTR 8 partitions Jenkins run.

1st MP:

Port AHI partitions from 5.5 to 5.6, implementing https://blueprints.launchpad.net/percona-server/+spec/ahi-part-5-6.

Default Jenkins run at
http://jenkins.percona.com/job/percona-server-5.6-param/233/
and additional MTR --mysqld=--mysqld=--innodb-adaptive-hash-index-partitions=8 run at
http://jenkins.percona.com/job/percona-server-5.6-param/234/.

Port adaptive hash index partitions from 5.5.

There are no major algorithmic differences from the 5.5 version. The
are minor differences from the 5.5 version:
- simplify latching changes in row_search_for_mysql() by spliting out
  a helper function trx_search_latch_lock(), by using
  trx_search_latch_release_if_reserved() where appropriate, by not
  bothering to compute an X waiters bit mask in phase 0 but checking
  whether any X waiter is present instead;
- add additional latching order enforcement code to
  sync_thread_add_level();
- some comments in surrounding code were updated to reflect the
  partitioning;
- added missing header and arg comments. Add function attributes to
  btr_search_get_hash_index(), btr_search_get_latch(). New helper
  function btr_search_own_all().
- merged btr_search_drop_page_hash_index() with 5.6 version and
  adjusted UNIV_LIKELY/UNIV_UNLIKELY annotations to better reflect my
  expected reality;
- instead of adding an outer loop to it as in 5.5, rename
  btr_search_validate() to btr_search_validate_one_table() and add a
  new function btr_search_validate() that calls the former in a loop;
- instead of disabling UNIV_SYNC_DEBUG checks in ha_clear(),
  ha_delete_hash_node(), and ha_search_and_update_if_found_func(),
  implement a helper function ha_assert_btr_x_locked() which is then
  called from them;
- fix AHI-related code formatting in
  xtradb_internal_hash_tables_fill_table().
- expanded the sys_vars suite test
  innodb_adaptive_hash_index_partitions_basic.test;

At the same time fix bug 1216815 /
http://bugs.mysql.com/bug.php?id=69617 (5.6.12 removed UNIV_SYNC_DEBUG
from UNIV_DEBUG) by re-enabling it in univ.i.

Merge bug 1214449 (Adaptive hash index partitions not tested in MTR)
fix by merging the testcase.

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

Same comments about excessive INSERT/SELECT statements as in https://code.launchpad.net/~laurynas-biveinis/percona-server/ahi-partitions-5.6-5.5/+merge/181713.

I haven't reviewed the actual code port yet.

review: Needs Fixing
Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

More comments on test cases:

> === added file 'Percona-Server/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_partitions_basic.test'
> --- Percona-Server/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_partitions_basic.test 1970-01-01 00:00:00 +0000
> +++ Percona-Server/mysql-test/suite/sys_vars/t/innodb_adaptive_hash_index_partitions_basic.test 2013-08-26 13:16:30 +0000
> @@ -0,0 +1,32 @@
> +# A sys_vars suite test from innodb_adaptive_hash_index_partitions. Adapted from
> +# innodb_buffer_pool_instances_basic.test.
> +
> +--source include/have_innodb.inc
> +
> +SELECT COUNT(@@GLOBAL.innodb_adaptive_hash_index_partitions) AS should_be_1;
> +

I’m not sure what the above check is supposed to verify. Apparently that
the variable exists and is not NULL. But if that’s the case, the test
would fail anyway.

Just checking the default value would make sense. But it’s not checked
anywhere in the test.

> +--error ER_INCORRECT_GLOBAL_LOCAL_VAR
> +SET @@GLOBAL.innodb_adaptive_hash_index_partitions=1;
> +
> +SELECT COUNT(@@GLOBAL.innodb_adaptive_hash_index_partitions) AS should_be_1;
> +

The same check again?

> +SELECT COUNT(VARIABLE_VALUE) AS should_be_1
> +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
> +WHERE VARIABLE_NAME='innodb_adaptive_hash_index_partitions';
> +
> +SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions = VARIABLE_VALUE AS should_be_1
> +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
> +WHERE VARIABLE_NAME='innodb_adaptive_hash_index_partitions';
> +
> +SELECT @@innodb_adaptive_hash_index_partitions = @@GLOBAL.innodb_adaptive_hash_index_partitions AS should_be_1;
> +
> +SELECT COUNT(@@innodb_adaptive_hash_index_partitions) AS should_be_1;
> +
> +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
> +SELECT COUNT(@@LOCAL.innodb_adaptive_hash_index_partitions);
> +
> +--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
> +SELECT COUNT(@@SESSION.innodb_adaptive_hash_index_partitions);
> +
> +--Error ER_BAD_FIELD_ERROR
> +SELECT innodb_adaptive_hash_index_partitions = @@SESSION.innodb_adaptive_hash_index_partitions;

I don’t know the purpose of all these checks which are replicated from
one test case to another. It looks like some incompetent (to put it
mildly) person first wrote them, and then everyone else copies that
stuff whenever he needs to implement a variable test.

What I would expect to see in a sys_var.*_basic test is verifying
the variable type, and default/min/max values. Instead most tests do
some acrobatics with I_S and different syntax to access the variable.

Please also consider backporting it to 5.5 as I mentioned in the 5.5 MP.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

> More comments on test cases:
...
> I don’t know the purpose of all these checks which are replicated from
> one test case to another. It looks like some incompetent (to put it
> mildly) person first wrote them, and then everyone else copies that
> stuff whenever he needs to implement a variable test.
>
> What I would expect to see in a sys_var.*_basic test is verifying
> the variable type, and default/min/max values. Instead most tests do
> some acrobatics with I_S and different syntax to access the variable.

I absolutely agree with all these comments and obviously I have cut some corners when copied/pasted/modified it.

What do you think about the following? The variable is global-only, read-only. Check the default, check the read-only-ness, check that global only. For 5.5 too.

# A sys_vars suite test from innodb_adaptive_hash_index_partitions.

--source include/have_innodb.inc

SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;

--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@GLOBAL.innodb_adaptive_hash_index_partitions=1;

--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@LOCAL.innodb_adaptive_hash_index_partitions;

--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT @@SESSION.innodb_adaptive_hash_index_partitions;

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

On Tue, Aug 27 2013 15:52:14 +0000, Laurynas Biveinis wrote:

>> More comments on test cases:
> ...
>> I don’t know the purpose of all these checks which are replicated from
>> one test case to another. It looks like some incompetent (to put it
>> mildly) person first wrote them, and then everyone else copies that
>> stuff whenever he needs to implement a variable test.
>>
>> What I would expect to see in a sys_var.*_basic test is verifying
>> the variable type, and default/min/max values. Instead most tests do
>> some acrobatics with I_S and different syntax to access the variable.
>
> I absolutely agree with all these comments and obviously I have cut some corners when copied/pasted/modified it.
>
> What do you think about the following? The variable is global-only, read-only. Check the default, check the read-only-ness, check that global only. For 5.5 too.
>
> # A sys_vars suite test from innodb_adaptive_hash_index_partitions.
>
> --source include/have_innodb.inc
>
> SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;
>
> --error ER_INCORRECT_GLOBAL_LOCAL_VAR
> SET @@GLOBAL.innodb_adaptive_hash_index_partitions=1;
>
> --error ER_INCORRECT_GLOBAL_LOCAL_VAR
> SELECT @@LOCAL.innodb_adaptive_hash_index_partitions;
>
> --error ER_INCORRECT_GLOBAL_LOCAL_VAR
> SELECT @@SESSION.innodb_adaptive_hash_index_partitions;

OK.

Revision history for this message
Alexey Kopytov (akopytov) wrote :
Download full text (4.5 KiB)

Hi Laurynas,

As discussed on IRC, I’m only posting comments specific to the port
itself. I’ll handle everything else in the followup work on AHI.

On Wed, Aug 28 2013 13:59:04 +0400, Laurynas Biveinis wrote:

[...]

> - btr_search_latch_temp = (rw_lock_t*) mem_alloc(sizeof(rw_lock_t));
> + /* btr_search_index_num should be <= 32. (bits of
> + trx->has_search_latch) */
> + ut_ad(btr_search_index_num <= 32);

This assertion is wrong. We allow 64 AHI partitions in 64-bit
architectures in 5.5, and its documented. It’s just that the code
comment is wrong.

>
> - rw_lock_create(btr_search_latch_key, &btr_search_latch,
> - SYNC_SEARCH_SYS);
> + btr_search_latch_temp_arr = (rw_lock_t**)
> + mem_alloc(sizeof(rw_lock_t *) * btr_search_index_num);

What’s so temporal about btr_search_latch_temp_arr[]? It might make
sense in the single-lock code (though the reasoning for it is dubious),
but it correctly does not have “temp” in 5.5 code, as it’s a regular array.

[...]

> index = block->index;
> -
> - if (UNIV_LIKELY(!index)) {
> -
> - rw_lock_s_unlock(&btr_search_latch);
> -
> + if (UNIV_UNLIKELY(!index)) {
> + rw_lock_s_unlock(btr_search_latch);
> return;
> }
>
> + ut_a(btr_search_latch == btr_search_get_latch(index->id));
> +

Shouldn’t this be a debug assertion? btr_search_latch is basically a
constant attribute of each index. So it’s more of a code invariant.

[...]

> -btr_search_validate(void)
> -/*=====================*/
> +btr_search_validate_one_table(
> +/*==========================*/
> + ulint t)
> {
> ha_node_t* node;
> ulint n_page_dumps = 0;
> @@ -1874,24 +1944,20 @@
>
> rec_offs_init(offsets_);
>
> - rw_lock_x_lock(&btr_search_latch);
> - buf_pool_mutex_enter_all();
> -
> - cell_count = hash_get_n_cells(btr_search_sys->hash_index);
> + cell_count = hash_get_n_cells(btr_search_sys->hash_index[t]);
>

Why buf_pool_mutex_enter_all() / buf_pool_mutex_exit_all() calls are
being removed from btr_search_validate[_one_table]()?

[...]

> +ha_assert_btr_x_locked(
> +/*===================*/
> + const hash_table_t* table) /*!<in: hash table to check */
> +{
> + ulint i;
> +
> + ut_ad(table->adaptive);
> +
> + for (i = 0; i < btr_search_index_num; i++)
> + if (btr_search_sys->hash_index[i] == table)
> + break;

Braces.

[...]

> +/********************************************************************//**
> +Latches all adaptive hash index latches in shared mode. */
> +UNIV_INLINE
> +void
> +btr_search_s_lock_all(void);
> +/*========================*/
> +
> +/********************************************************************//**
> +Unlatches all adaptive hash index latches in shared mode. */
> +UNIV_INLINE
> +void
> +btr_search_s_unlock_all(void);
> +/*==========================*/
> +

These ones are declared and defined, but not used.

[...]

> === modified file 'Percona-Server/storage/innobase/include/mtr0log.ic'
> --- Percona-Server/storage/innobase/include/mtr0log.ic 2013-08-06 15:16:34 +0000
> +++ Percona-Server/storage/innobase/include/mtr0log.ic 2013-08-28 09:57:53 +0000
> @@ -28,6 +28,7 @@
> #include "buf0buf.h"
> #include "buf0dblwr.h"
> #include "fsp0types.h"
> +#include "btr0types.h"
> #inc...

Read more...

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

> Why buf_pool_mutex_enter_all() / buf_pool_mutex_exit_all() calls are
> being removed from btr_search_validate[_one_table]()?

A mistake, mix-up with the buffer pool mutex split patch.

> > +#include "btr0types.h"
>
> Why new #includes in mtr0log.ic, que0que.h and read0read.h, trx0roll.h,
> trx0trx.cc, ut0ut.cc and os0file.cc?

It's because trx0trx.ic needs btr stuff in trx_search_latch_reserve_if_needed(), and with these includes I broke the circular dependencies.

Preview Diff

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

Subscribers

People subscribed via source and target branches