diff options
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r-- | sql/sql_cache.cc | 428 |
1 files changed, 305 insertions, 123 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index fc03e03dee7..f8f7bde3a62 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -278,7 +278,6 @@ TODO list: - Move MRG_MYISAM table type processing to handlers, something like: tables_used->table->file->register_used_filenames(callback, first_argument); - - Make derived tables cachable. - QC improvement suggested by Monty: - Add a counter in open_table() for how many MERGE (ISAM or MyISAM) tables are cached in the table cache. @@ -311,7 +310,7 @@ TODO list: #include "emb_qcache.h" #endif -#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF) +#if !defined(EXTRA_DBUG) && !defined(DBUG_OFF) #define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \ pthread_mutex_lock(M);} #define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\ @@ -615,6 +614,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) DBUG_VOID_RETURN; } header->result(result); + header->last_pkt_nr= net->pkt_nr; BLOCK_UNLOCK_WR(query_block); } else @@ -796,10 +796,12 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) Query_cache_query_flags flags; // fill all gaps between fields with 0 to get repeatable key bzero(&flags, QUERY_CACHE_FLAGS_SIZE); - flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ? - 1 : 0); - flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ? - 1 : 0); + flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG); + flags.client_protocol_41= test(thd->client_capabilities & + CLIENT_PROTOCOL_41); + flags.more_results_exists= test(thd->server_status & + SERVER_MORE_RESULTS_EXISTS); + flags.pkt_nr= net->pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; flags.character_set_results_num= @@ -812,8 +814,28 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) flags.time_zone= thd->variables.time_zone; flags.sql_mode= thd->variables.sql_mode; flags.max_sort_length= thd->variables.max_sort_length; + flags.lc_time_names= thd->variables.lc_time_names; flags.group_concat_max_len= thd->variables.group_concat_max_len; - flags.lc_time_names= thd->variables.lc_time_names; + DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ +CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ +sql mode: 0x%lx, sort len: %lu, conncat len: %lu", + (int)flags.client_long_flag, + (int)flags.client_protocol_41, + (int)flags.more_results_exists, + flags.pkt_nr, + flags.character_set_client_num, + flags.character_set_results_num, + flags.collation_connection_num, + flags.limit, + (ulong)flags.time_zone, + flags.sql_mode, + flags.max_sort_length, + flags.group_concat_max_len)); + /* + Make InnoDB to release the adaptive hash index latch before + acquiring the query cache mutex. + */ + ha_release_temporary_latches(thd); STRUCT_LOCK(&structure_guard_mutex); if (query_cache_size == 0) @@ -931,17 +953,21 @@ end: 0 The query was cached and user was sent the result. -1 The query was cached but we didn't have rights to use it. No error is sent to the client yet. + + NOTE + This method requires that sql points to allocated memory of size: + tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; */ int Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) { + ulonglong engine_data; Query_cache_query *query; Query_cache_block *first_result_block, *result_block; Query_cache_block_table *block_table, *block_table_end; ulong tot_length; Query_cache_query_flags flags; - bool check_tables; DBUG_ENTER("Query_cache::send_result_to_client"); if (query_cache_size == 0 || thd->locked_tables || @@ -969,10 +995,15 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) /* Test if the query is a SELECT (pre-space is removed in dispatch_command) + + First '/' looks like comment before command it is not + frequently appeared in real lihe, consequently we can + check all such queries, too. */ - if (my_toupper(system_charset_info, sql[i]) != 'S' || - my_toupper(system_charset_info, sql[i + 1]) != 'E' || - my_toupper(system_charset_info, sql[i + 2]) != 'L') + if ((my_toupper(system_charset_info, sql[i]) != 'S' || + my_toupper(system_charset_info, sql[i + 1]) != 'E' || + my_toupper(system_charset_info, sql[i + 2]) != 'L') && + sql[i] != '/') { DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); goto err; @@ -1001,10 +1032,12 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) // fill all gaps between fields with 0 to get repeatable key bzero(&flags, QUERY_CACHE_FLAGS_SIZE); - flags.client_long_flag= (thd->client_capabilities & CLIENT_LONG_FLAG ? - 1 : 0); - flags.client_protocol_41= (thd->client_capabilities & CLIENT_PROTOCOL_41 ? - 1 : 0); + flags.client_long_flag= test(thd->client_capabilities & CLIENT_LONG_FLAG); + flags.client_protocol_41= test(thd->client_capabilities & + CLIENT_PROTOCOL_41); + flags.more_results_exists= test(thd->server_status & + SERVER_MORE_RESULTS_EXISTS); + flags.pkt_nr= thd->net.pkt_nr; flags.character_set_client_num= thd->variables.character_set_client->number; flags.character_set_results_num= (thd->variables.character_set_results ? @@ -1016,7 +1049,22 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) flags.sql_mode= thd->variables.sql_mode; flags.max_sort_length= thd->variables.max_sort_length; flags.group_concat_max_len= thd->variables.group_concat_max_len; - flags.lc_time_names= thd->variables.lc_time_names; + flags.lc_time_names= thd->variables.lc_time_names; + DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \ +CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \ +sql mode: 0x%lx, sort len: %lu, conncat len: %lu", + (int)flags.client_long_flag, + (int)flags.client_protocol_41, + (int)flags.more_results_exists, + flags.pkt_nr, + flags.character_set_client_num, + flags.character_set_results_num, + flags.collation_connection_num, + flags.limit, + (ulong)flags.time_zone, + flags.sql_mode, + flags.max_sort_length, + flags.group_concat_max_len)); memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)), &flags, QUERY_CACHE_FLAGS_SIZE); query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql, @@ -1055,7 +1103,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) goto err_unlock; } - check_tables= query->tables_type() & HA_CACHE_TBL_ASKTRANSACT; // Check access; block_table= query_block->table(0); block_table_end= block_table+query_block->n_tables; @@ -1063,7 +1110,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) { TABLE_LIST table_list; TABLE *tmptable; - Query_cache_table *table = block_table->parent; /* @@ -1074,8 +1120,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) */ for (tmptable= thd->temporary_tables; tmptable ; tmptable= tmptable->next) { - if (tmptable->key_length - TMP_TABLE_KEY_EXTRA == table->key_length() && - !memcmp(tmptable->table_cache_key, table->data(), + if (tmptable->s->key_length - TMP_TABLE_KEY_EXTRA == + table->key_length() && + !memcmp(tmptable->s->table_cache_key, table->data(), table->key_length())) { DBUG_PRINT("qcache", @@ -1095,7 +1142,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) bzero((char*) &table_list,sizeof(table_list)); table_list.db = table->db(); - table_list.alias= table_list.real_name= table->table(); + table_list.alias= table_list.table_name= table->table(); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_table_access(thd,SELECT_ACL,&table_list,1)) { @@ -1116,19 +1163,30 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) goto err_unlock; // Parse query } #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/ - if (check_tables && !ha_caching_allowed(thd, table->db(), - table->key_length(), - table->type())) + engine_data= table->engine_data(); + if (table->callback() && + !(*table->callback())(thd, table->db(), + table->key_length(), + &engine_data)) { DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s", table_list.db, table_list.alias)); BLOCK_UNLOCK_RD(query_block); - thd->lex->safe_to_cache_query= 0; // Don't try to cache this + if (engine_data != table->engine_data()) + { + DBUG_PRINT("qcache", + ("Handler require invalidation queries of %s.%s %lld-%lld", + table_list.db, table_list.alias, + engine_data, table->engine_data())); + invalidate_table((byte *) table->db(), table->key_length()); + } + else + thd->lex->safe_to_cache_query= 0; // Don't try to cache this goto err_unlock; // Parse query } else - DBUG_PRINT("qcache", ("handler allow caching (%d) %s,%s", - check_tables, table_list.db, table_list.alias)); + DBUG_PRINT("qcache", ("handler allow caching %s,%s", + table_list.db, table_list.alias)); } move_to_query_list_end(query_block); hits++; @@ -1152,6 +1210,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ALIGN_SIZE(sizeof(Query_cache_result)))) break; // Client aborted result_block = result_block->next; + thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated } while (result_block != first_result_block); #else { @@ -1162,6 +1221,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) #endif /*!EMBEDDED_LIBRARY*/ thd->limit_found_rows = query->found_rows(); + thd->status_var.last_query_cost= 0.0; BLOCK_UNLOCK_RD(query_block); DBUG_RETURN(1); // Result sent to client @@ -1190,7 +1250,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, using_transactions = using_transactions && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); - for (; tables_used; tables_used=tables_used->next) + for (; tables_used; tables_used= tables_used->next_local) { DBUG_ASSERT(!using_transactions || tables_used->table!=0); if (tables_used->derived) @@ -1222,7 +1282,7 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) if (query_cache_size > 0) { DUMP(this); - for (; tables_used; tables_used=tables_used->next) + for (; tables_used; tables_used= tables_used->next) { invalidate_table((byte*) tables_used->key, tables_used->key_length); DBUG_PRINT("qcache", (" db %s, table %s", tables_used->key, @@ -1255,9 +1315,10 @@ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used) if (query_cache_size > 0) { DUMP(this); - for (; tables_used; tables_used= tables_used->next) + for (; tables_used; tables_used= tables_used->next_local) { - if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE)) + if (tables_used->lock_type & (TL_WRITE_LOW_PRIORITY | TL_WRITE) && + tables_used->table) invalidate_table(tables_used->table); } } @@ -2057,7 +2118,7 @@ my_bool Query_cache::allocate_data_chain(Query_cache_block **result_block, */ data_len= len - new_block->length; prev_block= new_block; - } while(1); + } while (1); DBUG_RETURN(TRUE); } @@ -2080,7 +2141,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) uint key_length; Query_cache_block *table_block; key_length=(uint) (strmov(strmov(key,table_list->db)+1, - table_list->real_name) -key)+ 1; + table_list->table_name) -key)+ 1; // We don't store temporary tables => no key_length+=4 ... if ((table_block = (Query_cache_block*) @@ -2091,7 +2152,7 @@ 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); + invalidate_table((byte*) table->s->table_cache_key, table->s->key_length); } void Query_cache::invalidate_table(byte * key, uint32 key_length) @@ -2113,6 +2174,107 @@ void Query_cache::invalidate_table(Query_cache_block *table_block) } } + +/* + Register given table list begining with given position in tables table of + block + + SYNOPSIS + Query_cache::register_tables_from_list + tables_used given table list + counter number current position in table of tables of block + block_table pointer to current position in tables table of block + + RETURN + 0 error + number of next position of table entry in table of tables of block +*/ + +TABLE_COUNTER_TYPE +Query_cache::register_tables_from_list(TABLE_LIST *tables_used, + TABLE_COUNTER_TYPE counter, + Query_cache_block_table *block_table) +{ + TABLE_COUNTER_TYPE n; + DBUG_ENTER("Query_cache::register_tables_from_list"); + for (n= counter; + tables_used; + tables_used= tables_used->next_global, n++, block_table++) + { + if (tables_used->derived && !tables_used->view) + { + DBUG_PRINT("qcache", ("derived table skipped")); + n--; + block_table--; + continue; + } + block_table->n= n; + if (tables_used->view) + { + char key[MAX_DBKEY_LENGTH]; + uint key_length; + DBUG_PRINT("qcache", ("view %s, db %s", + tables_used->view_name.str, + tables_used->view_db.str)); + key_length= (uint) (strmov(strmov(key, tables_used->view_db.str) + 1, + tables_used->view_name.str) - key) + 1; + /* + There are not callback function for for VIEWs + */ + if (!insert_table(key_length, key, block_table, + tables_used->view_db.length + 1, + HA_CACHE_TBL_NONTRANSACT, 0, 0)) + DBUG_RETURN(0); + /* + We do not need to register view tables here because they are already + present in the global list. + */ + } + else + { + DBUG_PRINT("qcache", + ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx", + tables_used->table->s->table_name, + tables_used->table->s->table_cache_key, + (ulong) tables_used->table, + tables_used->table->s->key_length, + (ulong) tables_used->table->s->table_cache_key)); + if (!insert_table(tables_used->table->s->key_length, + tables_used->table->s->table_cache_key, block_table, + tables_used->db_length, + tables_used->table->file->table_cache_type(), + tables_used->callback_func, + tables_used->engine_data)) + DBUG_RETURN(0); + + if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM) + { + ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file; + MYRG_INFO *file = handler->myrg_info(); + for (MYRG_TABLE *table = file->open_tables; + table != file->end_table ; + table++) + { + char key[MAX_DBKEY_LENGTH]; + uint32 db_length; + uint key_length= filename_2_table_key(key, table->table->filename, + &db_length); + (++block_table)->n= ++n; + /* + There are not callback function for for MyISAM, and engine data + */ + if (!insert_table(key_length, key, block_table, + db_length, + tables_used->table->file->table_cache_type(), + 0, 0)) + DBUG_RETURN(0); + } + } + } + } + DBUG_RETURN(n - counter); +} + /* Store all used tables @@ -2134,51 +2296,9 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, Query_cache_block_table *block_table = block->table(0); - for (n=0; tables_used; tables_used=tables_used->next, n++, block_table++) - { - if (tables_used->derived) - { - DBUG_PRINT("qcache", ("derived table skipped")); - n--; - block_table--; - continue; - } - DBUG_PRINT("qcache", - ("table %s, db %s, openinfo at 0x%lx, keylen %u, key at 0x%lx", - tables_used->real_name, tables_used->db, - (ulong) tables_used->table, - tables_used->table->key_length, - (ulong) tables_used->table->table_cache_key)); - block_table->n=n; - if (!insert_table(tables_used->table->key_length, - tables_used->table->table_cache_key, block_table, - tables_used->db_length, - tables_used->table->file->table_cache_type())) - break; - - if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) - { - ha_myisammrg *handler = (ha_myisammrg *) tables_used->table->file; - MYRG_INFO *file = handler->myrg_info(); - for (MYRG_TABLE *table = file->open_tables; - table != file->end_table ; - table++) - { - char key[MAX_DBKEY_LENGTH]; - uint32 db_length; - uint key_length= filename_2_table_key(key, table->table->filename, - &db_length); - (++block_table)->n= ++n; - if (!insert_table(key_length, key, block_table, - db_length, - tables_used->table->file->table_cache_type())) - goto err; - } - } - } + n= register_tables_from_list(tables_used, 0, block_table); -err: - if (tables_used) + if (n) { DBUG_PRINT("qcache", ("failed at table %d", (int) n)); /* Unlink the tables we allocated above */ @@ -2187,7 +2307,7 @@ err: tmp++) unlink_table(tmp); } - return (tables_used == 0); + return (n); } /* @@ -2198,7 +2318,9 @@ err: my_bool Query_cache::insert_table(uint key_len, char *key, Query_cache_block_table *node, - uint32 db_length, uint8 cache_type) + uint32 db_length, uint8 cache_type, + qc_engine_callback callback, + ulonglong engine_data) { DBUG_ENTER("Query_cache::insert_table"); DBUG_PRINT("qcache", ("insert table node 0x%lx, len %d", @@ -2208,6 +2330,23 @@ Query_cache::insert_table(uint key_len, char *key, hash_search(&tables, (byte*) key, key_len)); + if (table_block && + table_block->table()->engine_data() != engine_data) + { + DBUG_PRINT("qcache", + ("Handler require invalidation queries of %s.%s %lld-%lld", + table_block->table()->db(), + table_block->table()->table(), + engine_data, + table_block->table()->engine_data())); + /* + as far as we delete all queries with this table, table block will be + deleted, too + */ + invalidate_table(table_block); + table_block= 0; + } + if (table_block == 0) { DBUG_PRINT("qcache", ("new table block from 0x%lx (%u)", @@ -2238,6 +2377,8 @@ Query_cache::insert_table(uint key_len, char *key, header->table(db + db_length + 1); header->key_length(key_len); header->type(cache_type); + header->callback(callback); + header->engine_data(engine_data); } Query_cache_block_table *list_root = table_block->table(0); @@ -2676,6 +2817,77 @@ void Query_cache::double_linked_list_join(Query_cache_block *head_tail, *****************************************************************************/ /* + Collect information about table types, check that tables are cachable and + count them + + SYNOPSIS + process_and_count_tables() + tables_used table list for processing + tables_type pointer to variable for table types collection + + RETURN + 0 error + >0 number of tables +*/ + +static TABLE_COUNTER_TYPE process_and_count_tables(TABLE_LIST *tables_used, + uint8 *tables_type) +{ + DBUG_ENTER("process_and_count_tables"); + TABLE_COUNTER_TYPE table_count = 0; + for (; tables_used; tables_used= tables_used->next_global) + { + table_count++; + if (tables_used->view) + { + DBUG_PRINT("qcache", ("view %s, db %s", + tables_used->view_name.str, + tables_used->view_db.str)); + *tables_type|= HA_CACHE_TBL_NONTRANSACT; + } + else + { + DBUG_PRINT("qcache", ("table %s, db %s, type %u", + tables_used->table->s->table_name, + tables_used->table->s->table_cache_key, + tables_used->table->s->db_type)); + if (tables_used->derived) + { + table_count--; + DBUG_PRINT("qcache", ("derived table skipped")); + continue; + } + *tables_type|= tables_used->table->file->table_cache_type(); + + /* + table_alias_charset used here because it depends of + lower_case_table_names variable + */ + if (tables_used->table->s->tmp_table != NO_TMP_TABLE || + (*tables_type & HA_CACHE_TBL_NOCACHE) || + (tables_used->db_length == 5 && + my_strnncoll(table_alias_charset, + (uchar*)tables_used->table->s->table_cache_key, 6, + (uchar*)"mysql",6) == 0)) + { + DBUG_PRINT("qcache", + ("select not cacheable: temporary, system or \ + other non-cacheable table(s)")); + DBUG_RETURN(0); + } + if (tables_used->table->s->db_type == DB_TYPE_MRG_MYISAM) + { + ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; + MYRG_INFO *file = handler->myrg_info(); + table_count+= (file->end_table - file->open_tables); + } + } + } + DBUG_RETURN(table_count); +} + + +/* If query is cacheable return number tables in query (query without tables are not cached) */ @@ -2686,7 +2898,7 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, TABLE_LIST *tables_used, uint8 *tables_type) { - TABLE_COUNTER_TYPE table_count = 0; + TABLE_COUNTER_TYPE table_count; DBUG_ENTER("Query_cache::is_cacheable"); if (lex->sql_command == SQLCOM_SELECT && @@ -2700,42 +2912,8 @@ TABLE_COUNTER_TYPE Query_cache::is_cacheable(THD *thd, uint32 query_len, lex->select_lex.options, (int) thd->variables.query_cache_type)); - for (; tables_used; tables_used= tables_used->next) - { - table_count++; - DBUG_PRINT("qcache", ("table %s, db %s, type %u", - tables_used->real_name, - tables_used->db, tables_used->table->db_type)); - *tables_type|= tables_used->table->file->table_cache_type(); - - /* - table_alias_charset used here because it depends of - lower_case_table_names variable - */ - if ((tables_used->table->tmp_table != NO_TMP_TABLE && - !tables_used->derived) || - (*tables_type & HA_CACHE_TBL_NOCACHE) || - (tables_used->db_length == 5 && - my_strnncoll(table_alias_charset, (uchar*)tables_used->db, 6, - (uchar*)"mysql",6) == 0)) - { - DBUG_PRINT("qcache", - ("select not cacheable: temporary, system or \ -other non-cacheable table(s)")); - DBUG_RETURN(0); - } - if (tables_used->derived) - { - table_count--; - DBUG_PRINT("qcache", ("derived table skipped")); - } - else if (tables_used->table->db_type == DB_TYPE_MRG_MYISAM) - { - ha_myisammrg *handler = (ha_myisammrg *)tables_used->table->file; - MYRG_INFO *file = handler->myrg_info(); - table_count+= (file->end_table - file->open_tables); - } - } + if (!(table_count= process_and_count_tables(tables_used, tables_type))) + DBUG_RETURN(0); if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && ((*tables_type)&HA_CACHE_TBL_TRANSACT)) @@ -2773,12 +2951,16 @@ my_bool Query_cache::ask_handler_allowance(THD *thd, { DBUG_ENTER("Query_cache::ask_handler_allowance"); - for (; tables_used; tables_used= tables_used->next) + for (; tables_used; tables_used= tables_used->next_global) { - TABLE *table= tables_used->table; - if (!ha_caching_allowed(thd, table->table_cache_key, - table->key_length, - table->file->table_cache_type())) + TABLE *table; + if (!(table= tables_used->table)) + continue; + handler *handler= table->file; + if (!handler->register_query_cache_table(thd, table->s->table_cache_key, + table->s->key_length, + &tables_used->callback_func, + &tables_used->engine_data)) { DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s", tables_used->db, tables_used->alias)); @@ -3236,7 +3418,7 @@ void Query_cache::wreck(uint line, const char *message) DBUG_PRINT("warning", ("%5d QUERY CACHE WRECK => DISABLED",line)); DBUG_PRINT("warning", ("==================================")); if (thd) - thd->killed = 1; + thd->killed= THD::KILL_CONNECTION; cache_dump(); /* check_integrity(0); */ /* Can't call it here because of locks */ bins_dump(); |