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

Proposed by Laurynas Biveinis
Status: Merged
Approved by: Alexey Kopytov
Approved revision: no longer in the source branch.
Merged at revision: 420
Proposed branch: lp:~laurynas-biveinis/percona-server/ahi-partitions-5.6-5.6
Merge into: lp:percona-server/5.6
Diff against target: 1897 lines (+678/-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 (+52/-2)
Percona-Server/storage/innobase/include/btr0sea.ic (+79/-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) Approve
Review via email: mp+182960@code.launchpad.net

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

Description of the change

4th MP:

Removed btr_search_s_unlock_all().
Local compilation testing + percona_ahi_partitions testcase run.

3rd MP:

Review comments addressed,
http://jenkins.percona.com/job/percona-server-5.6-param/241/

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 : Posted in a previous version of this proposal
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 : Posted in a previous version of this proposal

> 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.

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

btr_search_s_unlock_all() is still there.

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

gah, removing.

Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'Percona-Server/mysql-test/suite/innodb/r/percona_ahi_partitions.result'
--- Percona-Server/mysql-test/suite/innodb/r/percona_ahi_partitions.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/innodb/r/percona_ahi_partitions.result 2013-08-29 17:11:28 +0000
@@ -0,0 +1,33 @@
1SELECT @@GLOBAL.innodb_adaptive_hash_index;
2@@GLOBAL.innodb_adaptive_hash_index
31
4SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;
5@@GLOBAL.innodb_adaptive_hash_index_partitions
64
7SET GLOBAL innodb_monitor_enable=module_adaptive_hash;
8CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
9CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
10CREATE TABLE t3 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
11Filling tables
12Querying
13SELECT COUNT >= 6 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_pages_added';
14should_be_1
151
16SELECT COUNT >= 6 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_rows_added';
17should_be_1
181
19SELECT COUNT > 0 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_searches';
20should_be_1
211
22SELECT COUNT(*) > 0 AS should_be_1 FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
23WHERE PAGE_STATE LIKE "MEMORY";
24should_be_1
251
26SELECT COUNT(*) >= 6 AS should_be_1 FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
27WHERE IS_HASHED LIKE "YES";
28should_be_1
291
30SET GLOBAL innodb_monitor_disable=module_adaptive_hash;
31DROP TABLE t1, t2, t3;
32SET GLOBAL innodb_monitor_enable=default;
33SET GLOBAL innodb_monitor_disable=default;
034
=== added file 'Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions-master.opt'
--- Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions-master.opt 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions-master.opt 2013-08-29 17:11:28 +0000
@@ -0,0 +1,1 @@
1--innodb-adaptive-hash-index-partitions=4
02
=== added file 'Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions.test'
--- Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions.test 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/innodb/t/percona_ahi_partitions.test 2013-08-29 17:11:28 +0000
@@ -0,0 +1,67 @@
1#
2# Basic test for InnoDB adaptive hash index partitions.
3# TODO: add another testcase that uses DEBUG_SYNC to check the partition locking
4#
5--source include/have_innodb.inc
6
7# Check setup
8SELECT @@GLOBAL.innodb_adaptive_hash_index;
9SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;
10
11SET GLOBAL innodb_monitor_enable=module_adaptive_hash;
12
13# 6 index trees across 4 AHI partitions
14CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
15CREATE TABLE t2 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
16CREATE TABLE t3 (a INT PRIMARY KEY, b INT, c CHAR(200), UNIQUE INDEX b(b)) ENGINE=InnoDB;
17
18--echo Filling tables
19--disable_query_log
20let $i=3;
21while ($i)
22{
23 eval INSERT INTO t1 VALUES ($i, $i, REPEAT("a", 200));
24 eval INSERT INTO t2 VALUES ($i, $i, REPEAT("a", 200));
25 eval INSERT INTO t3 VALUES ($i, $i, REPEAT("a", 200));
26 dec $i;
27}
28
29--echo Querying
30--disable_result_log
31let $i=200;
32while ($i)
33{
34 SELECT b FROM t1 WHERE a=1;
35 SELECT a FROM t1 WHERE b=1;
36 SELECT b FROM t2 WHERE a=2;
37 SELECT a FROM t2 WHERE b=2;
38 SELECT b FROM t3 WHERE a=3;
39 SELECT a FROM t3 WHERE b=3;
40 dec $i;
41}
42--enable_result_log
43--enable_query_log
44
45# Some buffer pool pages should be hashed
46SELECT COUNT >= 6 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_pages_added';
47# Some rows should be hashed
48SELECT COUNT >= 6 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_rows_added';
49# AHI should have been used for queries, but the exact lower bound is hard to determine
50SELECT COUNT > 0 as should_be_1 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME = 'adaptive_hash_searches';
51
52# Buffer pool must contain AHI pages now
53SELECT COUNT(*) > 0 AS should_be_1 FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
54 WHERE PAGE_STATE LIKE "MEMORY";
55
56# Buffer pool must contain no less than the number of index trees hashed pages now
57SELECT COUNT(*) >= 6 AS should_be_1 FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
58 WHERE IS_HASHED LIKE "YES";
59
60SET GLOBAL innodb_monitor_disable=module_adaptive_hash;
61
62DROP TABLE t1, t2, t3;
63
64--disable_warnings
65SET GLOBAL innodb_monitor_enable=default;
66SET GLOBAL innodb_monitor_disable=default;
67--enable_warnings
068
=== added file 'Percona-Server/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_partitions_basic.result'
--- Percona-Server/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_partitions_basic.result 1970-01-01 00:00:00 +0000
+++ Percona-Server/mysql-test/suite/sys_vars/r/innodb_adaptive_hash_index_partitions_basic.result 2013-08-29 17:11:28 +0000
@@ -0,0 +1,9 @@
1SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;
2@@GLOBAL.innodb_adaptive_hash_index_partitions
31
4SET @@GLOBAL.innodb_adaptive_hash_index_partitions=1;
5ERROR HY000: Variable 'innodb_adaptive_hash_index_partitions' is a read only variable
6SELECT @@LOCAL.innodb_adaptive_hash_index_partitions;
7ERROR HY000: Variable 'innodb_adaptive_hash_index_partitions' is a GLOBAL variable
8SELECT @@SESSION.innodb_adaptive_hash_index_partitions;
9ERROR HY000: Variable 'innodb_adaptive_hash_index_partitions' is a GLOBAL variable
010
=== 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-29 17:11:28 +0000
@@ -0,0 +1,14 @@
1# A sys_vars suite test for innodb_adaptive_hash_index_partitions.
2
3--source include/have_innodb.inc
4
5SELECT @@GLOBAL.innodb_adaptive_hash_index_partitions;
6
7--error ER_INCORRECT_GLOBAL_LOCAL_VAR
8SET @@GLOBAL.innodb_adaptive_hash_index_partitions=1;
9
10--error ER_INCORRECT_GLOBAL_LOCAL_VAR
11SELECT @@LOCAL.innodb_adaptive_hash_index_partitions;
12
13--error ER_INCORRECT_GLOBAL_LOCAL_VAR
14SELECT @@SESSION.innodb_adaptive_hash_index_partitions;
015
=== modified file 'Percona-Server/storage/innobase/btr/btr0cur.cc'
--- Percona-Server/storage/innobase/btr/btr0cur.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/storage/innobase/btr/btr0cur.cc 2013-08-29 17:11:28 +0000
@@ -536,7 +536,8 @@
536# ifdef UNIV_SEARCH_PERF_STAT536# ifdef UNIV_SEARCH_PERF_STAT
537 info->n_searches++;537 info->n_searches++;
538# endif538# endif
539 if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_NOT_LOCKED539 if ((rw_lock_get_writer(btr_search_get_latch(cursor->index->id))
540 == RW_LOCK_NOT_LOCKED)
540 && latch_mode <= BTR_MODIFY_LEAF541 && latch_mode <= BTR_MODIFY_LEAF
541 && info->last_hash_succ542 && info->last_hash_succ
542 && !estimate543 && !estimate
@@ -572,7 +573,7 @@
572573
573 if (has_search_latch) {574 if (has_search_latch) {
574 /* Release possible search latch to obey latching order */575 /* Release possible search latch to obey latching order */
575 rw_lock_s_unlock(&btr_search_latch);576 rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
576 }577 }
577578
578 /* Store the position of the tree latch we push to mtr so that we579 /* Store the position of the tree latch we push to mtr so that we
@@ -895,7 +896,7 @@
895896
896 if (has_search_latch) {897 if (has_search_latch) {
897898
898 rw_lock_s_lock(&btr_search_latch);899 rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
899 }900 }
900}901}
901902
@@ -2162,13 +2163,13 @@
2162 btr_search_update_hash_on_delete(cursor);2163 btr_search_update_hash_on_delete(cursor);
2163 }2164 }
21642165
2165 rw_lock_x_lock(&btr_search_latch);2166 rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
2166 }2167 }
21672168
2168 row_upd_rec_in_place(rec, index, offsets, update, page_zip);2169 row_upd_rec_in_place(rec, index, offsets, update, page_zip);
21692170
2170 if (is_hashed) {2171 if (is_hashed) {
2171 rw_lock_x_unlock(&btr_search_latch);2172 rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
2172 }2173 }
21732174
2174 btr_cur_update_in_place_log(flags, rec, index, update,2175 btr_cur_update_in_place_log(flags, rec, index, update,
21752176
=== modified file 'Percona-Server/storage/innobase/btr/btr0sea.cc'
--- Percona-Server/storage/innobase/btr/btr0sea.cc 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/btr/btr0sea.cc 2013-08-29 17:11:28 +0000
@@ -47,6 +47,9 @@
47Protected by btr_search_latch. */47Protected by btr_search_latch. */
48UNIV_INTERN char btr_search_enabled = TRUE;48UNIV_INTERN char btr_search_enabled = TRUE;
4949
50/** Number of adaptive hash index partitions */
51UNIV_INTERN ulint btr_search_index_num;
52
50/** A dummy variable to fool the compiler */53/** A dummy variable to fool the compiler */
51UNIV_INTERN ulint btr_search_this_is_zero = 0;54UNIV_INTERN ulint btr_search_this_is_zero = 0;
5255
@@ -68,9 +71,9 @@
68being updated in-place! We can use fact (1) to perform unique searches to71being updated in-place! We can use fact (1) to perform unique searches to
69indexes. */72indexes. */
7073
71/* We will allocate the latch from dynamic memory to get it to the74/* We will allocate the latches from dynamic memory to get them to the
72same DRAM page as other hotspot semaphores */75same DRAM page as other hotspot semaphores */
73UNIV_INTERN rw_lock_t* btr_search_latch_temp;76UNIV_INTERN rw_lock_t** btr_search_latch_arr;
7477
75/** padding to prevent other memory update hotspots from residing on78/** padding to prevent other memory update hotspots from residing on
76the same memory cache line */79the same memory cache line */
@@ -122,18 +125,19 @@
122will not guarantee success. */125will not guarantee success. */
123static126static
124void127void
125btr_search_check_free_space_in_heap(void)128btr_search_check_free_space_in_heap(
126/*=====================================*/129/*================================*/
130 index_id_t key) /*!<in: id of the hashed index tree */
127{131{
128 hash_table_t* table;132 hash_table_t* table;
129 mem_heap_t* heap;133 mem_heap_t* heap;
130134
131#ifdef UNIV_SYNC_DEBUG135#ifdef UNIV_SYNC_DEBUG
132 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));136 ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
133 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));137 ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
134#endif /* UNIV_SYNC_DEBUG */138#endif /* UNIV_SYNC_DEBUG */
135139
136 table = btr_search_sys->hash_index;140 table = btr_search_get_hash_index(key);
137141
138 heap = table->heap;142 heap = table->heap;
139143
@@ -144,7 +148,7 @@
144 if (heap->free_block == NULL) {148 if (heap->free_block == NULL) {
145 buf_block_t* block = buf_block_alloc(NULL);149 buf_block_t* block = buf_block_alloc(NULL);
146150
147 rw_lock_x_lock(&btr_search_latch);151 rw_lock_x_lock(btr_search_get_latch(key));
148152
149 if (heap->free_block == NULL) {153 if (heap->free_block == NULL) {
150 heap->free_block = block;154 heap->free_block = block;
@@ -152,7 +156,7 @@
152 buf_block_free(block);156 buf_block_free(block);
153 }157 }
154158
155 rw_lock_x_unlock(&btr_search_latch);159 rw_lock_x_unlock(btr_search_get_latch(key));
156 }160 }
157}161}
158162
@@ -164,23 +168,47 @@
164/*==================*/168/*==================*/
165 ulint hash_size) /*!< in: hash index hash table size */169 ulint hash_size) /*!< in: hash index hash table size */
166{170{
171 ulint i;
172
173 /* PS bug lp:1018264 - Multiple hash index partitions causes overly
174 large hash index: When multiple adaptive hash index partitions are
175 specified, _each_ partition was being created with hash_size which
176 should be 1/64 of the total size of all buffer pools which is
177 incorrect and can cause overly high memory usage. hash_size
178 should be representing the _total_ size of all partitions, not the
179 individual size of each partition. */
180 hash_size /= btr_search_index_num;
181
167 /* We allocate the search latch from dynamic memory:182 /* We allocate the search latch from dynamic memory:
168 see above at the global variable definition */183 see above at the global variable definition */
169184
170 btr_search_latch_temp = (rw_lock_t*) mem_alloc(sizeof(rw_lock_t));185 /* btr_search_index_num should be no greater than bits of
186 trx->has_search_latch, which is ulint. */
187 ut_ad(btr_search_index_num <= sizeof(ulint));
171188
172 rw_lock_create(btr_search_latch_key, &btr_search_latch,189 btr_search_latch_arr = (rw_lock_t**)
173 SYNC_SEARCH_SYS);190 mem_alloc(sizeof(rw_lock_t *) * btr_search_index_num);
174191
175 btr_search_sys = (btr_search_sys_t*)192 btr_search_sys = (btr_search_sys_t*)
176 mem_alloc(sizeof(btr_search_sys_t));193 mem_alloc(sizeof(btr_search_sys_t));
177194
178 btr_search_sys->hash_index = ha_create(hash_size, 0,195 btr_search_sys->hash_index = (hash_table_t **)
179 MEM_HEAP_FOR_BTR_SEARCH, 0);196 mem_alloc(sizeof(hash_table_t *) * btr_search_index_num);
197
198 for (i = 0; i < btr_search_index_num; i++) {
199 btr_search_latch_arr[i] = (rw_lock_t *)
200 mem_alloc(sizeof(rw_lock_t));
201
202 rw_lock_create(btr_search_latch_key, btr_search_latch_arr[i],
203 SYNC_SEARCH_SYS);
204
205 btr_search_sys->hash_index[i]
206 = ha_create(hash_size, 0, MEM_HEAP_FOR_BTR_SEARCH, 0);
207
180#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG208#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
181 btr_search_sys->hash_index->adaptive = TRUE;209 btr_search_sys->hash_index[i]->adaptive = TRUE;
182#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */210#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
183211 }
184}212}
185213
186/*****************************************************************//**214/*****************************************************************//**
@@ -190,11 +218,25 @@
190btr_search_sys_free(void)218btr_search_sys_free(void)
191/*=====================*/219/*=====================*/
192{220{
193 rw_lock_free(&btr_search_latch);221 ulint i;
194 mem_free(btr_search_latch_temp);222
195 btr_search_latch_temp = NULL;223 for (i = 0; i < btr_search_index_num; i++) {
196 mem_heap_free(btr_search_sys->hash_index->heap);224
197 hash_table_free(btr_search_sys->hash_index);225 rw_lock_free(btr_search_latch_arr[i]);
226
227 mem_free(btr_search_latch_arr[i]);
228
229 mem_heap_free(btr_search_sys->hash_index[i]->heap);
230
231 hash_table_free(btr_search_sys->hash_index[i]);
232
233 }
234
235 mem_free(btr_search_latch_arr);
236 btr_search_latch_arr = NULL;
237
238 mem_free(btr_search_sys->hash_index);
239
198 mem_free(btr_search_sys);240 mem_free(btr_search_sys);
199 btr_search_sys = NULL;241 btr_search_sys = NULL;
200}242}
@@ -210,13 +252,14 @@
210 dict_index_t* index;252 dict_index_t* index;
211253
212 ut_ad(mutex_own(&dict_sys->mutex));254 ut_ad(mutex_own(&dict_sys->mutex));
213#ifdef UNIV_SYNC_DEBUG
214 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
215#endif /* UNIV_SYNC_DEBUG */
216255
217 for (index = dict_table_get_first_index(table); index;256 for (index = dict_table_get_first_index(table); index;
218 index = dict_table_get_next_index(index)) {257 index = dict_table_get_next_index(index)) {
219258
259#ifdef UNIV_SYNC_DEBUG
260 ut_ad(rw_lock_own(btr_search_get_latch(index->id),
261 RW_LOCK_EX));
262#endif /* UNIV_SYNC_DEBUG */
220 index->search_info->ref_count = 0;263 index->search_info->ref_count = 0;
221 }264 }
222}265}
@@ -229,9 +272,10 @@
229/*====================*/272/*====================*/
230{273{
231 dict_table_t* table;274 dict_table_t* table;
275 ulint i;
232276
233 mutex_enter(&dict_sys->mutex);277 mutex_enter(&dict_sys->mutex);
234 rw_lock_x_lock(&btr_search_latch);278 btr_search_x_lock_all();
235279
236 btr_search_enabled = FALSE;280 btr_search_enabled = FALSE;
237281
@@ -255,10 +299,12 @@
255 buf_pool_clear_hash_index();299 buf_pool_clear_hash_index();
256300
257 /* Clear the adaptive hash index. */301 /* Clear the adaptive hash index. */
258 hash_table_clear(btr_search_sys->hash_index);302 for (i = 0; i < btr_search_index_num; i++) {
259 mem_heap_empty(btr_search_sys->hash_index->heap);303 hash_table_clear(btr_search_sys->hash_index[i]);
304 mem_heap_empty(btr_search_sys->hash_index[i]->heap);
305 }
260306
261 rw_lock_x_unlock(&btr_search_latch);307 btr_search_x_unlock_all();
262}308}
263309
264/********************************************************************//**310/********************************************************************//**
@@ -268,11 +314,11 @@
268btr_search_enable(void)314btr_search_enable(void)
269/*====================*/315/*====================*/
270{316{
271 rw_lock_x_lock(&btr_search_latch);317 btr_search_x_lock_all();
272318
273 btr_search_enabled = TRUE;319 btr_search_enabled = TRUE;
274320
275 rw_lock_x_unlock(&btr_search_latch);321 btr_search_x_unlock_all();
276}322}
277323
278/*****************************************************************//**324/*****************************************************************//**
@@ -324,20 +370,21 @@
324ulint370ulint
325btr_search_info_get_ref_count(371btr_search_info_get_ref_count(
326/*==========================*/372/*==========================*/
327 btr_search_t* info) /*!< in: search info. */373 btr_search_t* info, /*!< in: search info. */
374 index_id_t key) /*!< in: id of the index owning search info */
328{375{
329 ulint ret;376 ulint ret;
330377
331 ut_ad(info);378 ut_ad(info);
332379
333#ifdef UNIV_SYNC_DEBUG380#ifdef UNIV_SYNC_DEBUG
334 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));381 ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
335 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));382 ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
336#endif /* UNIV_SYNC_DEBUG */383#endif /* UNIV_SYNC_DEBUG */
337384
338 rw_lock_s_lock(&btr_search_latch);385 rw_lock_s_lock(btr_search_get_latch(key));
339 ret = info->ref_count;386 ret = info->ref_count;
340 rw_lock_s_unlock(&btr_search_latch);387 rw_lock_s_unlock(btr_search_get_latch(key));
341388
342 return(ret);389 return(ret);
343}390}
@@ -353,17 +400,15 @@
353 btr_search_t* info, /*!< in/out: search info */400 btr_search_t* info, /*!< in/out: search info */
354 btr_cur_t* cursor) /*!< in: cursor which was just positioned */401 btr_cur_t* cursor) /*!< in: cursor which was just positioned */
355{402{
356 dict_index_t* index;403 dict_index_t* index = cursor->index;
357 ulint n_unique;404 ulint n_unique;
358 int cmp;405 int cmp;
359406
360#ifdef UNIV_SYNC_DEBUG407#ifdef UNIV_SYNC_DEBUG
361 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));408 ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
362 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));409 ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
363#endif /* UNIV_SYNC_DEBUG */410#endif /* UNIV_SYNC_DEBUG */
364411
365 index = cursor->index;
366
367 if (dict_index_is_ibuf(index)) {412 if (dict_index_is_ibuf(index)) {
368 /* So many deletes are performed on an insert buffer tree413 /* So many deletes are performed on an insert buffer tree
369 that we do not consider a hash index useful on it: */414 that we do not consider a hash index useful on it: */
@@ -477,8 +522,10 @@
477 /*!< in: cursor */522 /*!< in: cursor */
478{523{
479#ifdef UNIV_SYNC_DEBUG524#ifdef UNIV_SYNC_DEBUG
480 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));525 ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
481 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));526 RW_LOCK_SHARED));
527 ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
528 RW_LOCK_EX));
482 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)529 ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
483 || rw_lock_own(&block->lock, RW_LOCK_EX));530 || rw_lock_own(&block->lock, RW_LOCK_EX));
484#endif /* UNIV_SYNC_DEBUG */531#endif /* UNIV_SYNC_DEBUG */
@@ -562,7 +609,8 @@
562609
563 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);610 ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
564#ifdef UNIV_SYNC_DEBUG611#ifdef UNIV_SYNC_DEBUG
565 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));612 ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id),
613 RW_LOCK_EX));
566 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)614 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
567 || rw_lock_own(&(block->lock), RW_LOCK_EX));615 || rw_lock_own(&(block->lock), RW_LOCK_EX));
568#endif /* UNIV_SYNC_DEBUG */616#endif /* UNIV_SYNC_DEBUG */
@@ -603,11 +651,13 @@
603 mem_heap_free(heap);651 mem_heap_free(heap);
604 }652 }
605#ifdef UNIV_SYNC_DEBUG653#ifdef UNIV_SYNC_DEBUG
606 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));654 ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id),
655 RW_LOCK_EX));
607#endif /* UNIV_SYNC_DEBUG */656#endif /* UNIV_SYNC_DEBUG */
608657
609 ha_insert_for_fold(btr_search_sys->hash_index, fold,658 ha_insert_for_fold(
610 block, rec);659 btr_search_get_hash_index(cursor->index->id), fold,
660 block, rec);
611661
612 MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);662 MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED);
613 }663 }
@@ -628,8 +678,10 @@
628 ulint* params2;678 ulint* params2;
629679
630#ifdef UNIV_SYNC_DEBUG680#ifdef UNIV_SYNC_DEBUG
631 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));681 ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
632 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));682 RW_LOCK_SHARED));
683 ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id),
684 RW_LOCK_EX));
633#endif /* UNIV_SYNC_DEBUG */685#endif /* UNIV_SYNC_DEBUG */
634686
635 block = btr_cur_get_block(cursor);687 block = btr_cur_get_block(cursor);
@@ -647,7 +699,7 @@
647699
648 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {700 if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
649701
650 btr_search_check_free_space_in_heap();702 btr_search_check_free_space_in_heap(cursor->index->id);
651 }703 }
652704
653 if (cursor->flag == BTR_CUR_HASH_FAIL) {705 if (cursor->flag == BTR_CUR_HASH_FAIL) {
@@ -657,11 +709,11 @@
657 btr_search_n_hash_fail++;709 btr_search_n_hash_fail++;
658#endif /* UNIV_SEARCH_PERF_STAT */710#endif /* UNIV_SEARCH_PERF_STAT */
659711
660 rw_lock_x_lock(&btr_search_latch);712 rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
661713
662 btr_search_update_hash_ref(info, block, cursor);714 btr_search_update_hash_ref(info, block, cursor);
663715
664 rw_lock_x_unlock(&btr_search_latch);716 rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
665 }717 }
666718
667 if (build_index) {719 if (build_index) {
@@ -906,17 +958,19 @@
906 cursor->flag = BTR_CUR_HASH;958 cursor->flag = BTR_CUR_HASH;
907959
908 if (UNIV_LIKELY(!has_search_latch)) {960 if (UNIV_LIKELY(!has_search_latch)) {
909 rw_lock_s_lock(&btr_search_latch);961 rw_lock_s_lock(btr_search_get_latch(index_id));
910962
911 if (UNIV_UNLIKELY(!btr_search_enabled)) {963 if (UNIV_UNLIKELY(!btr_search_enabled)) {
912 goto failure_unlock;964 goto failure_unlock;
913 }965 }
914 }966 }
915967
916 ut_ad(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_EX);968 ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id))
917 ut_ad(rw_lock_get_reader_count(&btr_search_latch) > 0);969 != RW_LOCK_EX);
970 ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
918971
919 rec = (rec_t*) ha_search_and_get_data(btr_search_sys->hash_index, fold);972 rec = (rec_t*) ha_search_and_get_data(
973 btr_search_get_hash_index(index_id), fold);
920974
921 if (UNIV_UNLIKELY(!rec)) {975 if (UNIV_UNLIKELY(!rec)) {
922 goto failure_unlock;976 goto failure_unlock;
@@ -934,7 +988,7 @@
934 goto failure_unlock;988 goto failure_unlock;
935 }989 }
936990
937 rw_lock_s_unlock(&btr_search_latch);991 rw_lock_s_unlock(btr_search_get_latch(index_id));
938992
939 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);993 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
940 }994 }
@@ -1031,7 +1085,7 @@
1031 /*-------------------------------------------*/1085 /*-------------------------------------------*/
1032failure_unlock:1086failure_unlock:
1033 if (UNIV_LIKELY(!has_search_latch)) {1087 if (UNIV_LIKELY(!has_search_latch)) {
1034 rw_lock_s_unlock(&btr_search_latch);1088 rw_lock_s_unlock(btr_search_get_latch(index_id));
1035 }1089 }
1036failure:1090failure:
1037 cursor->flag = BTR_CUR_HASH_FAIL;1091 cursor->flag = BTR_CUR_HASH_FAIL;
@@ -1079,12 +1133,9 @@
1079 const dict_index_t* index;1133 const dict_index_t* index;
1080 ulint* offsets;1134 ulint* offsets;
1081 btr_search_t* info;1135 btr_search_t* info;
10821136 rw_lock_t* btr_search_latch;
1083#ifdef UNIV_SYNC_DEBUG1137
1084 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));1138retry:
1085 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1086#endif /* UNIV_SYNC_DEBUG */
1087
1088 /* Do a dirty check on block->index, return if the block is1139 /* Do a dirty check on block->index, return if the block is
1089 not in the adaptive hash index. This is to avoid acquiring1140 not in the adaptive hash index. This is to avoid acquiring
1090 shared btr_search_latch for performance consideration. */1141 shared btr_search_latch for performance consideration. */
@@ -1092,17 +1143,31 @@
1092 return;1143 return;
1093 }1144 }
10941145
1095retry:1146 btr_search_latch = block->btr_search_latch;
1096 rw_lock_s_lock(&btr_search_latch);1147
1148 if (UNIV_UNLIKELY(!btr_search_latch)) {
1149 return;
1150 }
1151
1152#ifdef UNIV_SYNC_DEBUG
1153 ut_ad(!rw_lock_own(btr_search_latch, RW_LOCK_SHARED));
1154 ut_ad(!rw_lock_own(btr_search_latch, RW_LOCK_EX));
1155#endif /* UNIV_SYNC_DEBUG */
1156
1157 rw_lock_s_lock(btr_search_latch);
1158 if (UNIV_UNLIKELY(btr_search_latch != block->btr_search_latch)) {
1159 rw_lock_s_unlock(btr_search_latch);
1160 goto retry;
1161 }
1162
1097 index = block->index;1163 index = block->index;
10981164 if (UNIV_UNLIKELY(!index)) {
1099 if (UNIV_LIKELY(!index)) {1165 rw_lock_s_unlock(btr_search_latch);
1100
1101 rw_lock_s_unlock(&btr_search_latch);
1102
1103 return;1166 return;
1104 }1167 }
11051168
1169 ut_ad(btr_search_latch == btr_search_get_latch(index->id));
1170
1106 ut_a(!dict_index_is_ibuf(index));1171 ut_a(!dict_index_is_ibuf(index));
1107#ifdef UNIV_DEBUG1172#ifdef UNIV_DEBUG
1108 switch (dict_index_get_online_status(index)) {1173 switch (dict_index_get_online_status(index)) {
@@ -1125,7 +1190,7 @@
1125 }1190 }
1126#endif /* UNIV_DEBUG */1191#endif /* UNIV_DEBUG */
11271192
1128 table = btr_search_sys->hash_index;1193 table = btr_search_get_hash_index(index->id);
11291194
1130#ifdef UNIV_SYNC_DEBUG1195#ifdef UNIV_SYNC_DEBUG
1131 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)1196 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
@@ -1141,7 +1206,7 @@
1141 releasing btr_search_latch, as the index page might only1206 releasing btr_search_latch, as the index page might only
1142 be s-latched! */1207 be s-latched! */
11431208
1144 rw_lock_s_unlock(&btr_search_latch);1209 rw_lock_s_unlock(btr_search_latch);
11451210
1146 ut_a(n_fields + n_bytes > 0);1211 ut_a(n_fields + n_bytes > 0);
11471212
@@ -1192,7 +1257,7 @@
1192 mem_heap_free(heap);1257 mem_heap_free(heap);
1193 }1258 }
11941259
1195 rw_lock_x_lock(&btr_search_latch);1260 rw_lock_x_lock(btr_search_get_latch(index->id));
11961261
1197 if (UNIV_UNLIKELY(!block->index)) {1262 if (UNIV_UNLIKELY(!block->index)) {
1198 /* Someone else has meanwhile dropped the hash index */1263 /* Someone else has meanwhile dropped the hash index */
@@ -1208,7 +1273,7 @@
1208 /* Someone else has meanwhile built a new hash index on the1273 /* Someone else has meanwhile built a new hash index on the
1209 page, with different parameters */1274 page, with different parameters */
12101275
1211 rw_lock_x_unlock(&btr_search_latch);1276 rw_lock_x_unlock(btr_search_get_latch(index->id));
12121277
1213 mem_free(folds);1278 mem_free(folds);
1214 goto retry;1279 goto retry;
@@ -1224,6 +1289,7 @@
1224 info->ref_count--;1289 info->ref_count--;
12251290
1226 block->index = NULL;1291 block->index = NULL;
1292 block->btr_search_latch = NULL;
12271293
1228 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_REMOVED);1294 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_REMOVED);
1229 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_REMOVED, n_cached);1295 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_REMOVED, n_cached);
@@ -1239,14 +1305,14 @@
1239 "InnoDB: the hash index to a page of %s,"1305 "InnoDB: the hash index to a page of %s,"
1240 " still %lu hash nodes remain.\n",1306 " still %lu hash nodes remain.\n",
1241 index->name, (ulong) block->n_pointers);1307 index->name, (ulong) block->n_pointers);
1242 rw_lock_x_unlock(&btr_search_latch);1308 rw_lock_x_unlock(btr_search_get_latch(index->id));
12431309
1244 ut_ad(btr_search_validate());1310 ut_ad(btr_search_validate());
1245 } else {1311 } else {
1246 rw_lock_x_unlock(&btr_search_latch);1312 rw_lock_x_unlock(btr_search_get_latch(index->id));
1247 }1313 }
1248#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */1314#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1249 rw_lock_x_unlock(&btr_search_latch);1315 rw_lock_x_unlock(btr_search_get_latch(index->id));
1250#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */1316#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
12511317
1252 mem_free(folds);1318 mem_free(folds);
@@ -1325,30 +1391,30 @@
1325 ut_a(!dict_index_is_ibuf(index));1391 ut_a(!dict_index_is_ibuf(index));
13261392
1327#ifdef UNIV_SYNC_DEBUG1393#ifdef UNIV_SYNC_DEBUG
1328 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));1394 ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
1329 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)1395 ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1330 || rw_lock_own(&(block->lock), RW_LOCK_EX));1396 || rw_lock_own(&(block->lock), RW_LOCK_EX));
1331#endif /* UNIV_SYNC_DEBUG */1397#endif /* UNIV_SYNC_DEBUG */
13321398
1333 rw_lock_s_lock(&btr_search_latch);1399 rw_lock_s_lock(btr_search_get_latch(index->id));
13341400
1335 if (!btr_search_enabled) {1401 if (!btr_search_enabled) {
1336 rw_lock_s_unlock(&btr_search_latch);1402 rw_lock_s_unlock(btr_search_get_latch(index->id));
1337 return;1403 return;
1338 }1404 }
13391405
1340 table = btr_search_sys->hash_index;1406 table = btr_search_get_hash_index(index->id);
1341 page = buf_block_get_frame(block);1407 page = buf_block_get_frame(block);
13421408
1343 if (block->index && ((block->curr_n_fields != n_fields)1409 if (block->index && ((block->curr_n_fields != n_fields)
1344 || (block->curr_n_bytes != n_bytes)1410 || (block->curr_n_bytes != n_bytes)
1345 || (block->curr_left_side != left_side))) {1411 || (block->curr_left_side != left_side))) {
13461412
1347 rw_lock_s_unlock(&btr_search_latch);1413 rw_lock_s_unlock(btr_search_get_latch(index->id));
13481414
1349 btr_search_drop_page_hash_index(block);1415 btr_search_drop_page_hash_index(block);
1350 } else {1416 } else {
1351 rw_lock_s_unlock(&btr_search_latch);1417 rw_lock_s_unlock(btr_search_get_latch(index->id));
1352 }1418 }
13531419
1354 n_recs = page_get_n_recs(page);1420 n_recs = page_get_n_recs(page);
@@ -1442,9 +1508,9 @@
1442 fold = next_fold;1508 fold = next_fold;
1443 }1509 }
14441510
1445 btr_search_check_free_space_in_heap();1511 btr_search_check_free_space_in_heap(index->id);
14461512
1447 rw_lock_x_lock(&btr_search_latch);1513 rw_lock_x_lock(btr_search_get_latch(index->id));
14481514
1449 if (UNIV_UNLIKELY(!btr_search_enabled)) {1515 if (UNIV_UNLIKELY(!btr_search_enabled)) {
1450 goto exit_func;1516 goto exit_func;
@@ -1471,6 +1537,7 @@
1471 block->curr_n_bytes = n_bytes;1537 block->curr_n_bytes = n_bytes;
1472 block->curr_left_side = left_side;1538 block->curr_left_side = left_side;
1473 block->index = index;1539 block->index = index;
1540 block->btr_search_latch = btr_search_get_latch(index->id);
14741541
1475 for (i = 0; i < n_cached; i++) {1542 for (i = 0; i < n_cached; i++) {
14761543
@@ -1480,7 +1547,7 @@
1480 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);1547 MONITOR_INC(MONITOR_ADAPTIVE_HASH_PAGE_ADDED);
1481 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);1548 MONITOR_INC_VALUE(MONITOR_ADAPTIVE_HASH_ROW_ADDED, n_cached);
1482exit_func:1549exit_func:
1483 rw_lock_x_unlock(&btr_search_latch);1550 rw_lock_x_unlock(btr_search_get_latch(index->id));
14841551
1485 mem_free(folds);1552 mem_free(folds);
1486 mem_free(recs);1553 mem_free(recs);
@@ -1515,7 +1582,7 @@
1515 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));1582 ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
1516#endif /* UNIV_SYNC_DEBUG */1583#endif /* UNIV_SYNC_DEBUG */
15171584
1518 rw_lock_s_lock(&btr_search_latch);1585 rw_lock_s_lock(btr_search_get_latch(index->id));
15191586
1520 ut_a(!new_block->index || new_block->index == index);1587 ut_a(!new_block->index || new_block->index == index);
1521 ut_a(!block->index || block->index == index);1588 ut_a(!block->index || block->index == index);
@@ -1524,7 +1591,7 @@
15241591
1525 if (new_block->index) {1592 if (new_block->index) {
15261593
1527 rw_lock_s_unlock(&btr_search_latch);1594 rw_lock_s_unlock(btr_search_get_latch(index->id));
15281595
1529 btr_search_drop_page_hash_index(block);1596 btr_search_drop_page_hash_index(block);
15301597
@@ -1541,7 +1608,7 @@
1541 new_block->n_bytes = block->curr_n_bytes;1608 new_block->n_bytes = block->curr_n_bytes;
1542 new_block->left_side = left_side;1609 new_block->left_side = left_side;
15431610
1544 rw_lock_s_unlock(&btr_search_latch);1611 rw_lock_s_unlock(btr_search_get_latch(index->id));
15451612
1546 ut_a(n_fields + n_bytes > 0);1613 ut_a(n_fields + n_bytes > 0);
15471614
@@ -1553,7 +1620,7 @@
1553 return;1620 return;
1554 }1621 }
15551622
1556 rw_lock_s_unlock(&btr_search_latch);1623 rw_lock_s_unlock(btr_search_get_latch(index->id));
1557}1624}
15581625
1559/********************************************************************//**1626/********************************************************************//**
@@ -1592,7 +1659,7 @@
1592 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);1659 ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
1593 ut_a(!dict_index_is_ibuf(index));1660 ut_a(!dict_index_is_ibuf(index));
15941661
1595 table = btr_search_sys->hash_index;1662 table = btr_search_get_hash_index(cursor->index->id);
15961663
1597 rec = btr_cur_get_rec(cursor);1664 rec = btr_cur_get_rec(cursor);
15981665
@@ -1603,7 +1670,7 @@
1603 mem_heap_free(heap);1670 mem_heap_free(heap);
1604 }1671 }
16051672
1606 rw_lock_x_lock(&btr_search_latch);1673 rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
16071674
1608 if (block->index) {1675 if (block->index) {
1609 ut_a(block->index == index);1676 ut_a(block->index == index);
@@ -1616,7 +1683,7 @@
1616 }1683 }
1617 }1684 }
16181685
1619 rw_lock_x_unlock(&btr_search_latch);1686 rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
1620}1687}
16211688
1622/********************************************************************//**1689/********************************************************************//**
@@ -1653,7 +1720,7 @@
1653 ut_a(cursor->index == index);1720 ut_a(cursor->index == index);
1654 ut_a(!dict_index_is_ibuf(index));1721 ut_a(!dict_index_is_ibuf(index));
16551722
1656 rw_lock_x_lock(&btr_search_latch);1723 rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
16571724
1658 if (!block->index) {1725 if (!block->index) {
16591726
@@ -1667,7 +1734,7 @@
1667 && (cursor->n_bytes == block->curr_n_bytes)1734 && (cursor->n_bytes == block->curr_n_bytes)
1668 && !block->curr_left_side) {1735 && !block->curr_left_side) {
16691736
1670 table = btr_search_sys->hash_index;1737 table = btr_search_get_hash_index(cursor->index->id);
16711738
1672 if (ha_search_and_update_if_found(1739 if (ha_search_and_update_if_found(
1673 table, cursor->fold, rec, block,1740 table, cursor->fold, rec, block,
@@ -1676,9 +1743,9 @@
1676 }1743 }
16771744
1678func_exit:1745func_exit:
1679 rw_lock_x_unlock(&btr_search_latch);1746 rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
1680 } else {1747 } else {
1681 rw_lock_x_unlock(&btr_search_latch);1748 rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
16821749
1683 btr_search_update_hash_on_insert(cursor);1750 btr_search_update_hash_on_insert(cursor);
1684 }1751 }
@@ -1726,9 +1793,9 @@
1726 return;1793 return;
1727 }1794 }
17281795
1729 btr_search_check_free_space_in_heap();1796 btr_search_check_free_space_in_heap(cursor->index->id);
17301797
1731 table = btr_search_sys->hash_index;1798 table = btr_search_get_hash_index(cursor->index->id);
17321799
1733 rec = btr_cur_get_rec(cursor);1800 rec = btr_cur_get_rec(cursor);
17341801
@@ -1760,7 +1827,7 @@
1760 } else {1827 } else {
1761 if (left_side) {1828 if (left_side) {
17621829
1763 rw_lock_x_lock(&btr_search_latch);1830 rw_lock_x_lock(btr_search_get_latch(index->id));
17641831
1765 locked = TRUE;1832 locked = TRUE;
17661833
@@ -1778,7 +1845,7 @@
17781845
1779 if (!locked) {1846 if (!locked) {
17801847
1781 rw_lock_x_lock(&btr_search_latch);1848 rw_lock_x_lock(btr_search_get_latch(index->id));
17821849
1783 locked = TRUE;1850 locked = TRUE;
17841851
@@ -1800,7 +1867,8 @@
1800 if (!left_side) {1867 if (!left_side) {
18011868
1802 if (!locked) {1869 if (!locked) {
1803 rw_lock_x_lock(&btr_search_latch);1870 rw_lock_x_lock(btr_search_get_latch(
1871 index->id));
18041872
1805 locked = TRUE;1873 locked = TRUE;
18061874
@@ -1819,7 +1887,7 @@
18191887
1820 if (!locked) {1888 if (!locked) {
18211889
1822 rw_lock_x_lock(&btr_search_latch);1890 rw_lock_x_lock(btr_search_get_latch(index->id));
18231891
1824 locked = TRUE;1892 locked = TRUE;
18251893
@@ -1846,18 +1914,19 @@
1846 mem_heap_free(heap);1914 mem_heap_free(heap);
1847 }1915 }
1848 if (locked) {1916 if (locked) {
1849 rw_lock_x_unlock(&btr_search_latch);1917 rw_lock_x_unlock(btr_search_get_latch(index->id));
1850 }1918 }
1851}1919}
18521920
1853#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG1921#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1854/********************************************************************//**1922/********************************************************************//**
1855Validates the search system.1923Validates one hash table in the search system.
1856@return TRUE if ok */1924@return TRUE if ok */
1857UNIV_INTERN1925static
1858ibool1926ibool
1859btr_search_validate(void)1927btr_search_validate_one_table(
1860/*=====================*/1928/*==========================*/
1929 ulint t)
1861{1930{
1862 ha_node_t* node;1931 ha_node_t* node;
1863 ulint n_page_dumps = 0;1932 ulint n_page_dumps = 0;
@@ -1874,24 +1943,24 @@
18741943
1875 rec_offs_init(offsets_);1944 rec_offs_init(offsets_);
18761945
1877 rw_lock_x_lock(&btr_search_latch);
1878 buf_pool_mutex_enter_all();1946 buf_pool_mutex_enter_all();
18791947
1880 cell_count = hash_get_n_cells(btr_search_sys->hash_index);1948 cell_count = hash_get_n_cells(btr_search_sys->hash_index[t]);
18811949
1882 for (i = 0; i < cell_count; i++) {1950 for (i = 0; i < cell_count; i++) {
1883 /* We release btr_search_latch every once in a while to1951 /* We release btr_search_latch every once in a while to
1884 give other queries a chance to run. */1952 give other queries a chance to run. */
1885 if ((i != 0) && ((i % chunk_size) == 0)) {1953 if ((i != 0) && ((i % chunk_size) == 0)) {
1886 buf_pool_mutex_exit_all();1954 buf_pool_mutex_exit_all();
1887 rw_lock_x_unlock(&btr_search_latch);1955 btr_search_x_unlock_all();
1888 os_thread_yield();1956 os_thread_yield();
1889 rw_lock_x_lock(&btr_search_latch);1957 btr_search_x_lock_all();
1890 buf_pool_mutex_enter_all();1958 buf_pool_mutex_enter_all();
1891 }1959 }
18921960
1893 node = (ha_node_t*)1961 node = (ha_node_t*)
1894 hash_get_nth_cell(btr_search_sys->hash_index, i)->node;1962 hash_get_nth_cell(btr_search_sys->hash_index[t],
1963 i)->node;
18951964
1896 for (; node != NULL; node = node->next) {1965 for (; node != NULL; node = node->next) {
1897 const buf_block_t* block1966 const buf_block_t* block
@@ -2000,23 +2069,49 @@
2000 give other queries a chance to run. */2069 give other queries a chance to run. */
2001 if (i != 0) {2070 if (i != 0) {
2002 buf_pool_mutex_exit_all();2071 buf_pool_mutex_exit_all();
2003 rw_lock_x_unlock(&btr_search_latch);2072 btr_search_x_unlock_all();
2004 os_thread_yield();2073 os_thread_yield();
2005 rw_lock_x_lock(&btr_search_latch);2074 btr_search_x_lock_all();
2006 buf_pool_mutex_enter_all();2075 buf_pool_mutex_enter_all();
2007 }2076 }
20082077
2009 if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {2078 if (!ha_validate(btr_search_sys->hash_index[t], i,
2079 end_index)) {
2010 ok = FALSE;2080 ok = FALSE;
2011 }2081 }
2012 }2082 }
20132083
2014 buf_pool_mutex_exit_all();2084 buf_pool_mutex_exit_all();
2015 rw_lock_x_unlock(&btr_search_latch);
2016 if (UNIV_LIKELY_NULL(heap)) {2085 if (UNIV_LIKELY_NULL(heap)) {
2017 mem_heap_free(heap);2086 mem_heap_free(heap);
2018 }2087 }
20192088
2020 return(ok);2089 return(ok);
2021}2090}
2091
2092/********************************************************************//**
2093Validates the search system.
2094@return TRUE if ok */
2095UNIV_INTERN
2096ibool
2097btr_search_validate(void)
2098/*=====================*/
2099{
2100 ulint i;
2101 ibool ok = TRUE;
2102
2103 btr_search_x_lock_all();
2104
2105 for (i = 0; i < btr_search_index_num; i++) {
2106
2107 if (!btr_search_validate_one_table(i))
2108 ok = FALSE;
2109 }
2110
2111 btr_search_x_unlock_all();
2112
2113 return(ok);
2114}
2115
2116
2022#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */2117#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
20232118
=== modified file 'Percona-Server/storage/innobase/buf/buf0buf.cc'
--- Percona-Server/storage/innobase/buf/buf0buf.cc 2013-08-26 15:36:54 +0000
+++ Percona-Server/storage/innobase/buf/buf0buf.cc 2013-08-29 17:11:28 +0000
@@ -1013,6 +1013,7 @@
10131013
1014 block->check_index_page_at_flush = FALSE;1014 block->check_index_page_at_flush = FALSE;
1015 block->index = NULL;1015 block->index = NULL;
1016 block->btr_search_latch = NULL;
10161017
1017#ifdef UNIV_DEBUG1018#ifdef UNIV_DEBUG
1018 block->page.in_page_hash = FALSE;1019 block->page.in_page_hash = FALSE;
@@ -1484,7 +1485,7 @@
1484 ulint p;1485 ulint p;
14851486
1486#ifdef UNIV_SYNC_DEBUG1487#ifdef UNIV_SYNC_DEBUG
1487 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));1488 ut_ad(btr_search_own_all(RW_LOCK_EX));
1488#endif /* UNIV_SYNC_DEBUG */1489#endif /* UNIV_SYNC_DEBUG */
1489 ut_ad(!btr_search_enabled);1490 ut_ad(!btr_search_enabled);
14901491
@@ -2208,6 +2209,7 @@
2208{2209{
2209 block->check_index_page_at_flush = FALSE;2210 block->check_index_page_at_flush = FALSE;
2210 block->index = NULL;2211 block->index = NULL;
2212 block->btr_search_latch = NULL;
22112213
2212 block->n_hash_helps = 0;2214 block->n_hash_helps = 0;
2213 block->n_fields = 1;2215 block->n_fields = 1;
22142216
=== modified file 'Percona-Server/storage/innobase/dict/dict0dict.cc'
--- Percona-Server/storage/innobase/dict/dict0dict.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/storage/innobase/dict/dict0dict.cc 2013-08-29 17:11:28 +0000
@@ -1208,7 +1208,8 @@
12081208
1209 See also: dict_index_remove_from_cache_low() */1209 See also: dict_index_remove_from_cache_low() */
12101210
1211 if (btr_search_info_get_ref_count(info) > 0) {1211 if (btr_search_info_get_ref_count(info, index->id)
1212 > 0) {
1212 return(FALSE);1213 return(FALSE);
1213 }1214 }
1214 }1215 }
@@ -2483,7 +2484,8 @@
2483 zero. See also: dict_table_can_be_evicted() */2484 zero. See also: dict_table_can_be_evicted() */
24842485
2485 do {2486 do {
2486 ulint ref_count = btr_search_info_get_ref_count(info);2487 ulint ref_count = btr_search_info_get_ref_count(info,
2488 index->id);
24872489
2488 if (ref_count == 0) {2490 if (ref_count == 0) {
2489 break;2491 break;
24902492
=== modified file 'Percona-Server/storage/innobase/ha/ha0ha.cc'
--- Percona-Server/storage/innobase/ha/ha0ha.cc 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/ha/ha0ha.cc 2013-08-29 17:11:28 +0000
@@ -98,6 +98,33 @@
98 return(table);98 return(table);
99}99}
100100
101#ifdef UNIV_SYNC_DEBUG
102/*************************************************************//**
103Verifies that the specified hash table is a part of adaptive hash index and
104that its corresponding latch is X-latched by the current thread. */
105static
106bool
107ha_assert_btr_x_locked(
108/*===================*/
109 const hash_table_t* table) /*!<in: hash table to check */
110{
111 ulint i;
112
113 ut_ad(table->adaptive);
114
115 for (i = 0; i < btr_search_index_num; i++) {
116 if (btr_search_sys->hash_index[i] == table) {
117 break;
118 }
119 }
120
121 ut_ad(i < btr_search_index_num);
122 ut_ad(rw_lock_own(btr_search_latch_arr[i], RW_LOCK_EX));
123
124 return(true);
125}
126#endif /* UNIV_SYNC_DEBUG */
127
101/*************************************************************//**128/*************************************************************//**
102Empties a hash table and frees the memory heaps. */129Empties a hash table and frees the memory heaps. */
103UNIV_INTERN130UNIV_INTERN
@@ -112,8 +139,7 @@
112 ut_ad(table);139 ut_ad(table);
113 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);140 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
114#ifdef UNIV_SYNC_DEBUG141#ifdef UNIV_SYNC_DEBUG
115 ut_ad(!table->adaptive142 ut_ad(!table->adaptive || ha_assert_btr_x_locked(table));
116 || rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
117#endif /* UNIV_SYNC_DEBUG */143#endif /* UNIV_SYNC_DEBUG */
118144
119 /* Free the memory heaps. */145 /* Free the memory heaps. */
@@ -274,7 +300,7 @@
274 ut_ad(table);300 ut_ad(table);
275 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);301 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
276#ifdef UNIV_SYNC_DEBUG302#ifdef UNIV_SYNC_DEBUG
277 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));303 ut_ad(ha_assert_btr_x_locked(table));
278#endif /* UNIV_SYNC_DEBUG */304#endif /* UNIV_SYNC_DEBUG */
279 ut_ad(btr_search_enabled);305 ut_ad(btr_search_enabled);
280#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG306#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
@@ -313,7 +339,7 @@
313 ut_a(new_block->frame == page_align(new_data));339 ut_a(new_block->frame == page_align(new_data));
314#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */340#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
315#ifdef UNIV_SYNC_DEBUG341#ifdef UNIV_SYNC_DEBUG
316 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));342 ut_ad(ha_assert_btr_x_locked(table));
317#endif /* UNIV_SYNC_DEBUG */343#endif /* UNIV_SYNC_DEBUG */
318344
319 if (!btr_search_enabled) {345 if (!btr_search_enabled) {
320346
=== modified file 'Percona-Server/storage/innobase/handler/ha_innodb.cc'
--- Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-22 13:38:28 +0000
+++ Percona-Server/storage/innobase/handler/ha_innodb.cc 2013-08-29 17:11:28 +0000
@@ -16398,6 +16398,12 @@
16398 "Disable with --skip-innodb-adaptive-hash-index.",16398 "Disable with --skip-innodb-adaptive-hash-index.",
16399 NULL, innodb_adaptive_hash_index_update, TRUE);16399 NULL, innodb_adaptive_hash_index_update, TRUE);
1640016400
16401static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
16402 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
16403 "Number of InnoDB adaptive hash index partitions (default 1: disable "
16404 "partitioning)",
16405 NULL, NULL, 1, 1, sizeof(ulint) * 8, 0);
16406
16401static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,16407static MYSQL_SYSVAR_ULONG(replication_delay, srv_replication_delay,
16402 PLUGIN_VAR_RQCMDARG,16408 PLUGIN_VAR_RQCMDARG,
16403 "Replication thread delay (ms) on the slave server if "16409 "Replication thread delay (ms) on the slave server if "
@@ -17057,6 +17063,7 @@
17057 MYSQL_SYSVAR(stats_persistent_sample_pages),17063 MYSQL_SYSVAR(stats_persistent_sample_pages),
17058 MYSQL_SYSVAR(stats_auto_recalc),17064 MYSQL_SYSVAR(stats_auto_recalc),
17059 MYSQL_SYSVAR(adaptive_hash_index),17065 MYSQL_SYSVAR(adaptive_hash_index),
17066 MYSQL_SYSVAR(adaptive_hash_index_partitions),
17060 MYSQL_SYSVAR(stats_method),17067 MYSQL_SYSVAR(stats_method),
17061 MYSQL_SYSVAR(replication_delay),17068 MYSQL_SYSVAR(replication_delay),
17062 MYSQL_SYSVAR(status_file),17069 MYSQL_SYSVAR(status_file),
1706317070
=== modified file 'Percona-Server/storage/innobase/handler/xtradb_i_s.cc'
--- Percona-Server/storage/innobase/handler/xtradb_i_s.cc 2012-09-11 06:54:10 +0000
+++ Percona-Server/storage/innobase/handler/xtradb_i_s.cc 2013-08-29 17:11:28 +0000
@@ -329,34 +329,34 @@
329329
330 if (btr_search_sys)330 if (btr_search_sys)
331 {331 {
332 ulint btr_search_sys_subtotal= 0;332 ulint btr_search_sys_subtotal;
333333 const hash_table_t* hash_index_0
334 rw_lock_s_lock(&btr_search_latch);334 = btr_search_sys->hash_index[0];
335 if (btr_search_sys->hash_index->heap) {335
336 btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index->heap);336 if (hash_index_0->heap) {
337 } else {337 btr_search_sys_subtotal
338 btr_search_sys_subtotal = 0;338 = mem_heap_get_size(hash_index_0->heap);
339 for (unsigned int i=0;339 } else {
340 i < btr_search_sys->hash_index->n_sync_obj;340 for (ulint i = 0; i < hash_index_0->n_sync_obj; i++) {
341 i++) {341 btr_search_sys_subtotal
342 btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index->heaps[i]);342 += mem_heap_get_size(hash_index_0
343 }343 ->heaps[i]);
344 }344 }
345 rw_lock_s_unlock(&btr_search_latch);345 }
346346 btr_search_sys_subtotal *= btr_search_index_num;
347 OK(field_store_string(fields[INT_HASH_TABLES_NAME],347
348 "Adaptive hash index"));348 OK(field_store_string(fields[INT_HASH_TABLES_NAME],
349 OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],349 "Adaptive hash index"));
350 btr_search_sys_subtotal350 OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
351 + (btr_search_sys->hash_index->n_cells351 btr_search_sys_subtotal
352 * sizeof(hash_cell_t))));352 + (hash_index_0->n_cells
353 OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],353 * sizeof(hash_cell_t))));
354 (btr_search_sys->hash_index->n_cells354 OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
355 * sizeof(hash_cell_t))));355 (hash_index_0->n_cells
356 OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],356 * sizeof(hash_cell_t))));
357 btr_search_sys_subtotal));357 OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
358 OK(schema_table_store_record(thd, table));358 btr_search_sys_subtotal));
359359 OK(schema_table_store_record(thd, table));
360 }360 }
361361
362 {362 {
363363
=== modified file 'Percona-Server/storage/innobase/include/btr0sea.h'
--- Percona-Server/storage/innobase/include/btr0sea.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/btr0sea.h 2013-08-29 17:11:28 +0000
@@ -86,7 +86,8 @@
86ulint86ulint
87btr_search_info_get_ref_count(87btr_search_info_get_ref_count(
88/*==========================*/88/*==========================*/
89 btr_search_t* info); /*!< in: search info. */89 btr_search_t* info, /*!< in: search info. */
90 index_id_t key); /*!< in: id of the index owning search info */
90/*********************************************************************//**91/*********************************************************************//**
91Updates the search info. */92Updates the search info. */
92UNIV_INLINE93UNIV_INLINE
@@ -193,6 +194,55 @@
193# define btr_search_validate() TRUE194# define btr_search_validate() TRUE
194#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */195#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
195196
197/********************************************************************//**
198Returns the adaptive hash index table for a given index key.
199@return the adaptive hash index table for a given index key */
200UNIV_INLINE
201hash_table_t*
202btr_search_get_hash_index(
203/*======================*/
204 index_id_t key) /*!< in: index key */
205 __attribute__((pure,warn_unused_result));
206
207/********************************************************************//**
208Returns the adaptive hash index latch for a given index key.
209@return the adaptive hash index latch for a given index key */
210UNIV_INLINE
211rw_lock_t*
212btr_search_get_latch(
213/*=================*/
214 index_id_t key) /*!< in: index key */
215 __attribute__((pure,warn_unused_result));
216
217/********************************************************************//**
218Latches all adaptive hash index latches in exclusive mode. */
219UNIV_INLINE
220void
221btr_search_x_lock_all(void);
222/*========================*/
223
224/********************************************************************//**
225Unlatches all adaptive hash index latches in exclusive mode. */
226UNIV_INLINE
227void
228btr_search_x_unlock_all(void);
229/*==========================*/
230
231#ifdef UNIV_SYNC_DEBUG
232/******************************************************************//**
233Checks if the thread has locked all the adaptive hash index latches in the
234specified mode.
235
236@return true if all latches are locked by the current thread, false
237otherwise. */
238UNIV_INLINE
239bool
240btr_search_own_all(
241/*===============*/
242 ulint lock_type)
243 __attribute__((warn_unused_result));
244#endif /* UNIV_SYNC_DEBUG */
245
196/** The search info struct in an index */246/** The search info struct in an index */
197struct btr_search_t{247struct btr_search_t{
198 ulint ref_count; /*!< Number of blocks in this index tree248 ulint ref_count; /*!< Number of blocks in this index tree
@@ -250,7 +300,7 @@
250300
251/** The hash index system */301/** The hash index system */
252struct btr_search_sys_t{302struct btr_search_sys_t{
253 hash_table_t* hash_index; /*!< the adaptive hash index,303 hash_table_t** hash_index; /*!< the adaptive hash index,
254 mapping dtuple_fold values304 mapping dtuple_fold values
255 to rec_t pointers on index pages */305 to rec_t pointers on index pages */
256};306};
257307
=== modified file 'Percona-Server/storage/innobase/include/btr0sea.ic'
--- Percona-Server/storage/innobase/include/btr0sea.ic 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/btr0sea.ic 2013-08-29 17:11:28 +0000
@@ -60,8 +60,8 @@
60 btr_search_t* info;60 btr_search_t* info;
6161
62#ifdef UNIV_SYNC_DEBUG62#ifdef UNIV_SYNC_DEBUG
63 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));63 ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
64 ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));64 ut_ad(!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX));
65#endif /* UNIV_SYNC_DEBUG */65#endif /* UNIV_SYNC_DEBUG */
6666
67 info = btr_search_get_info(index);67 info = btr_search_get_info(index);
@@ -80,3 +80,80 @@
8080
81 btr_search_info_update_slow(info, cursor);81 btr_search_info_update_slow(info, cursor);
82}82}
83
84/********************************************************************//**
85Returns the adaptive hash index table for a given index key.
86@return the adaptive hash index table for a given index key */
87UNIV_INLINE
88hash_table_t*
89btr_search_get_hash_index(
90/*======================*/
91 index_id_t key) /*!< in: index key */
92{
93 return(btr_search_sys->hash_index[key % btr_search_index_num]);
94}
95
96/********************************************************************//**
97Returns the adaptive hash index latch for a given index key.
98@return the adaptive hash index latch for a given index key */
99UNIV_INLINE
100rw_lock_t*
101btr_search_get_latch(
102/*=================*/
103 index_id_t key) /*!< in: index key */
104{
105 return(btr_search_latch_arr[key % btr_search_index_num]);
106}
107
108/********************************************************************//**
109Latches all adaptive hash index latches in exclusive mode. */
110UNIV_INLINE
111void
112btr_search_x_lock_all(void)
113/*=======================*/
114{
115 ulint i;
116
117 for (i = 0; i < btr_search_index_num; i++) {
118 rw_lock_x_lock(btr_search_latch_arr[i]);
119 }
120}
121
122/********************************************************************//**
123Unlatches all adaptive hash index latches in exclusive mode. */
124UNIV_INLINE
125void
126btr_search_x_unlock_all(void)
127/*==========================*/
128{
129 ulint i;
130
131 for (i = 0; i < btr_search_index_num; i++) {
132 rw_lock_x_unlock(btr_search_latch_arr[i]);
133 }
134}
135
136#ifdef UNIV_SYNC_DEBUG
137/******************************************************************//**
138Checks if the thread has locked all the adaptive hash index latches in the
139specified mode.
140
141@return true if all latches are locked by the current thread, false
142otherwise. */
143UNIV_INLINE
144bool
145btr_search_own_all(
146/*===============*/
147 ulint lock_type)
148{
149 ulint i;
150
151 for (i = 0; i < btr_search_index_num; i++) {
152 if (!rw_lock_own(btr_search_latch_arr[i], lock_type)) {
153 return(false);
154 }
155 }
156
157 return(true);
158}
159#endif /* UNIV_SYNC_DEBUG */
83160
=== modified file 'Percona-Server/storage/innobase/include/btr0types.h'
--- Percona-Server/storage/innobase/include/btr0types.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/btr0types.h 2013-08-29 17:11:28 +0000
@@ -54,17 +54,17 @@
5454
55Bear in mind (3) and (4) when using the hash index.55Bear in mind (3) and (4) when using the hash index.
56*/56*/
57extern rw_lock_t* btr_search_latch_temp;57extern rw_lock_t** btr_search_latch_arr;
5858
59#endif /* UNIV_HOTBACKUP */59#endif /* UNIV_HOTBACKUP */
6060
61/** The latch protecting the adaptive search system */
62#define btr_search_latch (*btr_search_latch_temp)
63
64/** Flag: has the search system been enabled?61/** Flag: has the search system been enabled?
65Protected by btr_search_latch. */62Protected by btr_search_latch. */
66extern char btr_search_enabled;63extern char btr_search_enabled;
6764
65/** Number of adaptive hash index partitions */
66extern ulint btr_search_index_num;
67
68#ifdef UNIV_BLOB_DEBUG68#ifdef UNIV_BLOB_DEBUG
69# include "buf0types.h"69# include "buf0types.h"
70/** An index->blobs entry for keeping track of off-page column references */70/** An index->blobs entry for keeping track of off-page column references */
7171
=== modified file 'Percona-Server/storage/innobase/include/buf0buf.h'
--- Percona-Server/storage/innobase/include/buf0buf.h 2013-08-26 15:36:54 +0000
+++ Percona-Server/storage/innobase/include/buf0buf.h 2013-08-29 17:11:28 +0000
@@ -1700,6 +1700,8 @@
1700 complete, though: there may1700 complete, though: there may
1701 have been hash collisions,1701 have been hash collisions,
1702 record deletions, etc. */1702 record deletions, etc. */
1703 rw_lock_t* btr_search_latch;/*!< Adaptive hash index latch for the
1704 index this block belongs to or NULL */
1703 /* @} */1705 /* @} */
1704# ifdef UNIV_SYNC_DEBUG1706# ifdef UNIV_SYNC_DEBUG
1705 /** @name Debug fields */1707 /** @name Debug fields */
17061708
=== 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-29 17:11:28 +0000
@@ -28,6 +28,7 @@
28#include "buf0buf.h"28#include "buf0buf.h"
29#include "buf0dblwr.h"29#include "buf0dblwr.h"
30#include "fsp0types.h"30#include "fsp0types.h"
31#include "btr0types.h"
31#include "trx0sys.h"32#include "trx0sys.h"
3233
33/********************************************************//**34/********************************************************//**
3435
=== modified file 'Percona-Server/storage/innobase/include/que0que.h'
--- Percona-Server/storage/innobase/include/que0que.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/que0que.h 2013-08-29 17:11:28 +0000
@@ -29,6 +29,7 @@
29#include "univ.i"29#include "univ.i"
30#include "data0data.h"30#include "data0data.h"
31#include "dict0types.h"31#include "dict0types.h"
32#include "btr0sea.h"
32#include "trx0trx.h"33#include "trx0trx.h"
33#include "trx0roll.h"34#include "trx0roll.h"
34#include "srv0srv.h"35#include "srv0srv.h"
3536
=== modified file 'Percona-Server/storage/innobase/include/read0read.h'
--- Percona-Server/storage/innobase/include/read0read.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/read0read.h 2013-08-29 17:11:28 +0000
@@ -31,6 +31,7 @@
3131
32#include "ut0byte.h"32#include "ut0byte.h"
33#include "ut0lst.h"33#include "ut0lst.h"
34#include "btr0types.h"
34#include "trx0trx.h"35#include "trx0trx.h"
35#include "trx0sys.h"36#include "trx0sys.h"
36#include "read0types.h"37#include "read0types.h"
3738
=== modified file 'Percona-Server/storage/innobase/include/trx0roll.h'
--- Percona-Server/storage/innobase/include/trx0roll.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/trx0roll.h 2013-08-29 17:11:28 +0000
@@ -27,6 +27,7 @@
27#define trx0roll_h27#define trx0roll_h
2828
29#include "univ.i"29#include "univ.i"
30#include "btr0types.h"
30#include "trx0trx.h"31#include "trx0trx.h"
31#include "trx0types.h"32#include "trx0types.h"
32#include "mtr0mtr.h"33#include "mtr0mtr.h"
3334
=== modified file 'Percona-Server/storage/innobase/include/trx0trx.h'
--- Percona-Server/storage/innobase/include/trx0trx.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/trx0trx.h 2013-08-29 17:11:28 +0000
@@ -1136,10 +1136,7 @@
11361136
1137Bear in mind (3) and (4) when using the hash index.1137Bear in mind (3) and (4) when using the hash index.
1138*/1138*/
1139extern rw_lock_t* btr_search_latch_temp;1139extern rw_lock_t** btr_search_latch_arr;
1140
1141/** The latch protecting the adaptive search system */
1142#define btr_search_latch (*btr_search_latch_temp)
11431140
1144#ifndef UNIV_NONINL1141#ifndef UNIV_NONINL
1145#include "trx0trx.ic"1142#include "trx0trx.ic"
11461143
=== modified file 'Percona-Server/storage/innobase/include/trx0trx.ic'
--- Percona-Server/storage/innobase/include/trx0trx.ic 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/trx0trx.ic 2013-08-29 17:11:28 +0000
@@ -164,17 +164,21 @@
164}164}
165165
166/********************************************************************//**166/********************************************************************//**
167Releases the search latch if trx has reserved it. */167Releases the search latches if trx has reserved them. */
168UNIV_INLINE168UNIV_INLINE
169void169void
170trx_search_latch_release_if_reserved(170trx_search_latch_release_if_reserved(
171/*=================================*/171/*=================================*/
172 trx_t* trx) /*!< in: transaction */172 trx_t* trx) /*!< in: transaction */
173{173{
174 if (trx->has_search_latch) {174 ulint i;
175 rw_lock_s_unlock(&btr_search_latch);
176175
177 trx->has_search_latch = FALSE;176 for (i = 0; i < btr_search_index_num; i++) {
177 if (trx->has_search_latch & (1UL << i)) {
178 rw_lock_s_unlock(btr_search_latch_arr[i]);
179 }
178 }180 }
181
182 trx->has_search_latch = 0;
179}183}
180184
181185
=== modified file 'Percona-Server/storage/innobase/include/univ.i'
--- Percona-Server/storage/innobase/include/univ.i 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/include/univ.i 2013-08-29 17:11:28 +0000
@@ -179,7 +179,6 @@
179#define UNIV_COMPILE_TEST_FUNCS179#define UNIV_COMPILE_TEST_FUNCS
180*/180*/
181181
182#undef UNIV_SYNC_DEBUG
183#if defined HAVE_VALGRIND182#if defined HAVE_VALGRIND
184# define UNIV_DEBUG_VALGRIND183# define UNIV_DEBUG_VALGRIND
185#endif /* HAVE_VALGRIND */184#endif /* HAVE_VALGRIND */
186185
=== modified file 'Percona-Server/storage/innobase/os/os0file.cc'
--- Percona-Server/storage/innobase/os/os0file.cc 2013-08-21 07:19:25 +0000
+++ Percona-Server/storage/innobase/os/os0file.cc 2013-08-29 17:11:28 +0000
@@ -43,6 +43,7 @@
43#include "srv0start.h"43#include "srv0start.h"
44#include "fil0fil.h"44#include "fil0fil.h"
45#include "buf0buf.h"45#include "buf0buf.h"
46#include "btr0types.h"
46#include "trx0trx.h"47#include "trx0trx.h"
47#include "srv0mon.h"48#include "srv0mon.h"
48#ifndef UNIV_HOTBACKUP49#ifndef UNIV_HOTBACKUP
4950
=== modified file 'Percona-Server/storage/innobase/row/row0sel.cc'
--- Percona-Server/storage/innobase/row/row0sel.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/storage/innobase/row/row0sel.cc 2013-08-29 17:11:28 +0000
@@ -1233,7 +1233,8 @@
1233 ut_ad(!plan->must_get_clust);1233 ut_ad(!plan->must_get_clust);
1234#ifdef UNIV_SYNC_DEBUG1234#ifdef UNIV_SYNC_DEBUG
1235 if (search_latch_locked) {1235 if (search_latch_locked) {
1236 ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));1236 ut_ad(rw_lock_own(btr_search_get_latch(index->id),
1237 RW_LOCK_SHARED));
1237 }1238 }
1238#endif /* UNIV_SYNC_DEBUG */1239#endif /* UNIV_SYNC_DEBUG */
12391240
@@ -1405,10 +1406,11 @@
1405 && !plan->must_get_clust1406 && !plan->must_get_clust
1406 && !plan->table->big_rows) {1407 && !plan->table->big_rows) {
1407 if (!search_latch_locked) {1408 if (!search_latch_locked) {
1408 rw_lock_s_lock(&btr_search_latch);1409 rw_lock_s_lock(btr_search_get_latch(index->id));
14091410
1410 search_latch_locked = TRUE;1411 search_latch_locked = TRUE;
1411 } else if (rw_lock_get_writer(&btr_search_latch) == RW_LOCK_WAIT_EX) {1412 } else if (rw_lock_get_writer(btr_search_get_latch(index->id))
1413 == RW_LOCK_WAIT_EX) {
14121414
1413 /* There is an x-latch request waiting: release the1415 /* There is an x-latch request waiting: release the
1414 s-latch for a moment; as an s-latch here is often1416 s-latch for a moment; as an s-latch here is often
@@ -1417,8 +1419,8 @@
1417 from acquiring an s-latch for a long time, lowering1419 from acquiring an s-latch for a long time, lowering
1418 performance significantly in multiprocessors. */1420 performance significantly in multiprocessors. */
14191421
1420 rw_lock_s_unlock(&btr_search_latch);1422 rw_lock_s_unlock(btr_search_get_latch(index->id));
1421 rw_lock_s_lock(&btr_search_latch);1423 rw_lock_s_lock(btr_search_get_latch(index->id));
1422 }1424 }
14231425
1424 found_flag = row_sel_try_search_shortcut(node, plan,1426 found_flag = row_sel_try_search_shortcut(node, plan,
@@ -1443,7 +1445,7 @@
1443 }1445 }
14441446
1445 if (search_latch_locked) {1447 if (search_latch_locked) {
1446 rw_lock_s_unlock(&btr_search_latch);1448 rw_lock_s_unlock(btr_search_get_latch(index->id));
14471449
1448 search_latch_locked = FALSE;1450 search_latch_locked = FALSE;
1449 }1451 }
@@ -2019,7 +2021,7 @@
20192021
2020func_exit:2022func_exit:
2021 if (search_latch_locked) {2023 if (search_latch_locked) {
2022 rw_lock_s_unlock(&btr_search_latch);2024 rw_lock_s_unlock(btr_search_get_latch(index->id));
2023 }2025 }
2024 if (UNIV_LIKELY_NULL(heap)) {2026 if (UNIV_LIKELY_NULL(heap)) {
2025 mem_heap_free(heap);2027 mem_heap_free(heap);
@@ -3597,6 +3599,47 @@
3597}3599}
35983600
3599/********************************************************************//**3601/********************************************************************//**
3602Acquires an S latch for the adaptive hash index for a given index tree if is
3603not acquired already. If the current transaction already owns a latch with
3604a higher index in the latch array, release all the already-held S latches
3605and reacquire them together with the desired latch to honor the latching
3606order. */
3607static
3608void
3609trx_search_latch_lock(
3610/*==================*/
3611 trx_t* trx, /*!< in: latching transcation */
3612 ulint index_id) /*!< in: index to latch AHI for */
3613{
3614 ulint latch_mask = 1UL << (index_id % btr_search_index_num);
3615
3616 if (!(trx->has_search_latch & latch_mask)) {
3617
3618 if (trx->has_search_latch < latch_mask) {
3619
3620 rw_lock_s_lock(btr_search_get_latch(index_id));
3621 trx->has_search_latch |= latch_mask;
3622 } else {
3623
3624 ulint taken_latches = trx->has_search_latch;
3625
3626 trx_search_latch_release_if_reserved(trx);
3627
3628 trx->has_search_latch = taken_latches | latch_mask;
3629
3630 for (ulint i = 0; i < btr_search_index_num; i++) {
3631 if (trx->has_search_latch & (1UL << i)) {
3632
3633 rw_lock_s_lock(
3634 btr_search_latch_arr[i]);
3635 }
3636 }
3637 }
3638 }
3639}
3640
3641
3642/********************************************************************//**
3600Searches for rows in the database. This is used in the interface to3643Searches for rows in the database. This is used in the interface to
3601MySQL. This function opens a cursor, and also implements fetch next3644MySQL. This function opens a cursor, and also implements fetch next
3602and fetch prev. NOTE that if we do a search with a full key value3645and fetch prev. NOTE that if we do a search with a full key value
@@ -3658,6 +3701,7 @@
3658 ulint* offsets = offsets_;3701 ulint* offsets = offsets_;
3659 ibool table_lock_waited = FALSE;3702 ibool table_lock_waited = FALSE;
3660 byte* next_buf = 0;3703 byte* next_buf = 0;
3704 bool should_release;
36613705
3662 rec_offs_init(offsets_);3706 rec_offs_init(offsets_);
36633707
@@ -3733,19 +3777,28 @@
3733 (ulong) trx->mysql_n_tables_locked);3777 (ulong) trx->mysql_n_tables_locked);
3734#endif3778#endif
3735 /*-------------------------------------------------------------*/3779 /*-------------------------------------------------------------*/
3736 /* PHASE 0: Release a possible s-latch we are holding on the3780 /* PHASE 0: Release possible latches we are holding on the
3737 adaptive hash index latch if there is someone waiting behind */3781 adaptive hash index latches if there is someone waiting behind */
37383782
3739 if (UNIV_UNLIKELY(rw_lock_get_writer(&btr_search_latch) != RW_LOCK_NOT_LOCKED)3783 should_release = false;
3740 && trx->has_search_latch) {3784 for (ulint i = 0; i < btr_search_index_num; i++) {
3785 /* we should check all latches (fix Bug#791030) */
3786 if (UNIV_UNLIKELY(rw_lock_get_writer(btr_search_latch_arr[i])
3787 != RW_LOCK_NOT_LOCKED)) {
3788 should_release = true;
3789 break;
3790 }
3791 }
3792
3793 if (UNIV_UNLIKELY(should_release)) {
37413794
3742 /* There is an x-latch request on the adaptive hash index:3795 /* There is an x-latch request on the adaptive hash index:
3743 release the s-latch to reduce starvation and wait for3796 release the s-latch to reduce starvation and wait for
3744 BTR_SEA_TIMEOUT rounds before trying to keep it again over3797 BTR_SEA_TIMEOUT rounds before trying to keep it again over
3745 calls from MySQL */3798 calls from MySQL */
37463799
3747 rw_lock_s_unlock(&btr_search_latch);3800 /* We should release all s-latches (fix Bug#791030) */
3748 trx->has_search_latch = FALSE;3801 trx_search_latch_release_if_reserved(trx);
37493802
3750 trx->search_latch_timeout = BTR_SEA_TIMEOUT;3803 trx->search_latch_timeout = BTR_SEA_TIMEOUT;
3751 }3804 }
@@ -3896,10 +3949,7 @@
3896 hash index semaphore! */3949 hash index semaphore! */
38973950
3898#ifndef UNIV_SEARCH_DEBUG3951#ifndef UNIV_SEARCH_DEBUG
3899 if (!trx->has_search_latch) {3952 trx_search_latch_lock(trx, index->id);
3900 rw_lock_s_lock(&btr_search_latch);
3901 trx->has_search_latch = TRUE;
3902 }
3903#endif3953#endif
3904 switch (row_sel_try_search_shortcut_for_mysql(3954 switch (row_sel_try_search_shortcut_for_mysql(
3905 &rec, prebuilt, &offsets, &heap,3955 &rec, prebuilt, &offsets, &heap,
@@ -3969,8 +4019,8 @@
39694019
3970 trx->search_latch_timeout--;4020 trx->search_latch_timeout--;
39714021
3972 rw_lock_s_unlock(&btr_search_latch);4022 trx_search_latch_release_if_reserved(
3973 trx->has_search_latch = FALSE;4023 trx);
3974 }4024 }
39754025
3976 /* NOTE that we do NOT store the cursor4026 /* NOTE that we do NOT store the cursor
@@ -3992,10 +4042,7 @@
3992 /*-------------------------------------------------------------*/4042 /*-------------------------------------------------------------*/
3993 /* PHASE 3: Open or restore index cursor position */4043 /* PHASE 3: Open or restore index cursor position */
39944044
3995 if (trx->has_search_latch) {4045 trx_search_latch_release_if_reserved(trx);
3996 rw_lock_s_unlock(&btr_search_latch);
3997 trx->has_search_latch = FALSE;
3998 }
39994046
4000 /* The state of a running trx can only be changed by the4047 /* The state of a running trx can only be changed by the
4001 thread that is currently serving the transaction. Because we4048 thread that is currently serving the transaction. Because we
40024049
=== modified file 'Percona-Server/storage/innobase/srv/srv0conc.cc'
--- Percona-Server/storage/innobase/srv/srv0conc.cc 2013-05-10 08:51:53 +0000
+++ Percona-Server/storage/innobase/srv/srv0conc.cc 2013-08-29 17:11:28 +0000
@@ -39,6 +39,7 @@
3939
40#include "srv0srv.h"40#include "srv0srv.h"
41#include "sync0sync.h"41#include "sync0sync.h"
42#include "btr0types.h"
42#include "trx0trx.h"43#include "trx0trx.h"
4344
44#include "mysql/plugin.h"45#include "mysql/plugin.h"
4546
=== modified file 'Percona-Server/storage/innobase/srv/srv0srv.cc'
--- Percona-Server/storage/innobase/srv/srv0srv.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/storage/innobase/srv/srv0srv.cc 2013-08-29 17:11:28 +0000
@@ -1308,17 +1308,20 @@
1308 os_atomic_increment_lint(&srv_read_views_memory, 0));1308 os_atomic_increment_lint(&srv_read_views_memory, 0));
13091309
1310 /* Calculate reserved memories */1310 /* Calculate reserved memories */
1311 if (btr_search_sys && btr_search_sys->hash_index->heap) {1311 if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1312 btr_search_sys_subtotal1312 btr_search_sys_subtotal
1313 = mem_heap_get_size(btr_search_sys->hash_index->heap);1313 = mem_heap_get_size(btr_search_sys->hash_index[0]
1314 ->heap);
1314 } else {1315 } else {
1315 btr_search_sys_subtotal = 0;1316 btr_search_sys_subtotal = 0;
1316 for (i=0; i < btr_search_sys->hash_index->n_sync_obj; i++) {1317 for (i=0; i < btr_search_sys->hash_index[0]->n_sync_obj; i++) {
1317 btr_search_sys_subtotal1318 btr_search_sys_subtotal
1318 += mem_heap_get_size(1319 += mem_heap_get_size(
1319 btr_search_sys->hash_index->heaps[i]);1320 btr_search_sys->hash_index[0]
1321 ->heaps[i]);
1320 }1322 }
1321 }1323 }
1324 btr_search_sys_subtotal *= btr_search_index_num;
13221325
1323 lock_sys_subtotal = 0;1326 lock_sys_subtotal = 0;
1324 if (trx_sys) {1327 if (trx_sys) {
@@ -1347,13 +1350,15 @@
1347 " Recovery system %lu \t(%lu + " ULINTPF ")\n",1350 " Recovery system %lu \t(%lu + " ULINTPF ")\n",
13481351
1349 (ulong) (btr_search_sys1352 (ulong) (btr_search_sys
1350 ? (btr_search_sys->hash_index->n_cells1353 ? (btr_search_sys->hash_index[0]->n_cells
1351 * sizeof(hash_cell_t))1354 * sizeof(hash_cell_t)
1355 * btr_search_index_num)
1352 : 0)1356 : 0)
1353 + btr_search_sys_subtotal,1357 + btr_search_sys_subtotal,
1354 (ulong) (btr_search_sys1358 (ulong) (btr_search_sys
1355 ? (btr_search_sys->hash_index->n_cells1359 ? (btr_search_sys->hash_index[0]->n_cells
1356 * sizeof(hash_cell_t))1360 * sizeof(hash_cell_t)
1361 * btr_search_index_num)
1357 : 0),1362 : 0),
1358 btr_search_sys_subtotal,1363 btr_search_sys_subtotal,
13591364
@@ -1504,21 +1509,23 @@
1504 buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);1509 buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
1505 buf_get_total_list_size_in_bytes(&buf_pools_list_size);1510 buf_get_total_list_size_in_bytes(&buf_pools_list_size);
15061511
1507 if (btr_search_sys && btr_search_sys->hash_index->heap) {1512 if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
1508 mem_adaptive_hash1513 mem_adaptive_hash
1509 = mem_heap_get_size(btr_search_sys->hash_index->heap);1514 = mem_heap_get_size(btr_search_sys
1515 ->hash_index[0]->heap);
1510 } else {1516 } else {
1511 mem_adaptive_hash = 0;1517 mem_adaptive_hash = 0;
1512 for (i=0; i < btr_search_sys->hash_index->n_sync_obj; i++) {1518 for (i=0; i < btr_search_sys->hash_index[0]->n_sync_obj; i++) {
1513 mem_adaptive_hash1519 mem_adaptive_hash
1514 += mem_heap_get_size1520 += mem_heap_get_size
1515 (btr_search_sys->hash_index->heaps[i]);1521 (btr_search_sys->hash_index[0]->heaps[i]);
1516 }1522 }
1517 }1523 }
1518 if (btr_search_sys) {1524 if (btr_search_sys) {
1519 mem_adaptive_hash += (btr_search_sys->hash_index->n_cells1525 mem_adaptive_hash += (btr_search_sys->hash_index[0]->n_cells
1520 * sizeof(hash_cell_t));1526 * sizeof(hash_cell_t));
1521 }1527 }
1528 mem_adaptive_hash *= btr_search_index_num;
15221529
1523 mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells1530 mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
1524 + dict_sys->table_id_hash->n_cells1531 + dict_sys->table_id_hash->n_cells
15251532
=== modified file 'Percona-Server/storage/innobase/sync/sync0sync.cc'
--- Percona-Server/storage/innobase/sync/sync0sync.cc 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/sync/sync0sync.cc 2013-08-29 17:11:28 +0000
@@ -38,6 +38,7 @@
38#include "sync0rw.h"38#include "sync0rw.h"
39#include "buf0buf.h"39#include "buf0buf.h"
40#include "srv0srv.h"40#include "srv0srv.h"
41#include "btr0types.h"
41#include "buf0types.h"42#include "buf0types.h"
42#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */43#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
43#ifdef UNIV_SYNC_DEBUG44#ifdef UNIV_SYNC_DEBUG
@@ -1149,7 +1150,6 @@
1149 case SYNC_ANY_LATCH:1150 case SYNC_ANY_LATCH:
1150 case SYNC_FILE_FORMAT_TAG:1151 case SYNC_FILE_FORMAT_TAG:
1151 case SYNC_DOUBLEWRITE:1152 case SYNC_DOUBLEWRITE:
1152 case SYNC_SEARCH_SYS:
1153 case SYNC_THREADS:1153 case SYNC_THREADS:
1154 case SYNC_LOCK_SYS:1154 case SYNC_LOCK_SYS:
1155 case SYNC_LOCK_WAIT_SYS:1155 case SYNC_LOCK_WAIT_SYS:
@@ -1182,6 +1182,24 @@
1182 ut_a(sync_thread_levels_contain(array, SYNC_LOCK_SYS));1182 ut_a(sync_thread_levels_contain(array, SYNC_LOCK_SYS));
1183 }1183 }
1184 break;1184 break;
1185 case SYNC_SEARCH_SYS: {
1186 /* Verify the lock order inside the split btr_search_latch
1187 array */
1188 bool found_current = false;
1189 for (ulint i = 0; i < btr_search_index_num; i++) {
1190 if (btr_search_latch_arr[i] == latch) {
1191 found_current = true;
1192 } else if (found_current) {
1193 ut_ad(!rw_lock_own(btr_search_latch_arr[i],
1194 RW_LOCK_SHARED));
1195 ut_ad(!rw_lock_own(btr_search_latch_arr[i],
1196 RW_LOCK_EX));
1197 }
1198 }
1199 ut_ad(found_current);
1200
1201 /* fallthrough */
1202 }
1185 case SYNC_BUF_FLUSH_LIST:1203 case SYNC_BUF_FLUSH_LIST:
1186 case SYNC_BUF_POOL:1204 case SYNC_BUF_POOL:
1187 /* We can have multiple mutexes of this type therefore we1205 /* We can have multiple mutexes of this type therefore we
11881206
=== modified file 'Percona-Server/storage/innobase/trx/trx0trx.cc'
--- Percona-Server/storage/innobase/trx/trx0trx.cc 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/trx/trx0trx.cc 2013-08-29 17:11:28 +0000
@@ -23,6 +23,7 @@
23Created 3/26/1996 Heikki Tuuri23Created 3/26/1996 Heikki Tuuri
24*******************************************************/24*******************************************************/
2525
26#include "btr0types.h"
26#include "trx0trx.h"27#include "trx0trx.h"
2728
28#ifdef UNIV_NONINL29#ifdef UNIV_NONINL
2930
=== modified file 'Percona-Server/storage/innobase/ut/ut0ut.cc'
--- Percona-Server/storage/innobase/ut/ut0ut.cc 2013-08-06 15:16:34 +0000
+++ Percona-Server/storage/innobase/ut/ut0ut.cc 2013-08-29 17:11:28 +0000
@@ -39,6 +39,7 @@
39#include <ctype.h>39#include <ctype.h>
4040
41#ifndef UNIV_HOTBACKUP41#ifndef UNIV_HOTBACKUP
42# include "btr0types.h"
42# include "trx0trx.h"43# include "trx0trx.h"
43# include "ha_prototypes.h"44# include "ha_prototypes.h"
44# include "mysql_com.h" /* NAME_LEN */45# include "mysql_com.h" /* NAME_LEN */

Subscribers

People subscribed via source and target branches