Skip to content

Commit 2d6a356

Browse files
author
Kristofer Pettersson
committed
Bug#38551 query cache can still consume [very little] cpu time even when it is off.
When the query cache is disabled, the server shouldn't attempt to take the query cache mutex. By using the command line option --query_cache_type=0, the user can disable (backport from mysql-pe)
1 parent 800ba38 commit 2d6a356

File tree

7 files changed

+124
-24
lines changed

7 files changed

+124
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--query_cache_type=0
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-- source include/have_query_cache.inc
2+
#
3+
# Bug#38551 query cache can still consume [very little] cpu time even when it is off.
4+
#
5+
SHOW GLOBAL VARIABLES LIKE 'query_cache_type';
6+
--error ER_QUERY_CACHE_DISABLED
7+
SET GLOBAL query_cache_type=ON;
8+
--error ER_QUERY_CACHE_DISABLED
9+
SET GLOBAL query_cache_type=DEMAND;
10+
--error ER_QUERY_CACHE_DISABLED
11+
SET GLOBAL query_cache_type=OFF;
12+
SET GLOBAL query_cache_size=1024*1024;
13+
SHOW GLOBAL VARIABLES LIKE 'query_cache_size';
14+
SET GLOBAL query_cache_size=0;
15+

sql/set_var.cc

+50-12
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,10 @@ static void fix_net_read_timeout(THD *thd, enum_var_type type);
125125
static void fix_net_write_timeout(THD *thd, enum_var_type type);
126126
static void fix_net_retry_count(THD *thd, enum_var_type type);
127127
static void fix_max_join_size(THD *thd, enum_var_type type);
128+
#ifdef HAVE_QUERY_CACHE
128129
static void fix_query_cache_size(THD *thd, enum_var_type type);
129130
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
131+
#endif
130132
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
131133
static void fix_max_binlog_size(THD *thd, enum_var_type type);
132134
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
@@ -493,9 +495,6 @@ static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
493495
&SV::div_precincrement);
494496
static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
495497
&rpl_recovery_rank);
496-
static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size",
497-
&query_cache_size,
498-
fix_query_cache_size);
499498

500499
static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size",
501500
&SV::range_alloc_block_size);
@@ -557,14 +556,20 @@ sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
557556
NULL);
558557

559558
#ifdef HAVE_QUERY_CACHE
559+
static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size",
560+
&query_cache_size,
561+
fix_query_cache_size);
560562
static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit",
561-
&query_cache.query_cache_limit);
562-
static sys_var_long_ptr sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
563-
&query_cache_min_res_unit,
564-
fix_query_cache_min_res_unit);
563+
&query_cache.query_cache_limit);
564+
static sys_var_long_ptr
565+
sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
566+
&query_cache_min_res_unit,
567+
fix_query_cache_min_res_unit);
568+
static int check_query_cache_type(THD *thd, set_var *var);
565569
static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type",
566570
&SV::query_cache_type,
567-
&query_cache_type_typelib);
571+
&query_cache_type_typelib, NULL,
572+
check_query_cache_type);
568573
static sys_var_thd_bool
569574
sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
570575
&SV::query_cache_wlock_invalidate);
@@ -1131,10 +1136,9 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)),
11311136
{}
11321137
#endif /* HAVE_REPLICATION */
11331138

1134-
1139+
#ifdef HAVE_QUERY_CACHE
11351140
static void fix_query_cache_size(THD *thd, enum_var_type type)
11361141
{
1137-
#ifdef HAVE_QUERY_CACHE
11381142
ulong new_cache_size= query_cache.resize(query_cache_size);
11391143

11401144
/*
@@ -1148,11 +1152,35 @@ static void fix_query_cache_size(THD *thd, enum_var_type type)
11481152
query_cache_size, new_cache_size);
11491153

11501154
query_cache_size= new_cache_size;
1151-
#endif
11521155
}
11531156

11541157

1155-
#ifdef HAVE_QUERY_CACHE
1158+
/**
1159+
Trigger before query_cache_type variable is updated.
1160+
@param thd Thread handler
1161+
@param var Pointer to the new variable status
1162+
1163+
@return Status code
1164+
@retval 1 Failure
1165+
@retval 0 Success
1166+
*/
1167+
1168+
static int check_query_cache_type(THD *thd, set_var *var)
1169+
{
1170+
/*
1171+
Don't allow changes of the query_cache_type if the query cache
1172+
is disabled.
1173+
*/
1174+
if (query_cache.is_disabled())
1175+
{
1176+
my_error(ER_QUERY_CACHE_DISABLED,MYF(0));
1177+
return 1;
1178+
}
1179+
1180+
return 0;
1181+
}
1182+
1183+
11561184
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
11571185
{
11581186
query_cache_min_res_unit=
@@ -3601,6 +3629,16 @@ bool not_all_support_one_shot(List<set_var_base> *var_list)
36013629
Functions to handle SET mysql_internal_variable=const_expr
36023630
*****************************************************************************/
36033631

3632+
/**
3633+
Verify that the supplied value is correct.
3634+
3635+
@param thd Thread handler
3636+
3637+
@return status code
3638+
@retval -1 Failure
3639+
@retval 0 Success
3640+
*/
3641+
36043642
int set_var::check(THD *thd)
36053643
{
36063644
if (var->is_readonly())

sql/set_var.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -543,10 +543,16 @@ class sys_var_thd_enum :public sys_var_thd
543543
{ chain_sys_var(chain); }
544544
bool check(THD *thd, set_var *var)
545545
{
546-
int ret= 0;
547-
if (check_func)
548-
ret= (*check_func)(thd, var);
549-
return ret ? ret : check_enum(thd, var, enum_names);
546+
/*
547+
check_enum fails if the character representation supplied was wrong
548+
or that the integer value was wrong or missing.
549+
*/
550+
if (check_enum(thd, var, enum_names))
551+
return TRUE;
552+
else if ((check_func && (*check_func)(thd, var)))
553+
return TRUE;
554+
else
555+
return FALSE;
550556
}
551557
bool update(THD *thd, set_var *var);
552558
void set_default(THD *thd, enum_var_type type);

sql/share/errmsg-utf8.txt

+3
Original file line numberDiff line numberDiff line change
@@ -6241,3 +6241,6 @@ ER_UNKNOWN_LOCALE
62416241
ER_SLAVE_IGNORE_SERVER_IDS
62426242
eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id"
62436243

6244+
ER_QUERY_CACHE_DISABLED
6245+
eng "Query cache is disabled; restart the server with query_cache_type=1 to enable it"
6246+

sql/sql_cache.cc

+40-8
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ The query cache interfaces with the rest of the server code through 7
286286
if (and only if) this query has a registered result set writer
287287
(thd->net.query_cache_query).
288288
4. Query_cache::invalidate
289+
Query_cache::invalidate_locked_for_write
289290
- Called from various places to invalidate query cache based on data-
290291
base, table and myisam file name. During an on going invalidation
291292
the query cache is temporarily disabled.
@@ -851,7 +852,7 @@ Query_cache::insert(Query_cache_tls *query_cache_tls,
851852
DBUG_ENTER("Query_cache::insert");
852853

853854
/* See the comment on double-check locking usage above. */
854-
if (query_cache_tls->first_query_block == NULL)
855+
if (is_disabled() || query_cache_tls->first_query_block == NULL)
855856
DBUG_VOID_RETURN;
856857

857858
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
@@ -913,7 +914,7 @@ Query_cache::abort(Query_cache_tls *query_cache_tls)
913914
THD *thd= current_thd;
914915

915916
/* See the comment on double-check locking usage above. */
916-
if (query_cache_tls->first_query_block == NULL)
917+
if (is_disabled() || query_cache_tls->first_query_block == NULL)
917918
DBUG_VOID_RETURN;
918919

919920
if (try_lock())
@@ -1055,7 +1056,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg,
10551056
min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)),
10561057
def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)),
10571058
def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)),
1058-
initialized(0)
1059+
initialized(0), m_query_cache_is_disabled(FALSE)
10591060
{
10601061
ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) +
10611062
ALIGN_SIZE(sizeof(Query_cache_block_table)) +
@@ -1362,8 +1363,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
13621363
13631364
See also a note on double-check locking usage above.
13641365
*/
1365-
if (thd->locked_tables || thd->variables.query_cache_type == 0 ||
1366-
query_cache_size == 0)
1366+
if (is_disabled() || thd->locked_tables ||
1367+
thd->variables.query_cache_type == 0 || query_cache_size == 0)
13671368
goto err;
13681369

13691370
if (!thd->lex->safe_to_cache_query)
@@ -1669,6 +1670,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
16691670
my_bool using_transactions)
16701671
{
16711672
DBUG_ENTER("Query_cache::invalidate (table list)");
1673+
if (is_disabled())
1674+
DBUG_VOID_RETURN;
16721675

16731676
using_transactions= using_transactions &&
16741677
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
@@ -1699,6 +1702,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
16991702
void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
17001703
{
17011704
DBUG_ENTER("Query_cache::invalidate (changed table list)");
1705+
if (is_disabled())
1706+
DBUG_VOID_RETURN;
1707+
17021708
THD *thd= current_thd;
17031709
for (; tables_used; tables_used= tables_used->next)
17041710
{
@@ -1724,8 +1730,11 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
17241730
*/
17251731
void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
17261732
{
1727-
THD *thd= current_thd;
17281733
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
1734+
if (is_disabled())
1735+
DBUG_VOID_RETURN;
1736+
1737+
THD *thd= current_thd;
17291738
for (; tables_used; tables_used= tables_used->next_local)
17301739
{
17311740
thd_proc_info(thd, "invalidating query cache entries (table)");
@@ -1746,7 +1755,9 @@ void Query_cache::invalidate(THD *thd, TABLE *table,
17461755
my_bool using_transactions)
17471756
{
17481757
DBUG_ENTER("Query_cache::invalidate (table)");
1749-
1758+
if (is_disabled())
1759+
DBUG_VOID_RETURN;
1760+
17501761
using_transactions= using_transactions &&
17511762
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
17521763
if (using_transactions &&
@@ -1763,6 +1774,8 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
17631774
my_bool using_transactions)
17641775
{
17651776
DBUG_ENTER("Query_cache::invalidate (key)");
1777+
if (is_disabled())
1778+
DBUG_VOID_RETURN;
17661779

17671780
using_transactions= using_transactions &&
17681781
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
@@ -1781,9 +1794,12 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
17811794

17821795
void Query_cache::invalidate(char *db)
17831796
{
1784-
bool restart= FALSE;
1797+
17851798
DBUG_ENTER("Query_cache::invalidate (db)");
1799+
if (is_disabled())
1800+
DBUG_VOID_RETURN;
17861801

1802+
bool restart= FALSE;
17871803
/*
17881804
Lock the query cache and queue all invalidation attempts to avoid
17891805
the risk of a race between invalidation, cache inserts and flushes.
@@ -1868,6 +1884,9 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
18681884
void Query_cache::flush()
18691885
{
18701886
DBUG_ENTER("Query_cache::flush");
1887+
if (is_disabled())
1888+
DBUG_VOID_RETURN;
1889+
18711890
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
18721891
debug_wait_for_kill("wait_in_query_cache_flush1"););
18731892

@@ -1899,6 +1918,9 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
18991918
{
19001919
DBUG_ENTER("Query_cache::pack");
19011920

1921+
if (is_disabled())
1922+
DBUG_VOID_RETURN;
1923+
19021924
/*
19031925
If the entire qc is being invalidated we can bail out early
19041926
instead of waiting for the lock.
@@ -1956,6 +1978,15 @@ void Query_cache::init()
19561978
pthread_cond_init(&COND_cache_status_changed, NULL);
19571979
m_cache_lock_status= Query_cache::UNLOCKED;
19581980
initialized = 1;
1981+
/*
1982+
If we explicitly turn off query cache from the command line query cache will
1983+
be disabled for the reminder of the server life time. This is because we
1984+
want to avoid locking the QC specific mutex if query cache isn't going to
1985+
be used.
1986+
*/
1987+
if (global_system_variables.query_cache_type == 0)
1988+
query_cache.disable_query_cache();
1989+
19591990
DBUG_VOID_RETURN;
19601991
}
19611992

@@ -4660,3 +4691,4 @@ my_bool Query_cache::in_table_list(Query_cache_block_table * root,
46604691
#endif /* DBUG_OFF */
46614692

46624693
#endif /*HAVE_QUERY_CACHE*/
4694+

sql/sql_cache.h

+5
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,11 @@ class Query_cache
281281
enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED };
282282
Cache_lock_status m_cache_lock_status;
283283

284+
bool m_query_cache_is_disabled;
285+
284286
void free_query_internal(Query_cache_block *point);
285287
void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length);
288+
void disable_query_cache(void) { m_query_cache_is_disabled= TRUE; }
286289

287290
protected:
288291
/*
@@ -426,6 +429,8 @@ class Query_cache
426429
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
427430
uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
428431

432+
bool is_disabled(void) { return m_query_cache_is_disabled; }
433+
429434
/* initialize cache (mutex) */
430435
void init();
431436
/* resize query cache (return real query size, 0 if disabled) */

0 commit comments

Comments
 (0)