fixed QC invaluidation and processing with view (BUG#8050) (BUG#8054)
This commit is contained in:
parent
8881bead7a
commit
34b85449bb
@ -1,3 +1,5 @@
|
|||||||
|
drop table if exists t1,t2,v1,v2,v3;
|
||||||
|
drop view if exists t1,t2,v1,v2,v3;
|
||||||
set GLOBAL query_cache_size=1355776;
|
set GLOBAL query_cache_size=1355776;
|
||||||
flush status;
|
flush status;
|
||||||
create table t1 (a int, b int);
|
create table t1 (a int, b int);
|
||||||
@ -98,4 +100,27 @@ Qcache_hits 1
|
|||||||
drop view v1;
|
drop view v1;
|
||||||
set query_cache_type=default;
|
set query_cache_type=default;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values (1), (2), (3);
|
||||||
|
create view v1 as select a from t1 where a > 1;
|
||||||
|
select * from v1;
|
||||||
|
a
|
||||||
|
2
|
||||||
|
3
|
||||||
|
alter view v1 as select a from t1 where a > 2;
|
||||||
|
select * from v1;
|
||||||
|
a
|
||||||
|
3
|
||||||
|
drop view v1;
|
||||||
|
select * from v1;
|
||||||
|
ERROR 42S02: Table 'test.v1' doesn't exist
|
||||||
|
drop table t1;
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a), b int);
|
||||||
|
insert into t2 values (1000, 2000);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
drop view v3;
|
||||||
|
drop table t1, t2;
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
#
|
#
|
||||||
# QUERY CACHE options for VIEWs
|
# QUERY CACHE options for VIEWs
|
||||||
#
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1,t2,v1,v2,v3;
|
||||||
|
drop view if exists t1,t2,v1,v2,v3;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
set GLOBAL query_cache_size=1355776;
|
set GLOBAL query_cache_size=1355776;
|
||||||
flush status;
|
flush status;
|
||||||
create table t1 (a int, b int);
|
create table t1 (a int, b int);
|
||||||
@ -53,6 +58,30 @@ drop view v1;
|
|||||||
set query_cache_type=default;
|
set query_cache_type=default;
|
||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# invalidation of view
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values (1), (2), (3);
|
||||||
|
create view v1 as select a from t1 where a > 1;
|
||||||
|
select * from v1;
|
||||||
|
alter view v1 as select a from t1 where a > 2;
|
||||||
|
select * from v1;
|
||||||
|
drop view v1;
|
||||||
|
-- error 1146
|
||||||
|
select * from v1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# join view with QC
|
||||||
|
#
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a), b int);
|
||||||
|
insert into t2 values (1000, 2000);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
select * from v3;
|
||||||
|
drop view v3;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
|
||||||
|
|
||||||
|
229
sql/sql_cache.cc
229
sql/sql_cache.cc
@ -311,7 +311,7 @@ TODO list:
|
|||||||
#include "emb_qcache.h"
|
#include "emb_qcache.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
|
#if !defined(DBUG_OFF) && !defined(DBUG_OFF)
|
||||||
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
|
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
|
||||||
pthread_mutex_lock(M);}
|
pthread_mutex_lock(M);}
|
||||||
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
|
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
|
||||||
@ -2089,6 +2089,80 @@ void Query_cache::invalidate_table(Query_cache_block *table_block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TABLE_COUNTER_TYPE
|
||||||
|
Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
|
||||||
|
TABLE_COUNTER_TYPE counter,
|
||||||
|
Query_cache_block_table *block_table)
|
||||||
|
{
|
||||||
|
TABLE_COUNTER_TYPE n;
|
||||||
|
DBUG_ENTER("Query_cache::register_tables_from_list");
|
||||||
|
for (n= counter;
|
||||||
|
tables_used;
|
||||||
|
tables_used= tables_used->next_global, n++, block_table++)
|
||||||
|
{
|
||||||
|
block_table->n= n;
|
||||||
|
if (tables_used->view)
|
||||||
|
{
|
||||||
|
char key[MAX_DBKEY_LENGTH];
|
||||||
|
uint key_length;
|
||||||
|
DBUG_PRINT("qcache", ("view %s, db %s",
|
||||||
|
tables_used->view_name.str,
|
||||||
|
tables_used->view_db.str));
|
||||||
|
key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1,
|
||||||
|
tables_used->view_name.str) - key) + 1;
|
||||||
|
insert_table(key_length, key, block_table,
|
||||||
|
tables_used->view_db.length + 1,
|
||||||
|
HA_CACHE_TBL_NONTRANSACT);
|
||||||
|
{
|
||||||
|
TABLE_COUNTER_TYPE inc= register_tables_from_list(tables_used->ancestor,
|
||||||
|
n + 1,
|
||||||
|
block_table + 1);
|
||||||
|
if (!inc)
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
n+= inc;
|
||||||
|
block_table+= inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_PRINT("qcache",
|
||||||
|
("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
|
||||||
|
tables_used->table->s->table_name,
|
||||||
|
tables_used->table->s->table_cache_key,
|
||||||
|
(ulong) tables_used->table,
|
||||||
|
tables_used->table->s->key_length,
|
||||||
|
(ulong) tables_used->table->s->table_cache_key));
|
||||||
|
if (!insert_table(tables_used->table->s->key_length,
|
||||||
|
tables_used->table->s->table_cache_key, block_table,
|
||||||
|
tables_used->db_length,
|
||||||
|
tables_used->table->file->table_cache_type()))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
|
||||||
|
{
|
||||||
|
ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
|
||||||
|
MYRG_INFO *file = handler->myrg_info();
|
||||||
|
for (MYRG_TABLE *table = file->open_tables;
|
||||||
|
table != file->end_table ;
|
||||||
|
table++)
|
||||||
|
{
|
||||||
|
char key[MAX_DBKEY_LENGTH];
|
||||||
|
uint32 db_length;
|
||||||
|
uint key_length= filename_2_table_key(key, table->table->filename,
|
||||||
|
&db_length);
|
||||||
|
(++block_table)->n= ++n;
|
||||||
|
if (!insert_table(key_length, key, block_table,
|
||||||
|
db_length,
|
||||||
|
tables_used->table->file->table_cache_type()))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(n - counter);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Store all used tables
|
Store all used tables
|
||||||
|
|
||||||
@ -2110,46 +2184,10 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
|
|||||||
|
|
||||||
Query_cache_block_table *block_table = block->table(0);
|
Query_cache_block_table *block_table = block->table(0);
|
||||||
|
|
||||||
for (n= 0;
|
n= register_tables_from_list(tables_used, 0, block_table);
|
||||||
tables_used;
|
|
||||||
tables_used= tables_used->next_global, n++, block_table++)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("qcache",
|
|
||||||
("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx",
|
|
||||||
tables_used->table_name, tables_used->db,
|
|
||||||
(ulong) tables_used->table,
|
|
||||||
tables_used->table->s->key_length,
|
|
||||||
(ulong) tables_used->table->s->table_cache_key));
|
|
||||||
block_table->n= n;
|
|
||||||
if (!insert_table(tables_used->table->s->key_length,
|
|
||||||
tables_used->table->s->table_cache_key, block_table,
|
|
||||||
tables_used->db_length,
|
|
||||||
tables_used->table->file->table_cache_type()))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
|
|
||||||
{
|
|
||||||
ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file;
|
|
||||||
MYRG_INFO *file = handler->myrg_info();
|
|
||||||
for (MYRG_TABLE *table = file->open_tables;
|
|
||||||
table != file->end_table ;
|
|
||||||
table++)
|
|
||||||
{
|
|
||||||
char key[MAX_DBKEY_LENGTH];
|
|
||||||
uint32 db_length;
|
|
||||||
uint key_length= filename_2_table_key(key, table->table->filename,
|
|
||||||
&db_length);
|
|
||||||
(++block_table)->n= ++n;
|
|
||||||
if (!insert_table(key_length, key, block_table,
|
|
||||||
db_length,
|
|
||||||
tables_used->table->file->table_cache_type()))
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (tables_used)
|
if (n)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("failed at table %d", (int) n));
|
DBUG_PRINT("qcache", ("failed at table %d", (int) n));
|
||||||
/* Unlink the tables we allocated above */
|
/* Unlink the tables we allocated above */
|
||||||
@ -2158,7 +2196,7 @@ err:
|
|||||||
tmp++)
|
tmp++)
|
||||||
unlink_table(tmp);
|
unlink_table(tmp);
|
||||||
}
|
}
|
||||||
return (tables_used == 0);
|
return (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2634,6 +2672,80 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail,
|
|||||||
Query
|
Query
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collect information about table types, check that tables are cachable and
|
||||||
|
count them
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
process_and_count_tables()
|
||||||
|
tables_used table list for processing
|
||||||
|
tables_type pointer to variable for table types collection
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 error
|
||||||
|
>0 number of tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used,
|
||||||
|
uint8 *tables_type)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("process_and_count_tables");
|
||||||
|
TABLE_COUNTER_TYPE table_count = 0;
|
||||||
|
for (; tables_used; tables_used= tables_used->next_global)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (tables_used->view)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("qcache", ("view %s, db %s",
|
||||||
|
tables_used->view_name.str,
|
||||||
|
tables_used->view_db.str));
|
||||||
|
table_count++;
|
||||||
|
*tables_type|= HA_CACHE_TBL_NONTRANSACT;
|
||||||
|
{
|
||||||
|
TABLE_COUNTER_TYPE subcount;
|
||||||
|
if (!(subcount= process_and_count_tables(tables_used->ancestor,
|
||||||
|
tables_type)))
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
table_count+= subcount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
table_count++;
|
||||||
|
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
|
||||||
|
tables_used->table->s->table_name,
|
||||||
|
tables_used->table->s->table_cache_key,
|
||||||
|
tables_used->table->s->db_type));
|
||||||
|
*tables_type|= tables_used->table->file->table_cache_type();
|
||||||
|
|
||||||
|
/*
|
||||||
|
table_alias_charset used here because it depends of
|
||||||
|
lower_case_table_names variable
|
||||||
|
*/
|
||||||
|
if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
|
||||||
|
(*tables_type & HA_CACHE_TBL_NOCACHE) ||
|
||||||
|
(tables_used->db_length == 5 &&
|
||||||
|
my_strnncoll(table_alias_charset,
|
||||||
|
(uchar*)tables_used->table->s->table_cache_key, 6,
|
||||||
|
(uchar*)"mysql",6) == 0))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("qcache",
|
||||||
|
("select not cacheable: temporary, system or \
|
||||||
|
other non-cacheable table(s)"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
|
||||||
|
{
|
||||||
|
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
|
||||||
|
MYRG_INFO *file = handler->myrg_info();
|
||||||
|
table_count+= (file->end_table - file->open_tables);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(table_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If query is cacheable return number tables in query
|
If query is cacheable return number tables in query
|
||||||
(query without tables are not cached)
|
(query without tables are not cached)
|
||||||
@ -2645,7 +2757,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
|
|||||||
TABLE_LIST *tables_used,
|
TABLE_LIST *tables_used,
|
||||||
uint8 *tables_type)
|
uint8 *tables_type)
|
||||||
{
|
{
|
||||||
TABLE_COUNTER_TYPE table_count = 0;
|
TABLE_COUNTER_TYPE table_count;
|
||||||
DBUG_ENTER("Query_cache::is_cacheable");
|
DBUG_ENTER("Query_cache::is_cacheable");
|
||||||
|
|
||||||
if (lex->sql_command == SQLCOM_SELECT &&
|
if (lex->sql_command == SQLCOM_SELECT &&
|
||||||
@ -2659,36 +2771,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len,
|
|||||||
lex->select_lex.options,
|
lex->select_lex.options,
|
||||||
(int) thd->variables.query_cache_type));
|
(int) thd->variables.query_cache_type));
|
||||||
|
|
||||||
for (; tables_used; tables_used= tables_used->next_global)
|
if (!(table_count= process_and_count_tables(tables_used, tables_type)))
|
||||||
{
|
DBUG_RETURN(0);
|
||||||
table_count++;
|
|
||||||
DBUG_PRINT("qcache", ("table %s, db %s, type %u",
|
|
||||||
tables_used->table_name,
|
|
||||||
tables_used->db, tables_used->table->s->db_type));
|
|
||||||
*tables_type|= tables_used->table->file->table_cache_type();
|
|
||||||
|
|
||||||
/*
|
|
||||||
table_alias_charset used here because it depends of
|
|
||||||
lower_case_table_names variable
|
|
||||||
*/
|
|
||||||
if (tables_used->table->s->tmp_table != NO_TMP_TABLE ||
|
|
||||||
(*tables_type & HA_CACHE_TBL_NOCACHE) ||
|
|
||||||
(tables_used->db_length == 5 &&
|
|
||||||
my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6,
|
|
||||||
(uchar*)"mysql",6) == 0))
|
|
||||||
{
|
|
||||||
DBUG_PRINT("qcache",
|
|
||||||
("select not cacheable: temporary, system or \
|
|
||||||
other non-cacheable table(s)"));
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM)
|
|
||||||
{
|
|
||||||
ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file;
|
|
||||||
MYRG_INFO *file = handler->myrg_info();
|
|
||||||
table_count+= (file->end_table - file->open_tables);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
|
if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
|
||||||
((*tables_type)&HA_CACHE_TBL_TRANSACT))
|
((*tables_type)&HA_CACHE_TBL_TRANSACT))
|
||||||
@ -2729,7 +2813,8 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
|
|||||||
for (; tables_used; tables_used= tables_used->next_global)
|
for (; tables_used; tables_used= tables_used->next_global)
|
||||||
{
|
{
|
||||||
TABLE *table= tables_used->table;
|
TABLE *table= tables_used->table;
|
||||||
if (!ha_caching_allowed(thd, table->s->table_cache_key,
|
if (table &&
|
||||||
|
!ha_caching_allowed(thd, table->s->table_cache_key,
|
||||||
table->s->key_length,
|
table->s->key_length,
|
||||||
table->file->table_cache_type()))
|
table->file->table_cache_type()))
|
||||||
{
|
{
|
||||||
|
@ -277,6 +277,10 @@ protected:
|
|||||||
void invalidate_table(TABLE *table);
|
void invalidate_table(TABLE *table);
|
||||||
void invalidate_table(byte *key, uint32 key_length);
|
void invalidate_table(byte *key, uint32 key_length);
|
||||||
void invalidate_table(Query_cache_block *table_block);
|
void invalidate_table(Query_cache_block *table_block);
|
||||||
|
TABLE_COUNTER_TYPE
|
||||||
|
register_tables_from_list(TABLE_LIST *tables_used,
|
||||||
|
TABLE_COUNTER_TYPE counter,
|
||||||
|
Query_cache_block_table *block_table);
|
||||||
my_bool register_all_tables(Query_cache_block *block,
|
my_bool register_all_tables(Query_cache_block *block,
|
||||||
TABLE_LIST *tables_used,
|
TABLE_LIST *tables_used,
|
||||||
TABLE_COUNTER_TYPE tables);
|
TABLE_COUNTER_TYPE tables);
|
||||||
|
@ -305,6 +305,8 @@ bool mysql_create_view(THD *thd,
|
|||||||
VOID(pthread_mutex_lock(&LOCK_open));
|
VOID(pthread_mutex_lock(&LOCK_open));
|
||||||
res= mysql_register_view(thd, view, mode);
|
res= mysql_register_view(thd, view, mode);
|
||||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
|
if (view->revision != 1)
|
||||||
|
query_cache_invalidate3(thd, view, 0);
|
||||||
start_waiting_global_read_lock(thd);
|
start_waiting_global_read_lock(thd);
|
||||||
if (res)
|
if (res)
|
||||||
goto err;
|
goto err;
|
||||||
@ -912,6 +914,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
|
|||||||
}
|
}
|
||||||
if (my_delete(path, MYF(MY_WME)))
|
if (my_delete(path, MYF(MY_WME)))
|
||||||
goto err;
|
goto err;
|
||||||
|
query_cache_invalidate3(thd, view, 0);
|
||||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
}
|
}
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user