Commit ec41bed5 authored by unknown's avatar unknown

processing trunsactional tables in query cache


mysql-test/r/innodb_cache.result:
  new test for query cache with transactions
mysql-test/t/innodb_cache.test:
  new test for query cache with transactions
sql/sql_cache.cc:
  processing trunsactional tables in query cache & removing strlen
sql/sql_class.cc:
  processing trunsactional tables in query cache & added transaction-live memory
sql/sql_class.h:
  processing trunsactional tables in query cache & added transaction-live memory
sql/sql_parse.cc:
  processing trunsactional tables in query cache & added transaction-live memory
sql/table.h:
  removing strlen operation from query cache
parent cf534d43
...@@ -36229,9 +36229,8 @@ If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE}, ...@@ -36229,9 +36229,8 @@ If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE},
then all cached queries that used this table (possibly through a then all cached queries that used this table (possibly through a
@code{MRG_MyISAM} table!) become invalid and are removed from the cache. @code{MRG_MyISAM} table!) become invalid and are removed from the cache.
Currently all @code{InnoDB} tables are invalidated on @code{COMMIT}, Changed transactional @code{InnoDB} tables will be invalidated on
in the future this will be changed so only tables changed in the @code{COMMIT}.
transaction cause the corresponding cache entries to be invalidated.
A query cannot be cached if it contains one of the functions: A query cannot be cached if it contains one of the functions:
@multitable @columnfractions .25 .25 .25 .25 @multitable @columnfractions .25 .25 .25 .25
drop table if exists t1; drop table if exists t1, t2, t3;
flush status;
set autocommit=0; set autocommit=0;
create table t1 (a int not null) type=innodb; create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
...@@ -13,3 +14,87 @@ Qcache_queries_in_cache 0 ...@@ -13,3 +14,87 @@ Qcache_queries_in_cache 0
drop table t1; drop table t1;
commit; commit;
set autocommit=1; set autocommit=1;
begin;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
create table t1 (a int not null) type=innodb;
create table t2 (a int not null) type=innodb;
create table t3 (a int not null) type=innodb;
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
begin;
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
insert into t1 values (3);
insert into t2 values (3);
insert into t1 values (4);
select * from t1;
a
1
2
3
4
select * from t2;
a
1
2
3
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
commit;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
# #
# Without auto_commit. # Without auto_commit.
# #
drop table if exists t1; drop table if exists t1, t2, t3;
flush status;
set autocommit=0; set autocommit=0;
create table t1 (a int not null) type=innodb; create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
...@@ -12,3 +13,37 @@ show status like "Qcache_queries_in_cache"; ...@@ -12,3 +13,37 @@ show status like "Qcache_queries_in_cache";
drop table t1; drop table t1;
commit; commit;
set autocommit=1; set autocommit=1;
begin;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
commit;
create table t1 (a int not null) type=innodb;
create table t2 (a int not null) type=innodb;
create table t3 (a int not null) type=innodb;
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
begin;
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
insert into t1 values (3);
insert into t2 values (3);
insert into t1 values (4);
select * from t1;
select * from t2;
select * from t3;
show status like "Qcache_queries_in_cache";
show status like "Qcache_hits";
commit;
show status like "Qcache_queries_in_cache";
\ No newline at end of file
...@@ -271,7 +271,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) ...@@ -271,7 +271,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
if (opt_using_transactions) if (opt_using_transactions)
{ {
bool operation_done=0; bool operation_done= 0;
bool transaction_commited= 0;
/* Update the binary log if we have cached some queries */ /* Update the binary log if we have cached some queries */
if (trans == &thd->transaction.all && mysql_bin_log.is_open() && if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
my_b_tell(&thd->transaction.trans_log)) my_b_tell(&thd->transaction.trans_log))
...@@ -289,6 +290,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) ...@@ -289,6 +290,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
error=1; error=1;
} }
else
transaction_commited= 1;
trans->bdb_tid=0; trans->bdb_tid=0;
} }
#endif #endif
...@@ -302,12 +305,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) ...@@ -302,12 +305,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
} }
trans->innodb_active_trans=0; trans->innodb_active_trans=0;
if (trans == &thd->transaction.all) if (trans == &thd->transaction.all)
{ operation_done= transaction_commited= 1;
query_cache.invalidate(Query_cache_table::INNODB);
operation_done=1;
}
} }
#endif #endif
if (transaction_commited)
query_cache.invalidate(thd->transaction.changed_tables);
if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) if (error && trans == &thd->transaction.all && mysql_bin_log.is_open())
sql_print_error("Error: Got error during commit; Binlog is not up to date!"); sql_print_error("Error: Got error during commit; Binlog is not up to date!");
thd->tx_isolation=thd->session_tx_isolation; thd->tx_isolation=thd->session_tx_isolation;
......
...@@ -271,8 +271,6 @@ If join_results allocated new block(s) then we need call pack_cache again. ...@@ -271,8 +271,6 @@ If join_results allocated new block(s) then we need call pack_cache again.
TODO list: TODO list:
- Invalidate queries that use innoDB tables changed in transaction & remove
invalidation by table type
- Delayed till after-parsing qache answer (for column rights processing) - Delayed till after-parsing qache answer (for column rights processing)
- Optimize cache resizing - Optimize cache resizing
- if new_size < old_size then pack & shrink - if new_size < old_size then pack & shrink
...@@ -280,8 +278,6 @@ TODO list: ...@@ -280,8 +278,6 @@ TODO list:
- Move MRG_MYISAM table type processing to handlers, something like: - Move MRG_MYISAM table type processing to handlers, something like:
tables_used->table->file->register_used_filenames(callback, tables_used->table->file->register_used_filenames(callback,
first_argument); first_argument);
- In Query_cache::insert_table eliminate strlen(). To do this we have to
add db_len to the TABLE_LIST and TABLE structures.
*/ */
#include "mysql_priv.h" #include "mysql_priv.h"
...@@ -1030,7 +1026,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1030,7 +1026,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Remove all cached queries that uses any of the tables in the list Remove all cached queries that uses any of the tables in the list
*/ */
void Query_cache::invalidate(TABLE_LIST *tables_used) void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
my_bool using_transactions)
{ {
DBUG_ENTER("Query_cache::invalidate (table list)"); DBUG_ENTER("Query_cache::invalidate (table list)");
if (query_cache_size > 0) if (query_cache_size > 0)
...@@ -1039,54 +1036,76 @@ void Query_cache::invalidate(TABLE_LIST *tables_used) ...@@ -1039,54 +1036,76 @@ void Query_cache::invalidate(TABLE_LIST *tables_used)
if (query_cache_size > 0) if (query_cache_size > 0)
{ {
DUMP(this); DUMP(this);
using_transactions = using_transactions &&
(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN));
for ( ; tables_used; tables_used=tables_used->next) for ( ; tables_used; tables_used=tables_used->next)
invalidate_table(tables_used); {
DBUG_ASSERT(!using_transactions || tables_used->table!=0);
if (using_transactions &&
tables_used->table->file->has_transactions())
/*
Tables_used->table can't be 0 in transaction.
Only 'drop' invalidate not opened table, but 'drop'
force transaction finish.
*/
thd->add_changed_table(tables_used->table);
else
invalidate_table(tables_used);
}
} }
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
Remove all cached queries that uses the given table
*/
void Query_cache::invalidate(TABLE *table)
{ {
DBUG_ENTER("Query_cache::invalidate (table)"); DBUG_ENTER("Query_cache::invalidate (changed table list)");
if (query_cache_size > 0) if (query_cache_size > 0 && tables_used)
{ {
STRUCT_LOCK(&structure_guard_mutex); STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0) if (query_cache_size > 0)
invalidate_table(table); {
DUMP(this);
for ( ; tables_used; tables_used=tables_used->next)
{
invalidate_table(tables_used->key, tables_used->key_length);
DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key,
tables_used->table_name));
}
}
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
Remove all cached queries that uses the given table type. Remove all cached queries that uses the given table
*/ */
void Query_cache::invalidate(Query_cache_table::query_cache_table_type type) void Query_cache::invalidate(THD *thd, TABLE *table,
my_bool using_transactions)
{ {
DBUG_ENTER("Query_cache::invalidate (type)"); DBUG_ENTER("Query_cache::invalidate (table)");
if (query_cache_size > 0) if (query_cache_size > 0)
{ {
STRUCT_LOCK(&structure_guard_mutex); STRUCT_LOCK(&structure_guard_mutex);
DUMP(this);
if (query_cache_size > 0) if (query_cache_size > 0)
{ {
/* invalidate_table reduce list while only root of list remain */ using_transactions = using_transactions &&
while (tables_blocks[type] != 0) (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN));
invalidate_table(tables_blocks[type]); if (using_transactions && table->file->has_transactions())
thd->add_changed_table(table);
else
invalidate_table(table);
} }
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
Remove all cached queries that uses the given database Remove all cached queries that uses the given database
*/ */
...@@ -1100,12 +1119,9 @@ void Query_cache::invalidate(char *db) ...@@ -1100,12 +1119,9 @@ void Query_cache::invalidate(char *db)
if (query_cache_size > 0) if (query_cache_size > 0)
{ {
DUMP(this); DUMP(this);
for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++)
{
/* invalidate_table reduce list while only root of list remain */ /* invalidate_table reduce list while only root of list remain */
while (tables_blocks[i] !=0 ) while (tables_blocks !=0 )
invalidate_table(tables_blocks[i]); invalidate_table(tables_blocks);
}
} }
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
} }
...@@ -1120,7 +1136,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename) ...@@ -1120,7 +1136,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
{ {
/* Calculate the key outside the lock to make the lock shorter */ /* Calculate the key outside the lock to make the lock shorter */
char key[MAX_DBKEY_LENGTH]; char key[MAX_DBKEY_LENGTH];
uint key_length= filename_2_table_key(key, filename); uint32 db_length;
uint key_length= filename_2_table_key(key, filename, &db_length);
STRUCT_LOCK(&structure_guard_mutex); STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size > 0) // Safety if cache removed if (query_cache_size > 0) // Safety if cache removed
{ {
...@@ -1800,11 +1817,15 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) ...@@ -1800,11 +1817,15 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
} }
void Query_cache::invalidate_table(TABLE *table) void Query_cache::invalidate_table(TABLE *table)
{
invalidate_table((byte*) table->table_cache_key, table->key_length);
}
void Query_cache::invalidate_table(byte * key, uint32 key_length)
{ {
Query_cache_block *table_block; Query_cache_block *table_block;
if ((table_block = ((Query_cache_block*) if ((table_block = ((Query_cache_block*)
hash_search(&tables, (byte*) table->table_cache_key, hash_search(&tables, key, key_length))))
table->key_length))))
invalidate_table(table_block); invalidate_table(table_block);
} }
...@@ -1842,8 +1863,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, ...@@ -1842,8 +1863,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
block_table->n=n; block_table->n=n;
if (!insert_table(tables_used->table->key_length, if (!insert_table(tables_used->table->key_length,
tables_used->table->table_cache_key, block_table, tables_used->table->table_cache_key, block_table,
Query_cache_table::type_convertion(tables_used->table-> tables_used->db_length))
db_type)))
break; break;
if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM)
...@@ -1855,10 +1875,12 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, ...@@ -1855,10 +1875,12 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
table++) table++)
{ {
char key[MAX_DBKEY_LENGTH]; char key[MAX_DBKEY_LENGTH];
uint key_length =filename_2_table_key(key, table->table->filename); uint32 db_length;
uint key_length =filename_2_table_key(key, table->table->filename,
&db_length);
(++block_table)->n= ++n; (++block_table)->n= ++n;
if (!insert_table(key_length, key, block_table, if (!insert_table(key_length, key, block_table,
Query_cache_table::type_convertion(DB_TYPE_MYISAM))) db_length))
goto err; goto err;
} }
} }
...@@ -1885,7 +1907,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, ...@@ -1885,7 +1907,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
my_bool my_bool
Query_cache::insert_table(uint key_len, char *key, Query_cache::insert_table(uint key_len, char *key,
Query_cache_block_table *node, Query_cache_block_table *node,
Query_cache_table::query_cache_table_type type) uint32 db_length)
{ {
DBUG_ENTER("Query_cache::insert_table"); DBUG_ENTER("Query_cache::insert_table");
DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d", DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d",
...@@ -1909,9 +1931,8 @@ Query_cache::insert_table(uint key_len, char *key, ...@@ -1909,9 +1931,8 @@ Query_cache::insert_table(uint key_len, char *key,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
Query_cache_table *header = table_block->table(); Query_cache_table *header = table_block->table();
header->type(type);
double_linked_list_simple_include(table_block, double_linked_list_simple_include(table_block,
&tables_blocks[type]); &tables_blocks);
Query_cache_block_table *list_root = table_block->table(0); Query_cache_block_table *list_root = table_block->table(0);
list_root->n = 0; list_root->n = 0;
list_root->next = list_root->prev = list_root; list_root->next = list_root->prev = list_root;
...@@ -1923,7 +1944,7 @@ Query_cache::insert_table(uint key_len, char *key, ...@@ -1923,7 +1944,7 @@ Query_cache::insert_table(uint key_len, char *key,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
char *db = header->db(); char *db = header->db();
header->table(db + strlen(db) + 1); header->table(db + db_length + 1);
} }
Query_cache_block_table *list_root = table_block->table(0); Query_cache_block_table *list_root = table_block->table(0);
...@@ -1947,7 +1968,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node) ...@@ -1947,7 +1968,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
// list is empty (neighbor is root of list) // list is empty (neighbor is root of list)
Query_cache_block *table_block = neighbour->block(); Query_cache_block *table_block = neighbour->block();
double_linked_list_exclude(table_block, double_linked_list_exclude(table_block,
&tables_blocks[table_block->table()->type()]); &tables_blocks);
hash_delete(&tables,(byte *) table_block); hash_delete(&tables,(byte *) table_block);
free_memory_block(table_block); free_memory_block(table_block);
} }
...@@ -2033,7 +2054,7 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min) ...@@ -2033,7 +2054,7 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
block=block->prev; block=block->prev;
n++; n++;
} }
if(block->length < len) if (block->length < len)
block=block->next; block=block->next;
} }
} }
...@@ -2513,8 +2534,8 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2513,8 +2534,8 @@ my_bool Query_cache::move_by_type(byte **border,
new_block->n_tables=1; new_block->n_tables=1;
memmove((char*) new_block->data(), data, len-new_block->headers_len()); memmove((char*) new_block->data(), data, len-new_block->headers_len());
relink(block, new_block, next, prev, pnext, pprev); relink(block, new_block, next, prev, pnext, pprev);
if (tables_blocks[new_block->table()->type()] == block) if (tables_blocks == block)
tables_blocks[new_block->table()->type()] = new_block; tables_blocks = new_block;
Query_cache_block_table *nlist_root = new_block->table(0); Query_cache_block_table *nlist_root = new_block->table(0);
nlist_root->n = 0; nlist_root->n = 0;
...@@ -2771,10 +2792,10 @@ my_bool Query_cache::join_results(ulong join_limit) ...@@ -2771,10 +2792,10 @@ my_bool Query_cache::join_results(ulong join_limit)
} }
uint Query_cache::filename_2_table_key (char *key, const char *path) uint Query_cache::filename_2_table_key (char *key, const char *path,
uint32 *db_length)
{ {
char tablename[FN_REFLEN+2], *filename, *dbname; char tablename[FN_REFLEN+2], *filename, *dbname;
uint db_length;
DBUG_ENTER("Query_cache::filename_2_table_key"); DBUG_ENTER("Query_cache::filename_2_table_key");
/* Safety if filename didn't have a directory name */ /* Safety if filename didn't have a directory name */
...@@ -2785,10 +2806,10 @@ uint Query_cache::filename_2_table_key (char *key, const char *path) ...@@ -2785,10 +2806,10 @@ uint Query_cache::filename_2_table_key (char *key, const char *path)
filename= tablename + dirname_length(tablename + 2) + 2; filename= tablename + dirname_length(tablename + 2) + 2;
/* Find start of databasename */ /* Find start of databasename */
for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ; for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
db_length= (filename - dbname) - 1; *db_length= (filename - dbname) - 1;
DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename)); DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename));
DBUG_RETURN((uint) (strmov(strmake(key, dbname, db_length) + 1, DBUG_RETURN((uint) (strmov(strmake(key, dbname, *db_length) + 1,
filename) -key) + 1); filename) -key) + 1);
} }
...@@ -2975,22 +2996,18 @@ void Query_cache::tables_dump() ...@@ -2975,22 +2996,18 @@ void Query_cache::tables_dump()
DBUG_PRINT("qcache", ("--------------------")); DBUG_PRINT("qcache", ("--------------------"));
DBUG_PRINT("qcache", ("TABLES")); DBUG_PRINT("qcache", ("TABLES"));
DBUG_PRINT("qcache", ("--------------------")); DBUG_PRINT("qcache", ("--------------------"));
for (int i=0; i < (int) Query_cache_table::TYPES_NUMBER; i++) if (tables_blocks != 0)
{ {
DBUG_PRINT("qcache", ("--- type %u", i)); Query_cache_block *table_block = tables_blocks;
if (tables_blocks[i] != 0) do
{ {
Query_cache_block *table_block = tables_blocks[i]; Query_cache_table *table = table_block->table();
do DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
{ table_block = table_block->next;
Query_cache_table *table = table_block->table(); } while ( table_block != tables_blocks);
DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
table_block = table_block->next;
} while ( table_block != tables_blocks[i]);
}
else
DBUG_PRINT("qcache", ("no tables in list"));
} }
else
DBUG_PRINT("qcache", ("no tables in list"));
DBUG_PRINT("qcache", ("--------------------")); DBUG_PRINT("qcache", ("--------------------"));
} }
...@@ -3082,7 +3099,7 @@ my_bool Query_cache::check_integrity(bool not_locked) ...@@ -3082,7 +3099,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
break; break;
} }
case Query_cache_block::TABLE: case Query_cache_block::TABLE:
if (in_list(tables_blocks[block->table()->type()], block, "tables")) if (in_list(tables_blocks, block, "tables"))
result = 1; result = 1;
if (in_table_list(block->table(0), block->table(0), "table list root")) if (in_table_list(block->table(0), block->table(0), "table list root"))
result = 1; result = 1;
...@@ -3197,28 +3214,25 @@ my_bool Query_cache::check_integrity(bool not_locked) ...@@ -3197,28 +3214,25 @@ my_bool Query_cache::check_integrity(bool not_locked)
} }
DBUG_PRINT("qcache", ("check tables ...")); DBUG_PRINT("qcache", ("check tables ..."));
for (i=0 ; (int) i < (int) Query_cache_table::TYPES_NUMBER; i++) if ((block = tables_blocks))
{ {
if ((block = tables_blocks[i])) do
{ {
do DBUG_PRINT("qcache", ("block 0x%lx, type %u...",
(ulong) block, (uint) block->type));
uint length;
byte *key = query_cache_table_get_key((byte*) block, &length, 0);
gptr val = hash_search(&tables, key, length);
if (((gptr)block) != val)
{ {
DBUG_PRINT("qcache", ("block 0x%lx, type %u...", DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx",
(ulong) block, (uint) block->type)); (ulong) block, (ulong) val));
uint length; }
byte *key = query_cache_table_get_key((byte*) block, &length, 0);
gptr val = hash_search(&tables, key, length); if (in_blocks(block))
if (((gptr)block) != val) result = 1;
{ block=block->next;
DBUG_PRINT("error", ("block 0x%lx found in tables hash like 0x%lx", } while (block != tables_blocks);
(ulong) block, (ulong) val));
}
if (in_blocks(block))
result = 1;
block=block->next;
} while (block != tables_blocks[i]);
}
} }
DBUG_PRINT("qcache", ("check free blocks")); DBUG_PRINT("qcache", ("check free blocks"));
......
...@@ -148,17 +148,8 @@ struct Query_cache_query ...@@ -148,17 +148,8 @@ struct Query_cache_query
struct Query_cache_table struct Query_cache_table
{ {
enum query_cache_table_type {OTHER=0, INNODB=1, TYPES_NUMBER=2};
inline static query_cache_table_type type_convertion(db_type type)
{
return (type == DB_TYPE_INNODB ? INNODB : OTHER);
}
char *tbl; char *tbl;
query_cache_table_type tp;
inline query_cache_table_type type() { return tp; }
inline void type(query_cache_table_type t) { tp = t;}
inline char *db() { return (char *) data(); } inline char *db() { return (char *) data(); }
inline char *table() { return tbl; } inline char *table() { return tbl; }
inline void table(char *table) { tbl = table; } inline void table(char *table) { tbl = table; }
...@@ -248,7 +239,7 @@ class Query_cache ...@@ -248,7 +239,7 @@ class Query_cache
byte *cache; // cache memory byte *cache; // cache memory
Query_cache_block *first_block; // physical location block list Query_cache_block *first_block; // physical location block list
Query_cache_block *queries_blocks; // query list (LIFO) Query_cache_block *queries_blocks; // query list (LIFO)
Query_cache_block *tables_blocks[Query_cache_table::TYPES_NUMBER]; Query_cache_block *tables_blocks;
Query_cache_memory_bin *bins; // free block lists Query_cache_memory_bin *bins; // free block lists
Query_cache_memory_bin_step *steps; // bins spacing info Query_cache_memory_bin_step *steps; // bins spacing info
...@@ -270,7 +261,8 @@ class Query_cache ...@@ -270,7 +261,8 @@ class Query_cache
Query_cache_block *tail_head); Query_cache_block *tail_head);
/* Table key generation */ /* Table key generation */
static uint filename_2_table_key (char *key, const char *filename); static uint filename_2_table_key (char *key, const char *filename,
uint32 *db_langth);
/* The following functions require that structure_guard_mutex is locked */ /* The following functions require that structure_guard_mutex is locked */
void flush_cache(); void flush_cache();
...@@ -282,13 +274,14 @@ class Query_cache ...@@ -282,13 +274,14 @@ class Query_cache
my_bool first_block); my_bool first_block);
void invalidate_table(TABLE_LIST *table); void invalidate_table(TABLE_LIST *table);
void invalidate_table(TABLE *table); void invalidate_table(TABLE *table);
void invalidate_table(byte *key, uint32 key_length);
void invalidate_table(Query_cache_block *table_block); void invalidate_table(Query_cache_block *table_block);
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);
my_bool insert_table(uint key_len, char *key, my_bool insert_table(uint key_len, char *key,
Query_cache_block_table *node, Query_cache_block_table *node,
Query_cache_table::query_cache_table_type type); uint32 db_length);
void unlink_table(Query_cache_block_table *node); void unlink_table(Query_cache_block_table *node);
Query_cache_block *get_free_block (ulong len, my_bool not_less, Query_cache_block *get_free_block (ulong len, my_bool not_less,
ulong min); ulong min);
...@@ -369,11 +362,10 @@ class Query_cache ...@@ -369,11 +362,10 @@ class Query_cache
int send_result_to_client(THD *thd, char *query, uint query_length); int send_result_to_client(THD *thd, char *query, uint query_length);
/* Remove all queries that uses any of the listed following tables */ /* Remove all queries that uses any of the listed following tables */
void invalidate(TABLE_LIST *tables_used); void invalidate(THD* thd, TABLE_LIST *tables_used,
void invalidate(TABLE *table); my_bool using_transactions);
void invalidate(CHANGED_TABLE_LIST *tables_used);
/* Remove all queries that uses tables of pointed type*/ void invalidate(THD* thd, TABLE *table, my_bool using_transactions);
void invalidate(Query_cache_table::query_cache_table_type type);
/* Remove all queries that uses any of the tables in following database */ /* Remove all queries that uses any of the tables in following database */
void invalidate(char *db); void invalidate(char *db);
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#ifdef __WIN__ #ifdef __WIN__
#include <io.h> #include <io.h>
#endif #endif
#include <mysys_err.h>
#include <assert.h>
/***************************************************************************** /*****************************************************************************
** Instansiate templates ** Instansiate templates
...@@ -105,6 +107,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -105,6 +107,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
net.vio=0; net.vio=0;
ull=0; ull=0;
system_thread=cleanup_done=0; system_thread=cleanup_done=0;
transaction.changed_tables = 0;
#ifdef __WIN__ #ifdef __WIN__
real_id = 0; real_id = 0;
#endif #endif
...@@ -136,6 +139,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -136,6 +139,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */ /* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root)); bzero((char*) &mem_root,sizeof(mem_root));
bzero((char*) &transaction.mem_root,sizeof(transaction.mem_root));
user_connect=(UC *)0; user_connect=(UC *)0;
hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0, hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0,
(hash_get_key) get_var_key, (hash_get_key) get_var_key,
...@@ -211,6 +215,7 @@ THD::~THD() ...@@ -211,6 +215,7 @@ THD::~THD()
safeFree(db); safeFree(db);
safeFree(ip); safeFree(ip);
free_root(&mem_root,MYF(0)); free_root(&mem_root,MYF(0));
free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed) mysys_var=0; // Safety (shouldn't be needed)
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
pthread_mutex_destroy(&active_vio_lock); pthread_mutex_destroy(&active_vio_lock);
...@@ -255,6 +260,88 @@ bool THD::store_globals() ...@@ -255,6 +260,88 @@ bool THD::store_globals()
my_pthread_setspecific_ptr(THR_NET, &net)); my_pthread_setspecific_ptr(THR_NET, &net));
} }
/* routings to adding tables to list of changed in transaction tables */
inline static void list_include(CHANGED_TABLE_LIST** prev,
CHANGED_TABLE_LIST* curr,
CHANGED_TABLE_LIST* new_table)
{
if (new_table)
{
*prev = new_table;
(*prev)->next = curr;
}
}
/* add table to list of changed in transaction tables */
void THD::add_changed_table(TABLE *table)
{
DBUG_ENTER("THD::add_changed_table (table)");
DBUG_ASSERT((options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)) &&
table->file->has_transactions());
CHANGED_TABLE_LIST** prev = &transaction.changed_tables;
CHANGED_TABLE_LIST* curr = transaction.changed_tables;
for(; curr; prev = &(curr->next), curr = curr->next)
{
int cmp = (long)curr->key_length - (long)table->key_length;
if (cmp < 0)
{
list_include(prev, curr, changed_table_dup(table));
DBUG_PRINT("info",
("key_length %u %u", table->key_length, (*prev)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
{
cmp = memcmp(curr->key ,table->table_cache_key, curr->key_length);
if (cmp < 0)
{
list_include(prev, curr, changed_table_dup(table));
DBUG_PRINT("info",
("key_length %u %u", table->key_length, (*prev)->key_length));
DBUG_VOID_RETURN;
}
else if (cmp == 0)
{
DBUG_PRINT("info", ("already in list"));
DBUG_VOID_RETURN;
}
}
}
*prev = changed_table_dup(table);
DBUG_PRINT("info", ("key_length %u %u", table->key_length, (*prev)->key_length));
DBUG_VOID_RETURN;
}
CHANGED_TABLE_LIST* THD::changed_table_dup(TABLE *table)
{
CHANGED_TABLE_LIST* new_table =
(CHANGED_TABLE_LIST*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))+
table->key_length + 1);
if (!new_table)
{
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
ALIGN_SIZE(sizeof(TABLE_LIST)) + table->key_length + 1);
killed= 1;
return 0;
}
new_table->key = (char *) (((byte*)new_table)+
ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST)));
new_table->next = 0;
new_table->key_length = table->key_length;
uint32 db_len = ((new_table->table_name =
::strmake(new_table->key, table->table_cache_key,
table->key_length) + 1) - new_table->key);
::memcpy(new_table->key + db_len, table->table_cache_key + db_len,
table->key_length - db_len);
return new_table;
}
/***************************************************************************** /*****************************************************************************
** Functions to provide a interface to select results ** Functions to provide a interface to select results
*****************************************************************************/ *****************************************************************************/
......
...@@ -258,7 +258,7 @@ class THD :public ilink { ...@@ -258,7 +258,7 @@ class THD :public ilink {
public: public:
NET net; // client connection descriptor NET net; // client connection descriptor
LEX lex; // parse tree descriptor LEX lex; // parse tree descriptor
MEM_ROOT mem_root; // memory allocation pool MEM_ROOT mem_root; // 1 command-life memory allocation pool
HASH user_vars; // hash for user variables HASH user_vars; // hash for user variables
String packet; // dynamic string buffer used for network I/O String packet; // dynamic string buffer used for network I/O
struct sockaddr_in remote; // client socket address struct sockaddr_in remote; // client socket address
...@@ -326,6 +326,19 @@ class THD :public ilink { ...@@ -326,6 +326,19 @@ class THD :public ilink {
THD_TRANS all; // Trans since BEGIN WORK THD_TRANS all; // Trans since BEGIN WORK
THD_TRANS stmt; // Trans for current statement THD_TRANS stmt; // Trans for current statement
uint bdb_lock_count; uint bdb_lock_count;
/*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
cache (instead of full list of changed in transaction tables).
*/
CHANGED_TABLE_LIST* changed_tables;
MEM_ROOT mem_root; // Transaction-life memory allocation pool
void cleanup()
{
changed_tables = 0;
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
}
} transaction; } transaction;
Item *free_list, *handler_items; Item *free_list, *handler_items;
CONVERT *convert_set; CONVERT *convert_set;
...@@ -374,7 +387,7 @@ class THD :public ilink { ...@@ -374,7 +387,7 @@ class THD :public ilink {
ulong slave_proxy_id; ulong slave_proxy_id;
NET* slave_net; // network connection from slave -> m. NET* slave_net; // network connection from slave -> m.
my_off_t log_pos; my_off_t log_pos;
THD(); THD();
~THD(); ~THD();
void cleanup(void); void cleanup(void);
...@@ -471,6 +484,12 @@ class THD :public ilink { ...@@ -471,6 +484,12 @@ class THD :public ilink {
memcpy(ptr,str,size); memcpy(ptr,str,size);
return ptr; return ptr;
} }
inline gptr trans_alloc(unsigned int size)
{
return alloc_root(&transaction.mem_root,size);
}
void add_changed_table(TABLE *table);
CHANGED_TABLE_LIST * changed_table_dup(TABLE *table);
}; };
......
...@@ -182,7 +182,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -182,7 +182,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
thd->lock=0; thd->lock=0;
} }
if (deleted) if (deleted)
query_cache.invalidate(table_list); query_cache.invalidate(thd, table_list, 1);
delete select; delete select;
if (error >= 0) // Fatal error if (error >= 0) // Fatal error
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0); send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN: 0);
...@@ -470,7 +470,7 @@ bool multi_delete::send_eof() ...@@ -470,7 +470,7 @@ bool multi_delete::send_eof()
VOID(ha_autocommit_or_rollback(thd,error > 0)); VOID(ha_autocommit_or_rollback(thd,error > 0));
} }
if (deleted) if (deleted)
query_cache.invalidate(delete_tables); query_cache.invalidate(thd, delete_tables, 1);
::send_ok(&thd->net,deleted); ::send_ok(&thd->net,deleted);
return 0; return 0;
} }
...@@ -548,7 +548,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) ...@@ -548,7 +548,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
bzero((char*) &create_info,sizeof(create_info)); bzero((char*) &create_info,sizeof(create_info));
*fn_ext(path)=0; // Remove the .frm extension *fn_ext(path)=0; // Remove the .frm extension
error= ha_create_table(path,&create_info,1) ? -1 : 0; error= ha_create_table(path,&create_info,1) ? -1 : 0;
query_cache.invalidate(table_list); query_cache.invalidate(thd, table_list, 0);
if (!dont_send_ok) if (!dont_send_ok)
{ {
......
...@@ -311,7 +311,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields, ...@@ -311,7 +311,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
} }
thd->proc_info="end"; thd->proc_info="end";
if (info.copied || info.deleted) if (info.copied || info.deleted)
query_cache.invalidate(table_list); query_cache.invalidate(thd, table_list, 1);
table->time_stamp=save_time_stamp; // Restore auto timestamp ptr table->time_stamp=save_time_stamp; // Restore auto timestamp ptr
table->next_number_field=0; table->next_number_field=0;
thd->count_cuted_fields=0; thd->count_cuted_fields=0;
...@@ -1217,7 +1217,7 @@ bool delayed_insert::handle_inserts(void) ...@@ -1217,7 +1217,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error("%s",thd.net.last_error); sql_print_error("%s",thd.net.last_error);
goto err; goto err;
} }
query_cache.invalidate(table); query_cache.invalidate(&thd, table, 1);
if (thr_reschedule_write_lock(*thd.lock->locks)) if (thr_reschedule_write_lock(*thd.lock->locks))
{ {
/* This should never happen */ /* This should never happen */
...@@ -1242,7 +1242,7 @@ bool delayed_insert::handle_inserts(void) ...@@ -1242,7 +1242,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error("%s",thd.net.last_error); sql_print_error("%s",thd.net.last_error);
goto err; goto err;
} }
query_cache.invalidate(table); query_cache.invalidate(&thd, table, 1);
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -1330,7 +1330,7 @@ void select_insert::send_error(uint errcode,const char *err) ...@@ -1330,7 +1330,7 @@ void select_insert::send_error(uint errcode,const char *err)
table->file->activate_all_index(thd); table->file->activate_all_index(thd);
ha_rollback_stmt(thd); ha_rollback_stmt(thd);
if (info.copied || info.deleted) if (info.copied || info.deleted)
query_cache.invalidate(table); query_cache.invalidate(thd, table, 1);
} }
...@@ -1343,7 +1343,7 @@ bool select_insert::send_eof() ...@@ -1343,7 +1343,7 @@ bool select_insert::send_eof()
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
error=error2; error=error2;
if (info.copied || info.deleted) if (info.copied || info.deleted)
query_cache.invalidate(table); query_cache.invalidate(thd, table, 1);
if (error) if (error)
{ {
......
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8 #define SCRAMBLE_LENGTH 8
#define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192
#define TRANS_MEM_ROOT_BLOCK_SIZE 4096
#define TRANS_MEM_ROOT_PREALLOC 4096
extern int yyparse(void); extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" pthread_mutex_t THR_LOCK_keycache;
...@@ -615,7 +619,9 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -615,7 +619,9 @@ pthread_handler_decl(handle_one_connection,arg)
thd->command=COM_SLEEP; thd->command=COM_SLEEP;
thd->version=refresh_version; thd->version=refresh_version;
thd->set_time(); thd->set_time();
init_sql_alloc(&thd->mem_root,8192,8192); init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
init_sql_alloc(&thd->transaction.mem_root,
TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC);
while (!net->error && net->vio != 0 && !thd->killed) while (!net->error && net->vio != 0 && !thd->killed)
{ {
if (do_command(thd)) if (do_command(thd))
...@@ -688,7 +694,9 @@ pthread_handler_decl(handle_bootstrap,arg) ...@@ -688,7 +694,9 @@ pthread_handler_decl(handle_bootstrap,arg)
thd->priv_user=thd->user=(char*)"boot"; thd->priv_user=thd->user=(char*)"boot";
buff= (char*) thd->net.buff; buff= (char*) thd->net.buff;
init_sql_alloc(&thd->mem_root,8192,8192); init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
init_sql_alloc(&thd->transaction.mem_root,
TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC);
while (fgets(buff, thd->net.max_packet, file)) while (fgets(buff, thd->net.max_packet, file))
{ {
uint length=(uint) strlen(buff); uint length=(uint) strlen(buff);
...@@ -712,6 +720,7 @@ pthread_handler_decl(handle_bootstrap,arg) ...@@ -712,6 +720,7 @@ pthread_handler_decl(handle_bootstrap,arg)
if (thd->fatal_error) if (thd->fatal_error)
break; break;
free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC)); free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
} }
thd->priv_user=thd->user=0; thd->priv_user=thd->user=0;
...@@ -1084,6 +1093,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1084,6 +1093,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
close_connection(net); close_connection(net);
close_thread_tables(thd); // Free before kill close_thread_tables(thd); // Free before kill
free_root(&thd->mem_root,MYF(0)); free_root(&thd->mem_root,MYF(0));
free_root(&thd->transaction.mem_root,MYF(0));
kill_mysql(); kill_mysql();
error=TRUE; error=TRUE;
break; break;
...@@ -1620,7 +1630,7 @@ mysql_execute_command(void) ...@@ -1620,7 +1630,7 @@ mysql_execute_command(void)
goto error; goto error;
} }
} }
query_cache.invalidate(tables); query_cache.invalidate(thd, tables, 0);
if (end_active_trans(thd)) if (end_active_trans(thd))
res= -1; res= -1;
else if (mysql_rename_tables(thd,tables)) else if (mysql_rename_tables(thd,tables))
...@@ -1659,7 +1669,7 @@ mysql_execute_command(void) ...@@ -1659,7 +1669,7 @@ mysql_execute_command(void)
check_table_access(thd,SELECT_ACL | INSERT_ACL, tables)) check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
res = mysql_repair_table(thd, tables, &lex->check_opt); res = mysql_repair_table(thd, tables, &lex->check_opt);
query_cache.invalidate(tables); query_cache.invalidate(thd, tables, 0);
break; break;
} }
case SQLCOM_CHECK: case SQLCOM_CHECK:
...@@ -1668,7 +1678,7 @@ mysql_execute_command(void) ...@@ -1668,7 +1678,7 @@ mysql_execute_command(void)
check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables)) check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
res = mysql_check_table(thd, tables, &lex->check_opt); res = mysql_check_table(thd, tables, &lex->check_opt);
query_cache.invalidate(tables); query_cache.invalidate(thd, tables, 0);
break; break;
} }
case SQLCOM_ANALYZE: case SQLCOM_ANALYZE:
...@@ -2392,6 +2402,7 @@ mysql_execute_command(void) ...@@ -2392,6 +2402,7 @@ mysql_execute_command(void)
} }
else else
res= -1; res= -1;
thd->transaction.cleanup();
break; break;
} }
case SQLCOM_ROLLBACK: case SQLCOM_ROLLBACK:
...@@ -2406,6 +2417,7 @@ mysql_execute_command(void) ...@@ -2406,6 +2417,7 @@ mysql_execute_command(void)
else else
res= -1; res= -1;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE); thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->transaction.cleanup();
break; break;
default: /* Impossible */ default: /* Impossible */
send_ok(&thd->net); send_ok(&thd->net);
...@@ -3108,7 +3120,22 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3108,7 +3120,22 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
DBUG_RETURN(0); /* purecov: inspected */ DBUG_RETURN(0); /* purecov: inspected */
ptr->db= table->db.str ? table->db.str : (thd->db ? thd->db : (char*) ""); if (table->db.str)
{
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
else if (thd->db)
{
ptr->db= thd->db;
ptr->db_length= thd->db_length;
}
else
{
ptr->db= (char*) "";
ptr->db_length= 0;
}
ptr->name=alias_str; ptr->name=alias_str;
if (lower_case_table_names) if (lower_case_table_names)
{ {
...@@ -3116,6 +3143,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ...@@ -3116,6 +3143,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
casedn_str(table->table.str); casedn_str(table->table.str);
} }
ptr->real_name=table->table.str; ptr->real_name=table->table.str;
ptr->real_name_length=table->table.length;
ptr->lock_type=flags; ptr->lock_type=flags;
ptr->updating=updating; ptr->updating=updating;
if (use_index) if (use_index)
......
...@@ -161,7 +161,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -161,7 +161,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
} }
if (some_tables_deleted) if (some_tables_deleted)
{ {
query_cache.invalidate(tables); query_cache.invalidate(thd, tables, 0);
if (!dont_log_query) if (!dont_log_query)
{ {
mysql_update_log.write(thd, thd->query,thd->query_length); mysql_update_log.write(thd, thd->query,thd->query_length);
...@@ -1774,7 +1774,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1774,7 +1774,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID(pthread_cond_broadcast(&COND_refresh)); VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table=0; // For query cache table_list->table=0; // For query cache
query_cache.invalidate(table_list); query_cache.invalidate(thd, table_list, 0);
end_temporary: end_temporary:
sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted), sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted),
......
...@@ -324,7 +324,8 @@ int mysql_update(THD *thd, ...@@ -324,7 +324,8 @@ int mysql_update(THD *thd,
thd->lock=0; thd->lock=0;
} }
if (updated) if (updated)
query_cache.invalidate(table_list); query_cache.invalidate(thd, table_list, 1);
delete select; delete select;
if (error >= 0) if (error >= 0)
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
...@@ -787,7 +788,8 @@ bool multi_update::send_eof() ...@@ -787,7 +788,8 @@ bool multi_update::send_eof()
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated, sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
(long) thd->cuted_fields); (long) thd->cuted_fields);
if (updated) if (updated)
query_cache.invalidate(update_tables); query_cache.invalidate(thd, update_tables, 1);
::send_ok(&thd->net, ::send_ok(&thd->net,
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated, (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
thd->insert_id_used ? thd->insert_id() : 0L,buff); thd->insert_id_used ? thd->insert_id() : 0L,buff);
......
...@@ -137,6 +137,7 @@ struct st_table { ...@@ -137,6 +137,7 @@ struct st_table {
typedef struct st_table_list { typedef struct st_table_list {
struct st_table_list *next; struct st_table_list *next;
char *db,*name,*real_name; char *db,*name,*real_name;
uint32 db_length, real_name_length;
Item *on_expr; /* Used with outer join */ Item *on_expr; /* Used with outer join */
struct st_table_list *natural_join; /* natural join on this table*/ struct st_table_list *natural_join; /* natural join on this table*/
List<String> *use_index,*ignore_index; List<String> *use_index,*ignore_index;
...@@ -149,6 +150,12 @@ typedef struct st_table_list { ...@@ -149,6 +150,12 @@ typedef struct st_table_list {
bool shared; /* Used twice in union */ bool shared; /* Used twice in union */
} TABLE_LIST; } TABLE_LIST;
typedef struct st_changed_table_list {
struct st_changed_table_list *next;
char *key, *table_name;
uint32 key_length;
} CHANGED_TABLE_LIST;
typedef struct st_open_table_list typedef struct st_open_table_list
{ {
struct st_open_table_list *next; struct st_open_table_list *next;
......
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