Loading Docs/manual.texi +2 −3 Original line number Diff line number Diff line Loading @@ -36304,9 +36304,8 @@ If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE}, then all cached queries that used this table (possibly through a @code{MRG_MyISAM} table!) become invalid and are removed from the cache. Currently all @code{InnoDB} tables are invalidated on @code{COMMIT}, in the future this will be changed so only tables changed in the transaction cause the corresponding cache entries to be invalidated. Changed transactional @code{InnoDB} tables will be invalidated on @code{COMMIT}. A query cannot be cached if it contains one of the functions: @multitable @columnfractions .25 .25 .25 .25 mysql-test/r/innodb_cache.result +86 −1 Original line number Diff line number Diff line drop table if exists t1; drop table if exists t1, t2, t3; flush status; set autocommit=0; create table t1 (a int not null) type=innodb; insert into t1 values (1),(2),(3); Loading @@ -13,3 +14,87 @@ Qcache_queries_in_cache 0 drop table t1; commit; 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 mysql-test/t/innodb_cache.test +36 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,8 @@ # # Without auto_commit. # drop table if exists t1; drop table if exists t1, t2, t3; flush status; set autocommit=0; create table t1 (a int not null) type=innodb; insert into t1 values (1),(2),(3); Loading @@ -12,3 +13,37 @@ show status like "Qcache_queries_in_cache"; drop table t1; commit; 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 sql/handler.cc +8 −5 Original line number Diff line number Diff line Loading @@ -272,6 +272,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) if (opt_using_transactions) { bool operation_done= 0; bool transaction_commited= 0; /* Update the binary log if we have cached some queries */ if (trans == &thd->transaction.all && mysql_bin_log.is_open() && my_b_tell(&thd->transaction.trans_log)) Loading @@ -289,6 +290,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); error=1; } else transaction_commited= 1; trans->bdb_tid=0; } #endif Loading @@ -302,12 +305,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) } trans->innodb_active_trans=0; if (trans == &thd->transaction.all) { query_cache.invalidate(Query_cache_table::INNODB); operation_done=1; } operation_done= transaction_commited= 1; } #endif if (transaction_commited) query_cache.invalidate(thd->transaction.changed_tables); 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!"); thd->tx_isolation=thd->session_tx_isolation; Loading sql/sql_cache.cc +94 −80 Original line number Diff line number Diff line Loading @@ -271,8 +271,6 @@ If join_results allocated new block(s) then we need call pack_cache again. 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) - Optimize cache resizing - if new_size < old_size then pack & shrink Loading @@ -280,8 +278,6 @@ TODO list: - Move MRG_MYISAM table type processing to handlers, something like: tables_used->table->file->register_used_filenames(callback, 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" Loading Loading @@ -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 */ 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)"); if (query_cache_size > 0) Loading @@ -1039,54 +1036,76 @@ void Query_cache::invalidate(TABLE_LIST *tables_used) if (query_cache_size > 0) { DUMP(this); using_transactions = using_transactions && (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)); 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); } } STRUCT_UNLOCK(&structure_guard_mutex); } DBUG_VOID_RETURN; } /* Remove all cached queries that uses the given table */ void Query_cache::invalidate(TABLE *table) void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) { DBUG_ENTER("Query_cache::invalidate (table)"); if (query_cache_size > 0) 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) 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); } 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) { 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]); 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); } STRUCT_UNLOCK(&structure_guard_mutex); } DBUG_VOID_RETURN; } /* Remove all cached queries that uses the given database */ Loading @@ -1100,12 +1119,9 @@ void Query_cache::invalidate(char *db) if (query_cache_size > 0) { DUMP(this); for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++) { /* invalidate_table reduce list while only root of list remain */ while (tables_blocks[i] !=0 ) invalidate_table(tables_blocks[i]); } while (tables_blocks !=0 ) invalidate_table(tables_blocks); } STRUCT_UNLOCK(&structure_guard_mutex); } Loading @@ -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 */ 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); if (query_cache_size > 0) // Safety if cache removed { Loading Loading @@ -1800,11 +1817,15 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) } 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; if ((table_block = ((Query_cache_block*) hash_search(&tables, (byte*) table->table_cache_key, table->key_length)))) hash_search(&tables, key, key_length)))) invalidate_table(table_block); } Loading Loading @@ -1842,8 +1863,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, block_table->n=n; if (!insert_table(tables_used->table->key_length, tables_used->table->table_cache_key, block_table, Query_cache_table::type_convertion(tables_used->table-> db_type))) tables_used->db_length)) break; if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) Loading @@ -1855,10 +1875,12 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, table++) { 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; if (!insert_table(key_length, key, block_table, Query_cache_table::type_convertion(DB_TYPE_MYISAM))) db_length)) goto err; } } Loading @@ -1885,7 +1907,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, my_bool Query_cache::insert_table(uint key_len, char *key, Query_cache_block_table *node, Query_cache_table::query_cache_table_type type) uint32 db_length) { DBUG_ENTER("Query_cache::insert_table"); DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d", Loading @@ -1909,9 +1931,8 @@ Query_cache::insert_table(uint key_len, char *key, DBUG_RETURN(0); } Query_cache_table *header = table_block->table(); header->type(type); double_linked_list_simple_include(table_block, &tables_blocks[type]); &tables_blocks); Query_cache_block_table *list_root = table_block->table(0); list_root->n = 0; list_root->next = list_root->prev = list_root; Loading @@ -1923,7 +1944,7 @@ Query_cache::insert_table(uint key_len, char *key, DBUG_RETURN(0); } 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); Loading @@ -1947,7 +1968,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node) // list is empty (neighbor is root of list) Query_cache_block *table_block = neighbour->block(); double_linked_list_exclude(table_block, &tables_blocks[table_block->table()->type()]); &tables_blocks); hash_delete(&tables,(byte *) table_block); free_memory_block(table_block); } Loading Loading @@ -2513,8 +2534,8 @@ my_bool Query_cache::move_by_type(byte **border, new_block->n_tables=1; memmove((char*) new_block->data(), data, len-new_block->headers_len()); relink(block, new_block, next, prev, pnext, pprev); if (tables_blocks[new_block->table()->type()] == block) tables_blocks[new_block->table()->type()] = new_block; if (tables_blocks == block) tables_blocks = new_block; Query_cache_block_table *nlist_root = new_block->table(0); nlist_root->n = 0; Loading Loading @@ -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; uint db_length; DBUG_ENTER("Query_cache::filename_2_table_key"); /* Safety if filename didn't have a directory name */ Loading @@ -2785,10 +2806,10 @@ uint Query_cache::filename_2_table_key (char *key, const char *path) filename= tablename + dirname_length(tablename + 2) + 2; /* Find start of databasename */ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ; db_length= (filename - dbname) - 1; DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename)); *db_length= (filename - dbname) - 1; 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); } Loading Loading @@ -2975,22 +2996,18 @@ void Query_cache::tables_dump() DBUG_PRINT("qcache", ("--------------------")); DBUG_PRINT("qcache", ("TABLES")); 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)); if (tables_blocks[i] != 0) { Query_cache_block *table_block = tables_blocks[i]; Query_cache_block *table_block = tables_blocks; do { Query_cache_table *table = table_block->table(); DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table())); table_block = table_block->next; } while ( table_block != tables_blocks[i]); } while ( table_block != tables_blocks); } else DBUG_PRINT("qcache", ("no tables in list")); } DBUG_PRINT("qcache", ("--------------------")); } Loading Loading @@ -3082,7 +3099,7 @@ my_bool Query_cache::check_integrity(bool not_locked) break; } case Query_cache_block::TABLE: if (in_list(tables_blocks[block->table()->type()], block, "tables")) if (in_list(tables_blocks, block, "tables")) result = 1; if (in_table_list(block->table(0), block->table(0), "table list root")) result = 1; Loading Loading @@ -3197,9 +3214,7 @@ my_bool Query_cache::check_integrity(bool not_locked) } DBUG_PRINT("qcache", ("check tables ...")); for (i=0 ; (int) i < (int) Query_cache_table::TYPES_NUMBER; i++) { if ((block = tables_blocks[i])) if ((block = tables_blocks)) { do { Loading @@ -3217,8 +3232,7 @@ my_bool Query_cache::check_integrity(bool not_locked) if (in_blocks(block)) result = 1; block=block->next; } while (block != tables_blocks[i]); } } while (block != tables_blocks); } DBUG_PRINT("qcache", ("check free blocks")); Loading Loading
Docs/manual.texi +2 −3 Original line number Diff line number Diff line Loading @@ -36304,9 +36304,8 @@ If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE}, then all cached queries that used this table (possibly through a @code{MRG_MyISAM} table!) become invalid and are removed from the cache. Currently all @code{InnoDB} tables are invalidated on @code{COMMIT}, in the future this will be changed so only tables changed in the transaction cause the corresponding cache entries to be invalidated. Changed transactional @code{InnoDB} tables will be invalidated on @code{COMMIT}. A query cannot be cached if it contains one of the functions: @multitable @columnfractions .25 .25 .25 .25
mysql-test/r/innodb_cache.result +86 −1 Original line number Diff line number Diff line drop table if exists t1; drop table if exists t1, t2, t3; flush status; set autocommit=0; create table t1 (a int not null) type=innodb; insert into t1 values (1),(2),(3); Loading @@ -13,3 +14,87 @@ Qcache_queries_in_cache 0 drop table t1; commit; 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
mysql-test/t/innodb_cache.test +36 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,8 @@ # # Without auto_commit. # drop table if exists t1; drop table if exists t1, t2, t3; flush status; set autocommit=0; create table t1 (a int not null) type=innodb; insert into t1 values (1),(2),(3); Loading @@ -12,3 +13,37 @@ show status like "Qcache_queries_in_cache"; drop table t1; commit; 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
sql/handler.cc +8 −5 Original line number Diff line number Diff line Loading @@ -272,6 +272,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) if (opt_using_transactions) { bool operation_done= 0; bool transaction_commited= 0; /* Update the binary log if we have cached some queries */ if (trans == &thd->transaction.all && mysql_bin_log.is_open() && my_b_tell(&thd->transaction.trans_log)) Loading @@ -289,6 +290,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) my_error(ER_ERROR_DURING_COMMIT, MYF(0), error); error=1; } else transaction_commited= 1; trans->bdb_tid=0; } #endif Loading @@ -302,12 +305,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) } trans->innodb_active_trans=0; if (trans == &thd->transaction.all) { query_cache.invalidate(Query_cache_table::INNODB); operation_done=1; } operation_done= transaction_commited= 1; } #endif if (transaction_commited) query_cache.invalidate(thd->transaction.changed_tables); 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!"); thd->tx_isolation=thd->session_tx_isolation; Loading
sql/sql_cache.cc +94 −80 Original line number Diff line number Diff line Loading @@ -271,8 +271,6 @@ If join_results allocated new block(s) then we need call pack_cache again. 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) - Optimize cache resizing - if new_size < old_size then pack & shrink Loading @@ -280,8 +278,6 @@ TODO list: - Move MRG_MYISAM table type processing to handlers, something like: tables_used->table->file->register_used_filenames(callback, 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" Loading Loading @@ -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 */ 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)"); if (query_cache_size > 0) Loading @@ -1039,54 +1036,76 @@ void Query_cache::invalidate(TABLE_LIST *tables_used) if (query_cache_size > 0) { DUMP(this); using_transactions = using_transactions && (thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN)); 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); } } STRUCT_UNLOCK(&structure_guard_mutex); } DBUG_VOID_RETURN; } /* Remove all cached queries that uses the given table */ void Query_cache::invalidate(TABLE *table) void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) { DBUG_ENTER("Query_cache::invalidate (table)"); if (query_cache_size > 0) 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) 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); } 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) { 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]); 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); } STRUCT_UNLOCK(&structure_guard_mutex); } DBUG_VOID_RETURN; } /* Remove all cached queries that uses the given database */ Loading @@ -1100,12 +1119,9 @@ void Query_cache::invalidate(char *db) if (query_cache_size > 0) { DUMP(this); for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++) { /* invalidate_table reduce list while only root of list remain */ while (tables_blocks[i] !=0 ) invalidate_table(tables_blocks[i]); } while (tables_blocks !=0 ) invalidate_table(tables_blocks); } STRUCT_UNLOCK(&structure_guard_mutex); } Loading @@ -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 */ 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); if (query_cache_size > 0) // Safety if cache removed { Loading Loading @@ -1800,11 +1817,15 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) } 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; if ((table_block = ((Query_cache_block*) hash_search(&tables, (byte*) table->table_cache_key, table->key_length)))) hash_search(&tables, key, key_length)))) invalidate_table(table_block); } Loading Loading @@ -1842,8 +1863,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, block_table->n=n; if (!insert_table(tables_used->table->key_length, tables_used->table->table_cache_key, block_table, Query_cache_table::type_convertion(tables_used->table-> db_type))) tables_used->db_length)) break; if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) Loading @@ -1855,10 +1875,12 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, table++) { 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; if (!insert_table(key_length, key, block_table, Query_cache_table::type_convertion(DB_TYPE_MYISAM))) db_length)) goto err; } } Loading @@ -1885,7 +1907,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, my_bool Query_cache::insert_table(uint key_len, char *key, Query_cache_block_table *node, Query_cache_table::query_cache_table_type type) uint32 db_length) { DBUG_ENTER("Query_cache::insert_table"); DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d", Loading @@ -1909,9 +1931,8 @@ Query_cache::insert_table(uint key_len, char *key, DBUG_RETURN(0); } Query_cache_table *header = table_block->table(); header->type(type); double_linked_list_simple_include(table_block, &tables_blocks[type]); &tables_blocks); Query_cache_block_table *list_root = table_block->table(0); list_root->n = 0; list_root->next = list_root->prev = list_root; Loading @@ -1923,7 +1944,7 @@ Query_cache::insert_table(uint key_len, char *key, DBUG_RETURN(0); } 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); Loading @@ -1947,7 +1968,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node) // list is empty (neighbor is root of list) Query_cache_block *table_block = neighbour->block(); double_linked_list_exclude(table_block, &tables_blocks[table_block->table()->type()]); &tables_blocks); hash_delete(&tables,(byte *) table_block); free_memory_block(table_block); } Loading Loading @@ -2513,8 +2534,8 @@ my_bool Query_cache::move_by_type(byte **border, new_block->n_tables=1; memmove((char*) new_block->data(), data, len-new_block->headers_len()); relink(block, new_block, next, prev, pnext, pprev); if (tables_blocks[new_block->table()->type()] == block) tables_blocks[new_block->table()->type()] = new_block; if (tables_blocks == block) tables_blocks = new_block; Query_cache_block_table *nlist_root = new_block->table(0); nlist_root->n = 0; Loading Loading @@ -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; uint db_length; DBUG_ENTER("Query_cache::filename_2_table_key"); /* Safety if filename didn't have a directory name */ Loading @@ -2785,10 +2806,10 @@ uint Query_cache::filename_2_table_key (char *key, const char *path) filename= tablename + dirname_length(tablename + 2) + 2; /* Find start of databasename */ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ; db_length= (filename - dbname) - 1; DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename)); *db_length= (filename - dbname) - 1; 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); } Loading Loading @@ -2975,22 +2996,18 @@ void Query_cache::tables_dump() DBUG_PRINT("qcache", ("--------------------")); DBUG_PRINT("qcache", ("TABLES")); 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)); if (tables_blocks[i] != 0) { Query_cache_block *table_block = tables_blocks[i]; Query_cache_block *table_block = tables_blocks; do { Query_cache_table *table = table_block->table(); DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table())); table_block = table_block->next; } while ( table_block != tables_blocks[i]); } while ( table_block != tables_blocks); } else DBUG_PRINT("qcache", ("no tables in list")); } DBUG_PRINT("qcache", ("--------------------")); } Loading Loading @@ -3082,7 +3099,7 @@ my_bool Query_cache::check_integrity(bool not_locked) break; } case Query_cache_block::TABLE: if (in_list(tables_blocks[block->table()->type()], block, "tables")) if (in_list(tables_blocks, block, "tables")) result = 1; if (in_table_list(block->table(0), block->table(0), "table list root")) result = 1; Loading Loading @@ -3197,9 +3214,7 @@ my_bool Query_cache::check_integrity(bool not_locked) } DBUG_PRINT("qcache", ("check tables ...")); for (i=0 ; (int) i < (int) Query_cache_table::TYPES_NUMBER; i++) { if ((block = tables_blocks[i])) if ((block = tables_blocks)) { do { Loading @@ -3217,8 +3232,7 @@ my_bool Query_cache::check_integrity(bool not_locked) if (in_blocks(block)) result = 1; block=block->next; } while (block != tables_blocks[i]); } } while (block != tables_blocks); } DBUG_PRINT("qcache", ("check free blocks")); Loading