Commit 70ad689b authored by Jan Lindström's avatar Jan Lindström

MDEV-8633: information_schema.index_statistics doesn't delete

item when drop table indexes or drop table;

Problem was that table and index statistics is removed from
persistent tables but not from memory cache. Added functions
to remove table and index statistics from memory cache.
parent e24a1833
set global userstat=1;
create table just_a_test(id int,first_name varchar(10),last_name varchar(10),address varchar(100),phone bigint,email varchar(30), state varchar(30));
insert into just_a_test values(1,'fa','la','china_a',11111111,'fa_la@163.com','California'),
(2,'fb','lb','china_b',22222222,'fb_lb@163.com','Arizona'),
(3,'fc','lc','china_c',33333333,'fc_lc@163.com','California'),
(4,'fd','ld','china_d',44444444,'fd_ld@163.com','Utah'),
(5,'fe','le','china_e',55555555,'fe_le@163.com','Arizona');
alter table just_a_test add primary key (id);
alter table just_a_test add key IND_just_a_test_first_name_last_name(first_name,last_name);
alter table just_a_test add key IND_just_a_test_state(state);
select count(*) from just_a_test where first_name='fc' and last_name='lc';
count(*)
1
select count(*) from just_a_test where state = 'California';
count(*)
2
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
test just_a_test IND_just_a_test_state 2
test just_a_test IND_just_a_test_first_name_last_name 1
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
test just_a_test 18 5 5
alter table just_a_test drop key IND_just_a_test_first_name_last_name;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
test just_a_test IND_just_a_test_state 2
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
test just_a_test 23 5 5
alter table just_a_test drop column state;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
test just_a_test 28 5 5
drop table just_a_test;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
create table just_a_test(id int not null primary key,first_name varchar(10),last_name varchar(10),address varchar(100),phone bigint,email varchar(30), state varchar(30),key(first_name,last_name),key(state));
insert into just_a_test values(1,'fa','la','china_a',11111111,'fa_la@163.com','California'),
(2,'fb','lb','china_b',22222222,'fb_lb@163.com','Arizona'),
(3,'fc','lc','china_c',33333333,'fc_lc@163.com','California'),
(4,'fd','ld','china_d',44444444,'fd_ld@163.com','Utah'),
(5,'fe','le','china_e',55555555,'fe_le@163.com','Arizona');
select count(*) from just_a_test where first_name='fc' and last_name='lc';
count(*)
1
select count(*) from just_a_test where state = 'California';
count(*)
2
select count(*) from just_a_test where id between 2 and 4;
count(*)
3
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
test just_a_test first_name 1
test just_a_test state 2
test just_a_test PRIMARY 5
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
test just_a_test 8 5 15
drop table just_a_test;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
set global userstat=0;
......@@ -128,16 +128,12 @@ handler_read_key
set @@global.userstat=0;
select * from information_schema.index_statistics;
TABLE_SCHEMA TABLE_NAME INDEX_NAME ROWS_READ
test t1 PRIMARY 2
select * from information_schema.table_statistics;
TABLE_SCHEMA TABLE_NAME ROWS_READ ROWS_CHANGED ROWS_CHANGED_X_INDEXES
test t1 6 13 13
show table_statistics;
Table_schema Table_name Rows_read Rows_changed Rows_changed_x_#indexes
test t1 6 13 13
show index_statistics;
Table_schema Table_name Index_name Rows_read
test t1 PRIMARY 2
select TOTAL_CONNECTIONS, CONCURRENT_CONNECTIONS, ROWS_READ, ROWS_SENT, ROWS_DELETED, ROWS_INSERTED, ROWS_UPDATED, SELECT_COMMANDS, UPDATE_COMMANDS, OTHER_COMMANDS, COMMIT_TRANSACTIONS, ROLLBACK_TRANSACTIONS, DENIED_CONNECTIONS, LOST_CONNECTIONS, ACCESS_DENIED, EMPTY_QUERIES from information_schema.client_statistics;;
TOTAL_CONNECTIONS 1
CONCURRENT_CONNECTIONS 0
......
#
# MDEV-8633: information_schema.index_statistics doesn't delete item when drop table indexes or drop table;
#
set global userstat=1;
create table just_a_test(id int,first_name varchar(10),last_name varchar(10),address varchar(100),phone bigint,email varchar(30), state varchar(30));
insert into just_a_test values(1,'fa','la','china_a',11111111,'fa_la@163.com','California'),
(2,'fb','lb','china_b',22222222,'fb_lb@163.com','Arizona'),
(3,'fc','lc','china_c',33333333,'fc_lc@163.com','California'),
(4,'fd','ld','china_d',44444444,'fd_ld@163.com','Utah'),
(5,'fe','le','china_e',55555555,'fe_le@163.com','Arizona');
alter table just_a_test add primary key (id);
alter table just_a_test add key IND_just_a_test_first_name_last_name(first_name,last_name);
alter table just_a_test add key IND_just_a_test_state(state);
select count(*) from just_a_test where first_name='fc' and last_name='lc';
select count(*) from just_a_test where state = 'California';
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
alter table just_a_test drop key IND_just_a_test_first_name_last_name;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
alter table just_a_test drop column state;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
drop table just_a_test;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
#
# Test direct drop table
#
create table just_a_test(id int not null primary key,first_name varchar(10),last_name varchar(10),address varchar(100),phone bigint,email varchar(30), state varchar(30),key(first_name,last_name),key(state));
insert into just_a_test values(1,'fa','la','china_a',11111111,'fa_la@163.com','California'),
(2,'fb','lb','china_b',22222222,'fb_lb@163.com','Arizona'),
(3,'fc','lc','china_c',33333333,'fc_lc@163.com','California'),
(4,'fd','ld','china_d',44444444,'fd_ld@163.com','Utah'),
(5,'fe','le','china_e',55555555,'fe_le@163.com','Arizona');
select count(*) from just_a_test where first_name='fc' and last_name='lc';
select count(*) from just_a_test where state = 'California';
select count(*) from just_a_test where id between 2 and 4;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
drop table just_a_test;
select * from information_schema.index_statistics where table_schema='test' and table_name='just_a_test';
select * from information_schema.table_statistics where table_schema='test' and table_name='just_a_test';
set global userstat=0;
......@@ -3460,6 +3460,100 @@ int fill_schema_table_stats(THD *thd, TABLE_LIST *tables, COND *cond)
DBUG_RETURN(0);
}
/* Remove all indexes for a given table from global index statistics */
static
int del_global_index_stats_for_table(THD *thd, uchar* cache_key, uint cache_key_length)
{
int res = 0;
DBUG_ENTER("del_global_index_stats_for_table");
mysql_mutex_lock(&LOCK_global_index_stats);
for (uint i= 0; i < global_index_stats.records;)
{
INDEX_STATS *index_stats =
(INDEX_STATS*) my_hash_element(&global_index_stats, i);
/* We search correct db\0table_name\0 string */
if (index_stats &&
index_stats->index_name_length >= cache_key_length &&
!memcmp(index_stats->index, cache_key, cache_key_length))
{
res= my_hash_delete(&global_index_stats, (uchar*)index_stats);
/*
In our HASH implementation on deletion one elements
is moved into a place where a deleted element was,
and the last element is moved into the empty space.
Thus we need to re-examine the current element, but
we don't have to restart the search from the beginning.
*/
}
else
i++;
}
mysql_mutex_unlock(&LOCK_global_index_stats);
DBUG_RETURN(res);
}
/* Remove a table from global table statistics */
int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table)
{
TABLE_STATS *table_stats;
int res = 0;
uchar *cache_key;
uint cache_key_length;
DBUG_ENTER("del_global_table_stat");
cache_key_length= db->length + 1 + table->length + 1;
if(!(cache_key= (uchar *)my_malloc(cache_key_length,
MYF(MY_WME | MY_ZEROFILL))))
{
/* Out of memory error already given */
res = 1;
goto end;
}
memcpy(cache_key, db->str, db->length);
memcpy(cache_key + db->length + 1, table->str, table->length);
res= del_global_index_stats_for_table(thd, cache_key, cache_key_length);
mysql_mutex_lock(&LOCK_global_table_stats);
if((table_stats= (TABLE_STATS*) my_hash_search(&global_table_stats,
cache_key,
cache_key_length)))
res= my_hash_delete(&global_table_stats, (uchar*)table_stats);
my_free(cache_key);
mysql_mutex_unlock(&LOCK_global_table_stats);
end:
DBUG_RETURN(res);
}
/* Remove a index from global index statistics */
int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info)
{
INDEX_STATS *index_stats;
uint key_length= table->s->table_cache_key.length + key_info->name_length + 1;
int res = 0;
DBUG_ENTER("del_global_index_stat");
mysql_mutex_lock(&LOCK_global_index_stats);
if((index_stats= (INDEX_STATS*) my_hash_search(&global_index_stats,
key_info->cache_name,
key_length)))
res= my_hash_delete(&global_index_stats, (uchar*)index_stats);
mysql_mutex_unlock(&LOCK_global_index_stats);
DBUG_RETURN(res);
}
/* Fill information schema table with index statistics */
......
......@@ -113,7 +113,8 @@ void view_store_options(THD *thd, TABLE_LIST *table, String *buff);
void init_fill_schema_files_row(TABLE* table);
bool schema_table_store_record(THD *thd, TABLE *table);
void initialize_information_schema_acl();
int del_global_index_stat(THD *thd, TABLE* tab, KEY* key_info);
int del_global_table_stat(THD *thd, LEX_STRING *db, LEX_STRING *table);
ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx);
int make_schema_select(THD *thd, SELECT_LEX *sel,
......
......@@ -29,6 +29,7 @@
#include "sql_statistics.h"
#include "opt_range.h"
#include "my_atomic.h"
#include "sql_show.h"
/*
The system variable 'use_stat_tables' can take one of the
......@@ -3193,6 +3194,10 @@ int delete_statistics_for_table(THD *thd, LEX_STRING *db, LEX_STRING *tab)
rc= 1;
}
err= del_global_table_stat(thd, db, tab);
if (err & !rc)
rc= 1;
thd->restore_stmt_binlog_format(save_binlog_format);
close_system_tables(thd, &open_tables_backup);
......@@ -3339,6 +3344,10 @@ int delete_statistics_for_index(THD *thd, TABLE *tab, KEY *key_info,
}
}
err= del_global_index_stat(thd, tab, key_info);
if (err && !rc)
rc= 1;
thd->restore_stmt_binlog_format(save_binlog_format);
close_system_tables(thd, &open_tables_backup);
......
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