diff options
author | unknown <gshchepa/uchum@gleb.loc> | 2007-08-22 18:15:54 +0500 |
---|---|---|
committer | unknown <gshchepa/uchum@gleb.loc> | 2007-08-22 18:15:54 +0500 |
commit | 891b1659fcd0d0a65b2a6d8ccd40e9225b76bb88 (patch) | |
tree | 822d9e3b8b29ae32c681ec759d0d437912cdcc9e /sql/sql_cache.cc | |
parent | 92abaeee0c05ba5e1b074a4aff308789d4ecee12 (diff) | |
download | mariadb-git-891b1659fcd0d0a65b2a6d8ccd40e9225b76bb88.tar.gz |
Fixed bug #30201.
Killing a SELECT query with KILL QUERY or KILL CONNECTION
causes a server crash if the query cache is enabled.
Normal evaluation of a query may be interrupted by the
KILL QUERY/CONNECTION statement, in this case the mysql_execute_command
function returns TRUE, and the thd->killed flag has true value.
In this case the result of the query may
be cached incompletely (omitting call to query_cache_insert inside
the net_real_write function), and next call to query_cache_end_of_result
may lead to server crash.
Thus, the query_cache_end_of_result function has been modified to abort
query cache in the case of killed thread.
sql/sql_cache.cc:
Fixed bug #30201.
The query_cache_end_of_result function has been modified to abort query
cache in the case of query execution failure. Also this function has been
modified to remove incomplete query block.
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r-- | sql/sql_cache.cc | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 33d658ce6a1..0d8ef568550 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -710,6 +710,12 @@ void query_cache_end_of_result(THD *thd) if (thd->net.query_cache_query == 0) DBUG_VOID_RETURN; + if (thd->killed) + { + query_cache_abort(&thd->net); + DBUG_VOID_RETURN; + } + #ifdef EMBEDDED_LIBRARY query_cache_insert(&thd->net, (char*)thd, emb_count_querycache_size(thd)); @@ -727,27 +733,30 @@ void query_cache_end_of_result(THD *thd) DUMP(&query_cache); BLOCK_LOCK_WR(query_block); Query_cache_query *header= query_block->query(); - Query_cache_block *last_result_block= header->result()->prev; - ulong allign_size= ALIGN_SIZE(last_result_block->used); - ulong len= max(query_cache.min_allocation_unit, allign_size); - if (last_result_block->length >= query_cache.min_allocation_unit + len) - query_cache.split_block(last_result_block,len); + Query_cache_block *last_result_block; + ulong allign_size; + ulong len; -#ifndef DBUG_OFF if (header->result() == 0) { - DBUG_PRINT("error", ("end of data whith no result. query '%s'", - header->query())); - query_cache.wreck(__LINE__, ""); - + DBUG_PRINT("error", ("End of data with no result blocks; " + "Query '%s' removed from cache.", header->query())); /* - We do not need call of BLOCK_UNLOCK_WR(query_block); here because - query_cache.wreck() switched query cache off but left content - untouched for investigation (it is debugging method). + Extra safety: empty result should not happen in the normal call + to this function. In the release version that query should be ignored + and removed from QC. */ + DBUG_ASSERT(0); + query_cache.free_query(query_block); goto end; } -#endif + + last_result_block= header->result()->prev; + allign_size= ALIGN_SIZE(last_result_block->used); + len= max(query_cache.min_allocation_unit, allign_size); + if (last_result_block->length >= query_cache.min_allocation_unit + len) + query_cache.split_block(last_result_block,len); + header->found_rows(current_thd->limit_found_rows); header->result()->type= Query_cache_block::RESULT; header->writer(0); |