mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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
This commit is contained in:
@ -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
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
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
|
|||||||
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 @@
|
|||||||
#
|
#
|
||||||
# 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";
|
|||||||
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";
|
@ -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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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;
|
||||||
|
146
sql/sql_cache.cc
146
sql/sql_cache.cc
@ -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:
|
|||||||
- 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 @@ err:
|
|||||||
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,9 +1036,45 @@ 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)
|
||||||
|
{
|
||||||
|
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);
|
invalidate_table(tables_used);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
STRUCT_UNLOCK(&structure_guard_mutex);
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Query_cache::invalidate (changed table list)");
|
||||||
|
if (query_cache_size > 0 && tables_used)
|
||||||
|
{
|
||||||
|
STRUCT_LOCK(&structure_guard_mutex);
|
||||||
|
if (query_cache_size > 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
@ -1051,42 +1084,28 @@ void Query_cache::invalidate(TABLE_LIST *tables_used)
|
|||||||
Remove all cached queries that uses the given table
|
Remove all cached queries that uses the given table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Query_cache::invalidate(TABLE *table)
|
void Query_cache::invalidate(THD *thd, TABLE *table,
|
||||||
|
my_bool using_transactions)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::invalidate (table)");
|
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);
|
||||||
if (query_cache_size > 0)
|
if (query_cache_size > 0)
|
||||||
|
{
|
||||||
|
using_transactions = using_transactions &&
|
||||||
|
(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN));
|
||||||
|
if (using_transactions && table->file->has_transactions())
|
||||||
|
thd->add_changed_table(table);
|
||||||
|
else
|
||||||
invalidate_table(table);
|
invalidate_table(table);
|
||||||
STRUCT_UNLOCK(&structure_guard_mutex);
|
|
||||||
}
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove all cached queries that uses the given table type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("Query_cache::invalidate (type)");
|
|
||||||
if (query_cache_size > 0)
|
|
||||||
{
|
|
||||||
STRUCT_LOCK(&structure_guard_mutex);
|
|
||||||
DUMP(this);
|
|
||||||
if (query_cache_size > 0)
|
|
||||||
{
|
|
||||||
/* invalidate_table reduce list while only root of list remain */
|
|
||||||
while (tables_blocks[type] != 0)
|
|
||||||
invalidate_table(tables_blocks[type]);
|
|
||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
/* 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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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 @@ err:
|
|||||||
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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
// 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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
|||||||
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()
|
|||||||
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)
|
|
||||||
{
|
|
||||||
Query_cache_block *table_block = tables_blocks[i];
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Query_cache_table *table = table_block->table();
|
Query_cache_table *table = table_block->table();
|
||||||
DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
|
DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
|
||||||
table_block = table_block->next;
|
table_block = table_block->next;
|
||||||
} while ( table_block != tables_blocks[i]);
|
} while ( table_block != tables_blocks);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DBUG_PRINT("qcache", ("no tables in list"));
|
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)
|
|||||||
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,9 +3214,7 @@ 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
|
||||||
{
|
{
|
||||||
@ -3217,8 +3232,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
|
|||||||
if (in_blocks(block))
|
if (in_blocks(block))
|
||||||
result = 1;
|
result = 1;
|
||||||
block=block->next;
|
block=block->next;
|
||||||
} while (block != tables_blocks[i]);
|
} while (block != tables_blocks);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("qcache", ("check free blocks"));
|
DBUG_PRINT("qcache", ("check free blocks"));
|
||||||
|
@ -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 @@ protected:
|
|||||||
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 @@ protected:
|
|||||||
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 @@ protected:
|
|||||||
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 @@ protected:
|
|||||||
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 @@
|
|||||||
#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),
|
|||||||
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),
|
|||||||
|
|
||||||
/* 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()
|
|||||||
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()
|
|||||||
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 {
|
|||||||
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 @@ public:
|
|||||||
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;
|
||||||
@ -471,6 +484,12 @@ public:
|
|||||||
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 @@ cleanup:
|
|||||||
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()
|
|||||||
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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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()
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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,
|
|||||||
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,
|
|||||||
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()
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user