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
INNODB_RSEG
INNODB_TABLE_STATS
INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
......
......@@ -13,6 +13,7 @@ FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
INDEX_STATISTICS
KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
......@@ -76,6 +77,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
......@@ -139,6 +141,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
......@@ -221,6 +224,7 @@ INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
INNODB_RSEG information_schema.INNODB_RSEG 1
INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1
INNODB_TRX information_schema.INNODB_TRX 1
KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
......@@ -259,6 +263,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
......@@ -312,6 +317,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
......@@ -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;
table_schema count(*)
information_schema 48
information_schema 49
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
drop table if exists t1, t2, t3;
--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;
......@@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size;
SELECT @@small.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
......@@ -247,3 +249,263 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
# 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)
uint tmp_block_size= (uint) 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(!init_key_cache(key_cache,
tmp_block_size,
tmp_buff_size,
division_limit, age_threshold));
division_limit, age_threshold,
partitions));
}
DBUG_RETURN(0);
}
......@@ -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)
{
DBUG_ENTER("ha_change_key_cache_param");
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
......@@ -3874,9 +3878,35 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache)
pthread_mutex_unlock(&LOCK_global_system_variables);
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.
*/
......
......@@ -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);
int ha_resize_key_cache(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_end_key_cache(KEY_CACHE *key_cache);
......
......@@ -5825,6 +5825,7 @@ enum options_mysqld
OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_PARTITIONS,
OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
......@@ -6915,6 +6916,12 @@ log and this option does nothing anymore.",
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
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 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},
......@@ -8837,6 +8844,7 @@ mysql_getopt_value(const char *keyname, uint key_length,
case OPT_KEY_CACHE_BLOCK_SIZE:
case OPT_KEY_CACHE_DIVISION_LIMIT:
case OPT_KEY_CACHE_AGE_THRESHOLD:
case OPT_KEY_CACHE_PARTITIONS:
{
KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
......@@ -8854,6 +8862,8 @@ mysql_getopt_value(const char *keyname, uint key_length,
return (uchar**) &key_cache->param_division_limit;
case OPT_KEY_CACHE_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",
static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
&SV::join_buff_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",
offsetof(KEY_CACHE,
param_block_size));
static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit",
offsetof(KEY_CACHE,
param_division_limit));
static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
offsetof(KEY_CACHE,
param_age_threshold));
static sys_var_key_cache_long sys_key_cache_block_size(&vars,
"key_cache_block_size",
offsetof(KEY_CACHE,param_block_size));
static sys_var_key_cache_long sys_key_cache_division_limit(&vars,
"key_cache_division_limit",
offsetof(KEY_CACHE, param_division_limit));
static sys_var_key_cache_long sys_key_cache_age_threshold(&vars,
"key_cache_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",
OPT_GLOBAL, SHOW_CHAR,
(uchar*) language);
......@@ -2540,7 +2543,21 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
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);
key_cache->in_init= 0;
......@@ -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_division_limit= dflt_key_cache_var.param_division_limit;
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);
......
......@@ -1427,6 +1427,7 @@ public:
my_free((uchar*) name, MYF(0));
}
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,
void (*free_element)(const char*, uchar*));
};
......
......@@ -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,
SHOW_VAR *variables,
enum enum_var_type value_type,
......@@ -2352,10 +2377,12 @@ static bool show_status_array(THD *thd, const char *wild,
break;
}
case SHOW_KEY_CACHE_LONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_KEY_CACHE_LONGLONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
......@@ -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[]=
{
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
......@@ -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
......@@ -7227,6 +7367,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_variables, make_old_format, 0, 0, -1, 0, 0},
{"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
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,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY},
......
......@@ -435,7 +435,8 @@ static int print_key_cache_status(const char *name, KEY_CACHE *key_cache)
Buffer_size: %10lu\n\
Block_size: %10lu\n\
Division_limit: %10lu\n\
Age_limit: %10lu\n\
Age_threshold: %10lu\n\
Partitions: %10lu\n\
blocks used: %10lu\n\
not flushed: %10lu\n\
w_requests: %10s\n\
......@@ -445,6 +446,7 @@ reads: %10s\n\n",
name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold,
key_cache->param_partitions,
key_cache->blocks_used,key_cache->global_blocks_changed,
llstr(key_cache->global_cache_w_requests,llbuff1),
llstr(key_cache->global_cache_write,llbuff2),
......
......@@ -953,6 +953,7 @@ enum enum_schema_tables
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
SCH_INDEX_STATS,
SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,
......
......@@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register MI_INFO *info)
/* The following is needed if called externally (not from myisamchk) */
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));
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)
*/
DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_FORCE_WRITE);
goto end;
}
......@@ -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. */
if ((error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_IGNORE_CHANGED)))
goto end; /* purecov: inspected */
......@@ -1549,7 +1552,7 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info,
if (!param->using_global_keycache)
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,
(uint) param->read_buffer_length,
......@@ -1762,7 +1765,8 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
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)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
......@@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attribute__((unused)))
/* 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);
return(1);
......@@ -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_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);
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,
memcpy( &share->state.state, info->state, sizeof(*info->state));
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));
if (!got_error)
{
......@@ -3059,7 +3066,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
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
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)
if (share->kfile >= 0) abort(););
if (share->kfile >= 0 &&
flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
((share->temporary || share->deleting) ?
FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)))
......
......@@ -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
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
if (share->file_map)
_mi_unmap_file(info);
......
......@@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
pthread_mutex_lock(&share->intern_lock);
/* Flush pages that we don't need anymore */
if (flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
(function == HA_EXTRA_PREPARE_FOR_DROP ?
FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)))
{
......@@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
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
_mi_decrement_open_count(info);
#endif
......
......@@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
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;
mi_print_error(info->s, HA_ERR_CRASHED);
......@@ -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
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
......@@ -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.
*/
share->key_cache= key_cache;
share->dirty_part_map= 0;
/* store the key cache in the global hash structure for future opens */
if (multi_key_cache_set((uchar*) share->unique_file_name,
......
......@@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int lock_type)
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!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;
mi_print_error(info->s, HA_ERR_CRASHED);
......@@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
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;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;
......
......@@ -94,10 +94,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
}
#endif
DBUG_RETURN((key_cache_write(info->s->key_cache,
info->s->kfile,page, level, (uchar*) buff,length,
(uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
info->s->kfile, &info->s->dirty_part_map,
page, level, (uchar*) buff, length,
(uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
} /* mi_write_keypage */
......@@ -116,7 +117,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
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),
(uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK)));
......
......@@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#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;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))
......
......@@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
}
}
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;
set_if_bigger(length, block_length);
......@@ -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))))
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;
do
......
......@@ -49,7 +49,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
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);
exit(run_test("test1"));
......
......@@ -215,7 +215,8 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Writing key:s\n");
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)
mi_lock_database(file,F_WRLCK);
if (write_cacheing)
......
......@@ -177,7 +177,8 @@ void start_test(int id)
exit(1);
}
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());
fflush(stdout);
......
......@@ -83,7 +83,7 @@ int main(int argc,char *argv[])
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,
HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
......
......@@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, char * filename)
{
if (param->testflag & (T_EXTEND | T_MEDIUM))
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,
(uint) param->read_buffer_length,
READ_CACHE,
......@@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, char * filename)
HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM)))
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));
}
if (!error)
......@@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *param,
DBUG_RETURN(0); /* Nothing to do */
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,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
......@@ -1641,8 +1642,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0;
share->state.sortkey=sort_key;
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) |
got_error);
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map) | got_error);
} /* sort_records */
......
......@@ -174,6 +174,8 @@ typedef struct st_mi_isam_share
*index_file_name;
uchar *file_map; /* mem-map of file if possible */
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;
uint16 *decode_tables;
/* Function to use for a row checksum. */
......@@ -733,7 +735,8 @@ void mi_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...));
#ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg);
#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
}
#endif
......@@ -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,
(tree_element_free) file_info_free, NULL);
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;
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