Commit 7e4d89c9 authored by Igor Babaev's avatar Igor Babaev

WL#86: Partitioned key cache for MyISAM.

This is the base patch for the task.
parent abb87914
This diff is collapsed.
...@@ -69,6 +69,7 @@ INNODB_LOCK_WAITS ...@@ -69,6 +69,7 @@ INNODB_LOCK_WAITS
INNODB_RSEG INNODB_RSEG
INNODB_TABLE_STATS INNODB_TABLE_STATS
INNODB_TRX INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE KEY_COLUMN_USAGE
PARTITIONS PARTITIONS
PLUGINS PLUGINS
......
...@@ -13,6 +13,7 @@ FILES ...@@ -13,6 +13,7 @@ FILES
GLOBAL_STATUS GLOBAL_STATUS
GLOBAL_VARIABLES GLOBAL_VARIABLES
INDEX_STATISTICS INDEX_STATISTICS
KEY_CACHES
KEY_COLUMN_USAGE KEY_COLUMN_USAGE
PARTITIONS PARTITIONS
PLUGINS PLUGINS
...@@ -76,6 +77,7 @@ FILES TABLE_SCHEMA ...@@ -76,6 +77,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME PLUGINS PLUGIN_NAME
...@@ -139,6 +141,7 @@ FILES TABLE_SCHEMA ...@@ -139,6 +141,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME PLUGINS PLUGIN_NAME
...@@ -221,6 +224,7 @@ INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1 ...@@ -221,6 +224,7 @@ INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
INNODB_RSEG information_schema.INNODB_RSEG 1 INNODB_RSEG information_schema.INNODB_RSEG 1
INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1 INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1
INNODB_TRX information_schema.INNODB_TRX 1 INNODB_TRX information_schema.INNODB_TRX 1
KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1 KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1 PARTITIONS information_schema.PARTITIONS 1
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1 PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
...@@ -259,6 +263,7 @@ Database: information_schema ...@@ -259,6 +263,7 @@ Database: information_schema
| GLOBAL_STATUS | | GLOBAL_STATUS |
| GLOBAL_VARIABLES | | GLOBAL_VARIABLES |
| INDEX_STATISTICS | | INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE | | KEY_COLUMN_USAGE |
| PARTITIONS | | PARTITIONS |
| PLUGINS | | PLUGINS |
...@@ -312,6 +317,7 @@ Database: INFORMATION_SCHEMA ...@@ -312,6 +317,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS | | GLOBAL_STATUS |
| GLOBAL_VARIABLES | | GLOBAL_VARIABLES |
| INDEX_STATISTICS | | INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE | | KEY_COLUMN_USAGE |
| PARTITIONS | | PARTITIONS |
| PLUGINS | | PLUGINS |
...@@ -357,5 +363,5 @@ Wildcard: inf_rmation_schema ...@@ -357,5 +363,5 @@ Wildcard: inf_rmation_schema
+--------------------+ +--------------------+
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA; SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*) table_schema count(*)
information_schema 48 information_schema 49
mysql 22 mysql 22
This diff is collapsed.
This diff is collapsed.
# #
# Test of multiple key caches # Test of multiple key caches, simple an partitioned
# #
--disable_warnings --disable_warnings
drop table if exists t1, t2, t3; drop table if exists t1, t2, t3;
--enable_warnings --enable_warnings
SET @save_key_buffer=@@key_buffer_size; SET @save_key_buffer_size=@@key_buffer_size;
SET @save_key_cache_block_size=@@key_cache_block_size;
SET @save_key_cache_partitions=@@key_cache_partitions;
SELECT @@key_buffer_size, @@small.key_buffer_size; SELECT @@key_buffer_size, @@small.key_buffer_size;
...@@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size; ...@@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size;
SELECT @@small.key_buffer_size; SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size; SELECT @@medium.key_buffer_size;
SET @@global.key_buffer_size=@save_key_buffer; SET @@global.key_buffer_size=@save_key_buffer_size;
# #
# Errors # Errors
...@@ -247,3 +249,263 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; ...@@ -247,3 +249,263 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1; DROP TABLE t1;
# End of 4.1 tests # End of 4.1 tests
#
# Test cases for partitioned key caches
#
# Test usage of the KEY_CACHE table from information schema
# for a simple key cache
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_block_size=@save_key_cache_block_size;
select @@key_buffer_size;
select @@key_cache_block_size;
select @@key_cache_partitions;
create table t1 (
p int not null auto_increment primary key,
a char(10));
create table t2 (
p int not null auto_increment primary key,
i int, a char(10), key k1(i), key k2(a));
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t2 where a='zzzz';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
# For the key cache with 2 partitions execute the same sequence of
# statements as for the simple cache above.
# The statistical information on the number of i/o requests and
# the number of is expected to be the same.
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
# Check that we can work with one partition with the same results
set global key_cache_partitions=1;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
flush tables; flush status;
--replace_column 7 #
select * from information_schema.key_caches;
# Switch back to 2 partitions
set global key_buffer_size=32*1024;
select @@key_buffer_size;
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_column 7 #
select * from information_schema.key_caches;
# Add more rows to tables t1 and t2
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
--replace_column 6 # 7 # 10 #
select * from information_schema.key_caches;
select * from t1 where p between 1010 and 1020 ;
select * from t2 where p between 1010 and 1020 ;
--replace_column 6 # 7 # 10 #
select * from information_schema.key_caches;
flush tables; flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
# Now test how we can work with 7 partitions
set global keycache1.key_buffer_size=256*1024;
select @@keycache1.key_buffer_size;
set global keycache1.key_cache_partitions=7;
select @@keycache1.key_cache_partitions;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t1 key (`primary`) in keycache1;
explain select p from t1 where p between 1010 and 1020;
select p from t1 where p between 1010 and 1020;
explain select i from t2 where p between 1010 and 1020;
select i from t2 where p between 1010 and 1020;
explain select count(*) from t1, t2 where t1.p = t2.i;
select count(*) from t1, t2 where t1.p = t2.i;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t2 in keycache1;
update t2 set p=p+3000, i=2 where a='qqqq';
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "keycache2";
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t2 in keycache1;
update t2 set p=p+5000 where a='zzzz';
select * from t2 where p between 1010 and 1020;
explain select p from t2 where p between 1010 and 1020;
select p from t2 where p between 1010 and 1020;
explain select i from t2 where a='yyyy' and i=3;
select i from t2 where a='yyyy' and i=3;
explain select a from t2 where a='yyyy' and i=3;
select a from t2 where a='yyyy' and i=3 ;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=64*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=2*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=128*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
drop table t1,t2;
set global keycache1.key_buffer_size=0;
set global keycache2.key_buffer_size=0;
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_partitions=@save_key_cache_partitions;
#End of 5.1 tests
#
# Run select.test partitioned default key cache (with 7 partitions)
# (see setting the number of partitions in select_pkecache-master.opt)
# The result is expected the same as for select.test
#
--source t/select.test
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3828,11 +3828,13 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) ...@@ -3828,11 +3828,13 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
uint tmp_block_size= (uint) key_cache->param_block_size; uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit; uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold; uint age_threshold= key_cache->param_age_threshold;
uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!init_key_cache(key_cache, DBUG_RETURN(!init_key_cache(key_cache,
tmp_block_size, tmp_block_size,
tmp_buff_size, tmp_buff_size,
division_limit, age_threshold)); division_limit, age_threshold,
partitions));
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -3862,10 +3864,12 @@ int ha_resize_key_cache(KEY_CACHE *key_cache) ...@@ -3862,10 +3864,12 @@ int ha_resize_key_cache(KEY_CACHE *key_cache)
/** /**
Change parameters for key cache (like size) Change parameters for key cache (like division_limit)
*/ */
int ha_change_key_cache_param(KEY_CACHE *key_cache) int ha_change_key_cache_param(KEY_CACHE *key_cache)
{ {
DBUG_ENTER("ha_change_key_cache_param");
if (key_cache->key_cache_inited) if (key_cache->key_cache_inited)
{ {
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
...@@ -3874,9 +3878,35 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache) ...@@ -3874,9 +3878,35 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache)
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
change_key_cache_param(key_cache, division_limit, age_threshold); change_key_cache_param(key_cache, division_limit, age_threshold);
} }
return 0; DBUG_RETURN(0);
} }
/**
Repartition key cache
*/
int ha_repartition_key_cache(KEY_CACHE *key_cache)
{
DBUG_ENTER("ha_repartition_key_cache");
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
long tmp_block_size= (long) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!repartition_key_cache(key_cache, tmp_block_size,
tmp_buff_size,
division_limit, age_threshold,
partitions));
}
DBUG_RETURN(0);
}
/** /**
Free memory allocated by a key cache. Free memory allocated by a key cache.
*/ */
......
...@@ -2188,6 +2188,7 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name); ...@@ -2188,6 +2188,7 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache); extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache); int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache); int ha_change_key_cache_param(KEY_CACHE *key_cache);
int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
int ha_end_key_cache(KEY_CACHE *key_cache); int ha_end_key_cache(KEY_CACHE *key_cache);
......
...@@ -5825,6 +5825,7 @@ enum options_mysqld ...@@ -5825,6 +5825,7 @@ enum options_mysqld
OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE, OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE, OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD, OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_PARTITIONS,
OPT_LONG_QUERY_TIME, OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET, OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE, OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
...@@ -6915,6 +6916,12 @@ log and this option does nothing anymore.", ...@@ -6915,6 +6916,12 @@ log and this option does nothing anymore.",
(uchar**) 0, (uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0}, 1, 100, 0, 1, 0},
{"key_cache_partitions", OPT_KEY_CACHE_PARTITIONS,
"The number of partitions in key cache",
(uchar**) &dflt_key_cache_var.param_partitions,
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, DEFAULT_KEY_CACHE_PARTITIONS,
0, MAX_KEY_CACHE_PARTITIONS, 0, 1, 0},
{"log-slow-filter", OPT_LOG_SLOW_FILTER, {"log-slow-filter", OPT_LOG_SLOW_FILTER,
"Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [admin, filesort, filesort_on_disk, full_join, full_scan, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk]. Sets log-slow-admin-command to ON", "Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [admin, filesort, filesort_on_disk, full_join, full_scan, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk]. Sets log-slow-admin-command to ON",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, QPLAN_ALWAYS_SET, 0, 0}, 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, QPLAN_ALWAYS_SET, 0, 0},
...@@ -8837,6 +8844,7 @@ mysql_getopt_value(const char *keyname, uint key_length, ...@@ -8837,6 +8844,7 @@ mysql_getopt_value(const char *keyname, uint key_length,
case OPT_KEY_CACHE_BLOCK_SIZE: case OPT_KEY_CACHE_BLOCK_SIZE:
case OPT_KEY_CACHE_DIVISION_LIMIT: case OPT_KEY_CACHE_DIVISION_LIMIT:
case OPT_KEY_CACHE_AGE_THRESHOLD: case OPT_KEY_CACHE_AGE_THRESHOLD:
case OPT_KEY_CACHE_PARTITIONS:
{ {
KEY_CACHE *key_cache; KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length))) if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
...@@ -8854,6 +8862,8 @@ mysql_getopt_value(const char *keyname, uint key_length, ...@@ -8854,6 +8862,8 @@ mysql_getopt_value(const char *keyname, uint key_length,
return (uchar**) &key_cache->param_division_limit; return (uchar**) &key_cache->param_division_limit;
case OPT_KEY_CACHE_AGE_THRESHOLD: case OPT_KEY_CACHE_AGE_THRESHOLD:
return (uchar**) &key_cache->param_age_threshold; return (uchar**) &key_cache->param_age_threshold;
case OPT_KEY_CACHE_PARTITIONS:
return (uchar**) &key_cache->param_partitions;
} }
} }
} }
......
...@@ -317,15 +317,18 @@ static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout", ...@@ -317,15 +317,18 @@ static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout",
static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size", static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
&SV::join_buff_size); &SV::join_buff_size);
static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size"); static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size");
static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size", static sys_var_key_cache_long sys_key_cache_block_size(&vars,
offsetof(KEY_CACHE, "key_cache_block_size",
param_block_size)); offsetof(KEY_CACHE,param_block_size));
static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit", static sys_var_key_cache_long sys_key_cache_division_limit(&vars,
offsetof(KEY_CACHE, "key_cache_division_limit",
param_division_limit)); offsetof(KEY_CACHE, param_division_limit));
static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold", static sys_var_key_cache_long sys_key_cache_age_threshold(&vars,
offsetof(KEY_CACHE, "key_cache_age_threshold",
param_age_threshold)); offsetof(KEY_CACHE, param_age_threshold));
static sys_var_key_cache_long sys_key_cache_partitions(&vars,
"key_cache_partitions",
offsetof(KEY_CACHE, param_partitions));
static sys_var_const sys_language(&vars, "language", static sys_var_const sys_language(&vars, "language",
OPT_GLOBAL, SHOW_CHAR, OPT_GLOBAL, SHOW_CHAR,
(uchar*) language); (uchar*) language);
...@@ -2540,7 +2543,21 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) ...@@ -2540,7 +2543,21 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
error= (bool) (ha_resize_key_cache(key_cache)); switch (offset) {
case offsetof(KEY_CACHE, param_block_size):
error= (bool) (ha_resize_key_cache(key_cache));
break;
case offsetof(KEY_CACHE, param_division_limit):
case offsetof(KEY_CACHE, param_age_threshold):
error= (bool) (ha_change_key_cache_param(key_cache));
break;
case offsetof(KEY_CACHE, param_partitions):
error= (bool) (ha_repartition_key_cache(key_cache));
break;
}
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0; key_cache->in_init= 0;
...@@ -4142,6 +4159,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length) ...@@ -4142,6 +4159,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length)
key_cache->param_block_size= dflt_key_cache_var.param_block_size; key_cache->param_block_size= dflt_key_cache_var.param_block_size;
key_cache->param_division_limit= dflt_key_cache_var.param_division_limit; key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold; key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
key_cache->param_partitions= dflt_key_cache_var.param_partitions;
} }
} }
DBUG_RETURN(key_cache); DBUG_RETURN(key_cache);
......
...@@ -1427,6 +1427,7 @@ public: ...@@ -1427,6 +1427,7 @@ public:
my_free((uchar*) name, MYF(0)); my_free((uchar*) name, MYF(0));
} }
friend bool process_key_caches(process_key_cache_t func); friend bool process_key_caches(process_key_cache_t func);
friend int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond);
friend void delete_elements(I_List<NAMED_LIST> *list, friend void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char*, uchar*)); void (*free_element)(const char*, uchar*));
}; };
......
...@@ -2220,6 +2220,31 @@ void remove_status_vars(SHOW_VAR *list) ...@@ -2220,6 +2220,31 @@ void remove_status_vars(SHOW_VAR *list)
} }
static void update_key_cache_stat_var(KEY_CACHE *key_cache, size_t ofs)
{
uint var_no;
switch (ofs) {
case offsetof(KEY_CACHE, blocks_used):
case offsetof(KEY_CACHE, blocks_unused):
case offsetof(KEY_CACHE, global_blocks_changed):
var_no= (ofs-offsetof(KEY_CACHE, blocks_used))/sizeof(ulong);
*(ulong *)((char *) key_cache + ofs)=
(ulong) get_key_cache_stat_value(key_cache, var_no);
break;
case offsetof(KEY_CACHE, global_cache_r_requests):
case offsetof(KEY_CACHE, global_cache_read):
case offsetof(KEY_CACHE, global_cache_w_requests):
case offsetof(KEY_CACHE, global_cache_write):
var_no= 3+(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
sizeof(ulonglong);
*(ulonglong *)((char *) key_cache + ofs)=
get_key_cache_stat_value(key_cache, var_no);
break;
}
}
static bool show_status_array(THD *thd, const char *wild, static bool show_status_array(THD *thd, const char *wild,
SHOW_VAR *variables, SHOW_VAR *variables,
enum enum_var_type value_type, enum enum_var_type value_type,
...@@ -2352,10 +2377,12 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2352,10 +2377,12 @@ static bool show_status_array(THD *thd, const char *wild,
break; break;
} }
case SHOW_KEY_CACHE_LONG: case SHOW_KEY_CACHE_LONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value; value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10); end= int10_to_str(*(long*) value, buff, 10);
break; break;
case SHOW_KEY_CACHE_LONGLONG: case SHOW_KEY_CACHE_LONGLONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value; value= (char*) dflt_key_cache + (ulong)value;
end= longlong10_to_str(*(longlong*) value, buff, 10); end= longlong10_to_str(*(longlong*) value, buff, 10);
break; break;
...@@ -6611,6 +6638,90 @@ int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6611,6 +6638,90 @@ int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
} }
static
int store_key_cache_table_record(THD *thd, TABLE *table,
const char *name, uint name_length,
KEY_CACHE *key_cache,
uint partitions, uint partition_no)
{
KEY_CACHE_STATISTICS key_cache_stats;
uint err;
DBUG_ENTER("store_key_cache_table_record");
get_key_cache_statistics(key_cache, partition_no, &key_cache_stats);
if (key_cache_stats.mem_size == 0)
DBUG_RETURN(0);
restore_record(table, s->default_values);
table->field[0]->store(name, name_length, system_charset_info);
if (partitions == 0)
table->field[1]->set_null();
else
{
table->field[1]->set_notnull();
table->field[1]->store((long) partitions, TRUE);
}
if (partition_no == 0)
table->field[2]->set_null();
else
{
table->field[2]->set_notnull();
table->field[2]->store((long) partition_no, TRUE);
}
table->field[3]->store(key_cache_stats.mem_size, TRUE);
table->field[4]->store(key_cache_stats.block_size, TRUE);
table->field[5]->store(key_cache_stats.blocks_used, TRUE);
table->field[6]->store(key_cache_stats.blocks_unused, TRUE);
table->field[7]->store(key_cache_stats.blocks_changed, TRUE);
table->field[8]->store(key_cache_stats.read_requests, TRUE);
table->field[9]->store(key_cache_stats.reads, TRUE);
table->field[10]->store(key_cache_stats.write_requests, TRUE);
table->field[11]->store(key_cache_stats.writes, TRUE);
err= schema_table_store_record(thd, table);
DBUG_RETURN(err);
}
int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
TABLE *table= tables->table;
I_List_iterator<NAMED_LIST> it(key_caches);
NAMED_LIST *element;
DBUG_ENTER("fill_key_cache_tables");
while ((element= it++))
{
KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
if (!key_cache->key_cache_inited)
continue;
uint partitions= key_cache->partitions;
DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
if (partitions)
{
for (uint i= 0; i < partitions; i++)
{
if (store_key_cache_table_record(thd, table,
element->name, element->name_length,
key_cache, partitions, i+1))
DBUG_RETURN(1);
}
}
if (store_key_cache_table_record(thd, table,
element->name, element->name_length,
key_cache, partitions, 0))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
ST_FIELD_INFO schema_fields_info[]= ST_FIELD_INFO schema_fields_info[]=
{ {
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
...@@ -7188,6 +7299,35 @@ ST_FIELD_INFO referential_constraints_fields_info[]= ...@@ -7188,6 +7299,35 @@ ST_FIELD_INFO referential_constraints_fields_info[]=
}; };
ST_FIELD_INFO keycache_fields_info[]=
{
{"KEY_CACHE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
{"PARTITIONS", 3, MYSQL_TYPE_LONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED) , 0, SKIP_OPEN_TABLE},
{"PARTITION_NUMBER", 3, MYSQL_TYPE_LONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
{"FULL_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
{"BLOCK_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE },
{"USED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_used", SKIP_OPEN_TABLE},
{"UNUSED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_unused", SKIP_OPEN_TABLE},
{"DIRTY_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_not_flushed", SKIP_OPEN_TABLE},
{"READ_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_read_requests", SKIP_OPEN_TABLE},
{"READS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_reads", SKIP_OPEN_TABLE},
{"WRITE_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_write_requests", SKIP_OPEN_TABLE},
{"WRITES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_writes", SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
/* /*
Description of ST_FIELD_INFO in table.h Description of ST_FIELD_INFO in table.h
...@@ -7227,6 +7367,8 @@ ST_SCHEMA_TABLE schema_tables[]= ...@@ -7227,6 +7367,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_variables, make_old_format, 0, 0, -1, 0, 0}, fill_variables, make_old_format, 0, 0, -1, 0, 0},
{"INDEX_STATISTICS", index_stats_fields_info, create_schema_table, {"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0}, fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0},
{"KEY_CACHES", keycache_fields_info, create_schema_table,
fill_key_cache_tables, make_old_format, 0, -1,-1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0, get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY}, OPEN_TABLE_ONLY},
......
...@@ -435,7 +435,8 @@ static int print_key_cache_status(const char *name, KEY_CACHE *key_cache) ...@@ -435,7 +435,8 @@ static int print_key_cache_status(const char *name, KEY_CACHE *key_cache)
Buffer_size: %10lu\n\ Buffer_size: %10lu\n\
Block_size: %10lu\n\ Block_size: %10lu\n\
Division_limit: %10lu\n\ Division_limit: %10lu\n\
Age_limit: %10lu\n\ Age_threshold: %10lu\n\
Partitions: %10lu\n\
blocks used: %10lu\n\ blocks used: %10lu\n\
not flushed: %10lu\n\ not flushed: %10lu\n\
w_requests: %10s\n\ w_requests: %10s\n\
...@@ -445,6 +446,7 @@ reads: %10s\n\n", ...@@ -445,6 +446,7 @@ reads: %10s\n\n",
name, name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size, (ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold, key_cache->param_division_limit, key_cache->param_age_threshold,
key_cache->param_partitions,
key_cache->blocks_used,key_cache->global_blocks_changed, key_cache->blocks_used,key_cache->global_blocks_changed,
llstr(key_cache->global_cache_w_requests,llbuff1), llstr(key_cache->global_cache_w_requests,llbuff1),
llstr(key_cache->global_cache_write,llbuff2), llstr(key_cache->global_cache_write,llbuff2),
......
...@@ -953,6 +953,7 @@ enum enum_schema_tables ...@@ -953,6 +953,7 @@ enum enum_schema_tables
SCH_GLOBAL_STATUS, SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES, SCH_GLOBAL_VARIABLES,
SCH_INDEX_STATS, SCH_INDEX_STATS,
SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE, SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES, SCH_OPEN_TABLES,
SCH_PARTITIONS, SCH_PARTITIONS,
......
...@@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register MI_INFO *info) ...@@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register MI_INFO *info)
/* The following is needed if called externally (not from myisamchk) */ /* The following is needed if called externally (not from myisamchk) */
flush_key_blocks(info->s->key_cache, flush_key_blocks(info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE); info->s->kfile, &info->s->dirty_part_map,
FLUSH_FORCE_WRITE);
size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)); size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size) if ((skr=(my_off_t) info->state->key_file_length) != size)
...@@ -1474,6 +1475,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force) ...@@ -1474,6 +1475,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
*/ */
DBUG_PRINT("repair", ("all disabled are empty: create missing")); DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile, error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_FORCE_WRITE); FLUSH_FORCE_WRITE);
goto end; goto end;
} }
...@@ -1488,6 +1490,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force) ...@@ -1488,6 +1490,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
/* Remove all key blocks of this index file from key cache. */ /* Remove all key blocks of this index file from key cache. */
if ((error= flush_key_blocks(share->key_cache, share->kfile, if ((error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_IGNORE_CHANGED))) FLUSH_IGNORE_CHANGED)))
goto end; /* purecov: inspected */ goto end; /* purecov: inspected */
...@@ -1549,7 +1552,7 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info, ...@@ -1549,7 +1552,7 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info,
if (!param->using_global_keycache) if (!param->using_global_keycache)
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size, VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
(size_t) param->use_buffers, 0, 0)); (size_t) param->use_buffers, 0, 0, 0));
if (init_io_cache(&param->read_cache,info->dfile, if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length, (uint) param->read_buffer_length,
...@@ -1762,7 +1765,8 @@ err: ...@@ -1762,7 +1765,8 @@ err:
VOID(end_io_cache(&param->read_cache)); VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache)); VOID(end_io_cache(&info->rec_cache));
got_error|=flush_blocks(param, share->key_cache, share->kfile); got_error|=flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
if (!got_error && param->testflag & T_UNPACK) if (!got_error && param->testflag & T_UNPACK)
{ {
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD; share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
...@@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attribute__((unused))) ...@@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */ /* Flush all changed blocks to disk */
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file) int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
ulonglong *dirty_part_map)
{ {
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE)) if (flush_key_blocks(key_cache, file, dirty_part_map, FLUSH_RELEASE))
{ {
mi_check_print_error(param,"%d when trying to write bufferts",my_errno); mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1); return(1);
...@@ -1977,7 +1982,8 @@ int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name) ...@@ -1977,7 +1982,8 @@ int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name)
} }
/* Flush key cache for this file if we are calling this outside myisamchk */ /* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0); share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */ old_state= share->state; /* save state if not stored */
...@@ -2535,7 +2541,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info, ...@@ -2535,7 +2541,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state)); memcpy( &share->state.state, info->state, sizeof(*info->state));
err: err:
got_error|= flush_blocks(param, share->key_cache, share->kfile); got_error|= flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
VOID(end_io_cache(&info->rec_cache)); VOID(end_io_cache(&info->rec_cache));
if (!got_error) if (!got_error)
{ {
...@@ -3059,7 +3066,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, ...@@ -3059,7 +3066,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state)); memcpy(&share->state.state, info->state, sizeof(*info->state));
err: err:
got_error|= flush_blocks(param, share->key_cache, share->kfile); got_error|= flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
/* /*
Destroy the write cache. The master thread did already detach from Destroy the write cache. The master thread did already detach from
the share by remove_io_thread() or it was not yet started (if the the share by remove_io_thread() or it was not yet started (if the
......
...@@ -64,6 +64,7 @@ int mi_close(register MI_INFO *info) ...@@ -64,6 +64,7 @@ int mi_close(register MI_INFO *info)
if (share->kfile >= 0) abort();); if (share->kfile >= 0) abort(););
if (share->kfile >= 0 && if (share->kfile >= 0 &&
flush_key_blocks(share->key_cache, share->kfile, flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
((share->temporary || share->deleting) ? ((share->temporary || share->deleting) ?
FLUSH_IGNORE_CHANGED : FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE))) FLUSH_RELEASE)))
......
...@@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info) ...@@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache since it was locked then there may be key blocks in the key cache
*/ */
flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED); flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_IGNORE_CHANGED);
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
if (share->file_map) if (share->file_map)
_mi_unmap_file(info); _mi_unmap_file(info);
......
...@@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
pthread_mutex_lock(&share->intern_lock); pthread_mutex_lock(&share->intern_lock);
/* Flush pages that we don't need anymore */ /* Flush pages that we don't need anymore */
if (flush_key_blocks(share->key_cache, share->kfile, if (flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
(function == HA_EXTRA_PREPARE_FOR_DROP ? (function == HA_EXTRA_PREPARE_FOR_DROP ?
FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))) FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)))
{ {
...@@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg) ...@@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break; break;
case HA_EXTRA_FLUSH: case HA_EXTRA_FLUSH:
if (!share->temporary) if (!share->temporary)
flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP); flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_KEEP);
#ifdef HAVE_PWRITE #ifdef HAVE_PWRITE
_mi_decrement_open_count(info); _mi_decrement_open_count(info);
#endif #endif
......
...@@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info, ...@@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
in the old key cache. in the old key cache.
*/ */
if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE)) if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE))
{ {
error= my_errno; error= my_errno;
mi_print_error(info->s, HA_ERR_CRASHED); mi_print_error(info->s, HA_ERR_CRASHED);
...@@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info, ...@@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
(This can never fail as there is never any not written data in the (This can never fail as there is never any not written data in the
new key cache) new key cache)
*/ */
(void) flush_key_blocks(key_cache, share->kfile, FLUSH_RELEASE); (void) flush_key_blocks(key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE);
/* /*
ensure that setting the key cache and changing the multi_key_cache ensure that setting the key cache and changing the multi_key_cache
...@@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info, ...@@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
This should be seen at the lastes for the next call to an myisam function. This should be seen at the lastes for the next call to an myisam function.
*/ */
share->key_cache= key_cache; share->key_cache= key_cache;
share->dirty_part_map= 0;
/* store the key cache in the global hash structure for future opens */ /* store the key cache in the global hash structure for future opens */
if (multi_key_cache_set((uchar*) share->unique_file_name, if (multi_key_cache_set((uchar*) share->unique_file_name,
......
...@@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int lock_type)
--share->tot_locks; --share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks && if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache, !share->delay_key_write && flush_key_blocks(share->key_cache,
share->kfile,FLUSH_KEEP)) share->kfile,
&share->dirty_part_map,
FLUSH_KEEP))
{ {
error=my_errno; error=my_errno;
mi_print_error(info->s, HA_ERR_CRASHED); mi_print_error(info->s, HA_ERR_CRASHED);
...@@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO *info) ...@@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */ { /* Keyfile has changed */
DBUG_PRINT("info",("index file changed")); DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process) if (share->state.process != share->this_process)
VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE)); VOID(flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map, FLUSH_RELEASE));
share->last_process=share->state.process; share->last_process=share->state.process;
info->last_unique= share->state.unique; info->last_unique= share->state.unique;
info->last_loop= share->state.update_count; info->last_loop= share->state.update_count;
......
...@@ -94,10 +94,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, ...@@ -94,10 +94,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
} }
#endif #endif
DBUG_RETURN((key_cache_write(info->s->key_cache, DBUG_RETURN((key_cache_write(info->s->key_cache,
info->s->kfile,page, level, (uchar*) buff,length, info->s->kfile, &info->s->dirty_part_map,
(uint) keyinfo->block_length, page, level, (uchar*) buff, length,
(int) ((info->lock_type != F_UNLCK) || (uint) keyinfo->block_length,
info->s->delay_key_write)))); (int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
} /* mi_write_keypage */ } /* mi_write_keypage */
...@@ -116,7 +117,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos, ...@@ -116,7 +117,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
mi_sizestore(buff,old_link); mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES; info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache, DBUG_RETURN(key_cache_write(info->s->key_cache,
info->s->kfile, pos , level, buff, info->s->kfile, &info->s->dirty_part_map,
pos , level, buff,
sizeof(buff), sizeof(buff),
(uint) keyinfo->block_length, (uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK))); (int) (info->lock_type != F_UNLCK)));
......
...@@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag) ...@@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA) if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break; break;
#endif #endif
if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE)) if (flush_key_blocks(info->s->key_cache, info->s->kfile,
&info->s->dirty_part_map, FLUSH_RELEASE))
error=my_errno; error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED) if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache)) if (flush_io_cache(&info->rec_cache))
......
...@@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
} }
} }
else else
block_length= share->key_cache->key_cache_block_size; block_length= share->key_cache->param_block_size;
length= info->preload_buff_size/block_length * block_length; length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length); set_if_bigger(length, block_length);
...@@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME)))) if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE)) if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE))
goto err; goto err;
do do
......
...@@ -49,7 +49,8 @@ int main(int argc,char *argv[]) ...@@ -49,7 +49,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]); MY_INIT(argv[0]);
my_init(); my_init();
if (key_cacheing) if (key_cacheing)
init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0); init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0,
DEFAULT_KEY_CACHE_PARTITIONS);
get_options(argc,argv); get_options(argc,argv);
exit(run_test("test1")); exit(run_test("test1"));
......
...@@ -215,7 +215,8 @@ int main(int argc, char *argv[]) ...@@ -215,7 +215,8 @@ int main(int argc, char *argv[])
if (!silent) if (!silent)
printf("- Writing key:s\n"); printf("- Writing key:s\n");
if (key_cacheing) if (key_cacheing)
init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0); init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0,
DEFAULT_KEY_CACHE_PARTITIONS);
if (do_locking) if (do_locking)
mi_lock_database(file,F_WRLCK); mi_lock_database(file,F_WRLCK);
if (write_cacheing) if (write_cacheing)
......
...@@ -177,7 +177,8 @@ void start_test(int id) ...@@ -177,7 +177,8 @@ void start_test(int id)
exit(1); exit(1);
} }
if (key_cacheing && rnd(2) == 0) if (key_cacheing && rnd(2) == 0)
init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0); init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0,
DEFAULT_KEY_CACHE_PARTITIONS);
printf("Process %d, pid: %ld\n", id, (long) getpid()); printf("Process %d, pid: %ld\n", id, (long) getpid());
fflush(stdout); fflush(stdout);
......
...@@ -83,7 +83,7 @@ int main(int argc,char *argv[]) ...@@ -83,7 +83,7 @@ int main(int argc,char *argv[])
usage(); usage();
} }
init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0); init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0);
if (!(info=mi_open(argv[0], O_RDONLY, if (!(info=mi_open(argv[0], O_RDONLY,
HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER))) HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
......
...@@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, char * filename) ...@@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, char * filename)
{ {
if (param->testflag & (T_EXTEND | T_MEDIUM)) if (param->testflag & (T_EXTEND | T_MEDIUM))
VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size, VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size,
(size_t) param->use_buffers, 0, 0)); (size_t) param->use_buffers, 0, 0, 0));
VOID(init_io_cache(&param->read_cache,datafile, VOID(init_io_cache(&param->read_cache,datafile,
(uint) param->read_buffer_length, (uint) param->read_buffer_length,
READ_CACHE, READ_CACHE,
...@@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, char * filename) ...@@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, char * filename)
HA_OPTION_COMPRESS_RECORD)) || HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM))) (param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, test(param->testflag & T_EXTEND)); error|=chk_data_link(param, info, test(param->testflag & T_EXTEND));
error|=flush_blocks(param, share->key_cache, share->kfile); error|=flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
VOID(end_io_cache(&param->read_cache)); VOID(end_io_cache(&param->read_cache));
} }
if (!error) if (!error)
...@@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *param, ...@@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *param,
DBUG_RETURN(0); /* Nothing to do */ DBUG_RETURN(0); /* Nothing to do */
init_key_cache(dflt_key_cache, opt_key_cache_block_size, init_key_cache(dflt_key_cache, opt_key_cache_block_size,
(size_t) param->use_buffers, 0, 0); (size_t) param->use_buffers, 0, 0, 0);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length, if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1, WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL))) MYF(MY_WME | MY_WAIT_IF_FULL)))
...@@ -1641,8 +1642,8 @@ err: ...@@ -1641,8 +1642,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0; sort_info.buff=0;
share->state.sortkey=sort_key; share->state.sortkey=sort_key;
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) | DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile,
got_error); &share->dirty_part_map) | got_error);
} /* sort_records */ } /* sort_records */
......
...@@ -174,6 +174,8 @@ typedef struct st_mi_isam_share ...@@ -174,6 +174,8 @@ typedef struct st_mi_isam_share
*index_file_name; *index_file_name;
uchar *file_map; /* mem-map of file if possible */ uchar *file_map; /* mem-map of file if possible */
KEY_CACHE *key_cache; /* ref to the current key cache */ KEY_CACHE *key_cache; /* ref to the current key cache */
/* To mark the key cache partitions containing dirty pages for this file */
ulonglong dirty_part_map;
MI_DECODE_TREE *decode_trees; MI_DECODE_TREE *decode_trees;
uint16 *decode_tables; uint16 *decode_tables;
/* Function to use for a row checksum. */ /* Function to use for a row checksum. */
...@@ -733,7 +735,8 @@ void mi_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...)); ...@@ -733,7 +735,8 @@ void mi_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...));
#ifdef THREAD #ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg); pthread_handler_t thr_find_all_keys(void *arg);
#endif #endif
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file); int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
ulonglong *dirty_part_map);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
...@@ -333,7 +333,7 @@ static int examine_log(char * file_name, char **table_names) ...@@ -333,7 +333,7 @@ static int examine_log(char * file_name, char **table_names)
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL); (tree_element_free) file_info_free, NULL);
VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE, VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
0, 0)); 0, 0, 0));
files_open=0; access_time=0; files_open=0; access_time=0;
while (access_time++ != number_of_commands && while (access_time++ != number_of_commands &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment