Commit ff51b7d8 authored by Mikael Ronstrom's avatar Mikael Ronstrom

Patch to fix bug#38551

parent 9daa56fd
...@@ -3448,6 +3448,19 @@ You should consider changing lower_case_table_names to 1 or 2", ...@@ -3448,6 +3448,19 @@ You should consider changing lower_case_table_names to 1 or 2",
files_charset_info : files_charset_info :
&my_charset_bin); &my_charset_bin);
/*
If we explicitly turn off query cache from the command line query cache will
be disabled for the reminder of the server life time. This is because we
want to avoid locking the QC specific mutex if query cache isn't going to
be used.
*/
if (global_system_variables.query_cache_type == 0)
{
have_query_cache= SHOW_OPTION_NO;
query_cache.disable_query_cache();
}
return 0; return 0;
} }
...@@ -6672,12 +6685,10 @@ The minimum value for this variable is 4096.", ...@@ -6672,12 +6685,10 @@ The minimum value for this variable is 4096.",
(uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit,
0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE, 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE,
0, ULONG_MAX, 0, 1, 0}, 0, ULONG_MAX, 0, 1, 0},
#endif /*HAVE_QUERY_CACHE*/
{"query_cache_size", OPT_QUERY_CACHE_SIZE, {"query_cache_size", OPT_QUERY_CACHE_SIZE,
"The memory allocated to store results from old queries.", "The memory allocated to store results from old queries.",
(uchar**) &query_cache_size, (uchar**) &query_cache_size, 0, GET_ULONG, (uchar**) &query_cache_size, (uchar**) &query_cache_size, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0}, REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0},
#ifdef HAVE_QUERY_CACHE
{"query_cache_type", OPT_QUERY_CACHE_TYPE, {"query_cache_type", OPT_QUERY_CACHE_TYPE,
"0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.", "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.",
(uchar**) &global_system_variables.query_cache_type, (uchar**) &global_system_variables.query_cache_type,
......
...@@ -670,7 +670,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) ...@@ -670,7 +670,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
DBUG_ENTER("query_cache_insert"); DBUG_ENTER("query_cache_insert");
/* See the comment on double-check locking usage above. */ /* See the comment on double-check locking usage above. */
if (net->query_cache_query == 0) if (query_cache.is_disabled() || net->query_cache_query == 0)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
DBUG_EXECUTE_IF("wait_in_query_cache_insert", DBUG_EXECUTE_IF("wait_in_query_cache_insert",
...@@ -778,7 +778,7 @@ void query_cache_end_of_result(THD *thd) ...@@ -778,7 +778,7 @@ void query_cache_end_of_result(THD *thd)
DBUG_ENTER("query_cache_end_of_result"); DBUG_ENTER("query_cache_end_of_result");
/* See the comment on double-check locking usage above. */ /* See the comment on double-check locking usage above. */
if (thd->net.query_cache_query == 0) if (query_cache.is_disabled() || thd->net.query_cache_query == 0)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
if (thd->killed) if (thd->killed)
...@@ -891,7 +891,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg, ...@@ -891,7 +891,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg,
min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)), min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)), def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)), def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
initialized(0) initialized(0),m_query_cache_is_disabled(FALSE)
{ {
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) + ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
ALIGN_SIZE(sizeof(Query_cache_block_table)) + ALIGN_SIZE(sizeof(Query_cache_block_table)) +
...@@ -978,7 +978,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) ...@@ -978,7 +978,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
See also a note on double-check locking usage above. See also a note on double-check locking usage above.
*/ */
if (thd->locked_tables || query_cache_size == 0) if (m_query_cache_is_disabled || thd->locked_tables || query_cache_size == 0)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
uint8 tables_type= 0; uint8 tables_type= 0;
...@@ -1161,14 +1161,18 @@ end: ...@@ -1161,14 +1161,18 @@ end:
Check if the query is in the cache. If it was cached, send it Check if the query is in the cache. If it was cached, send it
to the user. to the user.
RESULTS @param thd Pointer to the thread handler
1 Query was not cached. @param sql A pointer to the sql statement *
0 The query was cached and user was sent the result. @param query_length Length of the statement in characters
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
NOTE @return status code
This method requires that sql points to allocated memory of size: @retval 1 Query was not cached.
@retval 0 The query was cached and user was sent the result.
@retval -1 The query was cached but we didn't have rights to use it.
In case of -1, no error is sent to the client.
*) The buffer must be allocated memory of size:
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
*/ */
...@@ -1183,6 +1187,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1183,6 +1187,9 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Query_cache_query_flags flags; Query_cache_query_flags flags;
DBUG_ENTER("Query_cache::send_result_to_client"); DBUG_ENTER("Query_cache::send_result_to_client");
if (m_query_cache_is_disabled)
DBUG_RETURN(0);
/* /*
Testing 'query_cache_size' without a lock here is safe: the thing Testing 'query_cache_size' without a lock here is safe: the thing
we may loose is that the query won't be served from cache, but we we may loose is that the query won't be served from cache, but we
...@@ -2530,7 +2537,17 @@ void Query_cache::invalidate_table(THD *thd, TABLE *table) ...@@ -2530,7 +2537,17 @@ void Query_cache::invalidate_table(THD *thd, TABLE *table)
void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length) void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
{ {
bool interrupt; bool interrupt;
if (m_query_cache_is_disabled)
return;
STRUCT_LOCK(&structure_guard_mutex); STRUCT_LOCK(&structure_guard_mutex);
if (query_cache_size == 0)
{
STRUCT_UNLOCK(&structure_guard_mutex);
return;
}
wait_while_table_flush_is_in_progress(&interrupt); wait_while_table_flush_is_in_progress(&interrupt);
if (interrupt) if (interrupt)
{ {
......
...@@ -279,6 +279,8 @@ private: ...@@ -279,6 +279,8 @@ private:
Cache_status m_cache_status; Cache_status m_cache_status;
bool m_query_cache_is_disabled;
void free_query_internal(Query_cache_block *point); void free_query_internal(Query_cache_block *point);
void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length); void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length);
...@@ -437,6 +439,14 @@ protected: ...@@ -437,6 +439,14 @@ protected:
/* register query in cache */ /* register query in cache */
void store_query(THD *thd, TABLE_LIST *used_tables); void store_query(THD *thd, TABLE_LIST *used_tables);
/**
At startup the user has an option to disable the query cache
to avoid locking the structure_guard_mutex.
This option is enabled by explicitly setting query_cache_type=OFF
in the command line.
*/
void disable_query_cache(void) { m_query_cache_is_disabled= TRUE; }
/* /*
Check if the query is in the cache and if this is true send the Check if the query is in the cache and if this is true send the
data to client. data to client.
...@@ -469,6 +479,8 @@ protected: ...@@ -469,6 +479,8 @@ protected:
friend void query_cache_end_of_result(THD *thd); friend void query_cache_end_of_result(THD *thd);
friend void query_cache_abort(NET *net); friend void query_cache_abort(NET *net);
bool is_disabled(void) { return m_query_cache_is_disabled; }
bool is_flushing(void) bool is_flushing(void)
{ {
return (m_cache_status != Query_cache::NO_FLUSH_IN_PROGRESS); return (m_cache_status != Query_cache::NO_FLUSH_IN_PROGRESS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment