diff options
author | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-10-29 12:19:36 +0100 |
---|---|---|
committer | Kristofer Pettersson <kristofer.pettersson@sun.com> | 2009-10-29 12:19:36 +0100 |
commit | ddcdacb297ffd42f38743321f7861451e77ce142 (patch) | |
tree | ee40d9b2a4d8b057cf54f1c758a85e0cbc092ab4 /sql | |
parent | 42cdc4df8f4a2ed375d935d7d3dd8a877fa9e007 (diff) | |
download | mariadb-git-ddcdacb297ffd42f38743321f7861451e77ce142.tar.gz |
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)
mysql-test/t/query_cache_disabled-master.opt:
* added test case for bug38551
mysql-test/t/query_cache_disabled.test:
* added test case for bug38551
sql/set_var.cc:
* Added before-trigger to verify that query_cache_type wasn't turned off or on during
runtime.
sql/set_var.h:
* Changed order on how the enumeration is processed. By first projecting the
character representation of the variable to a temporary integer we can have
one function instead of two to check if the value is valid.
sql/share/errmsg-utf8.txt:
* Added error message for query cache disabled state
sql/sql_cache.cc:
* If the query cache is disabled at start up, shorten the execution path and avoid
grabbing the query cache mutex each time the invalidate interface methods are called.
sql/sql_cache.h:
* Added new methods to set the query cache into a disabled state.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/set_var.cc | 62 | ||||
-rw-r--r-- | sql/set_var.h | 14 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 3 | ||||
-rw-r--r-- | sql/sql_cache.cc | 48 | ||||
-rw-r--r-- | sql/sql_cache.h | 5 |
5 files changed, 108 insertions, 24 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc index 32ac78f96ed..36597658077 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -125,8 +125,10 @@ static void fix_net_read_timeout(THD *thd, enum_var_type type); static void fix_net_write_timeout(THD *thd, enum_var_type type); static void fix_net_retry_count(THD *thd, enum_var_type type); static void fix_max_join_size(THD *thd, enum_var_type type); +#ifdef HAVE_QUERY_CACHE static void fix_query_cache_size(THD *thd, enum_var_type type); static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type); +#endif static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); static void fix_max_binlog_size(THD *thd, enum_var_type type); 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", &SV::div_precincrement); static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank", &rpl_recovery_rank); -static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size", - &query_cache_size, - fix_query_cache_size); static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size", &SV::range_alloc_block_size); @@ -557,14 +556,20 @@ sys_var_enum_const sys_thread_handling(&vars, "thread_handling", NULL); #ifdef HAVE_QUERY_CACHE +static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size", + &query_cache_size, + fix_query_cache_size); static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit", - &query_cache.query_cache_limit); -static sys_var_long_ptr sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit", - &query_cache_min_res_unit, - fix_query_cache_min_res_unit); + &query_cache.query_cache_limit); +static sys_var_long_ptr + sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit", + &query_cache_min_res_unit, + fix_query_cache_min_res_unit); +static int check_query_cache_type(THD *thd, set_var *var); static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type", &SV::query_cache_type, - &query_cache_type_typelib); + &query_cache_type_typelib, NULL, + check_query_cache_type); static sys_var_thd_bool sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate", &SV::query_cache_wlock_invalidate); @@ -1131,10 +1136,9 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)), {} #endif /* HAVE_REPLICATION */ - +#ifdef HAVE_QUERY_CACHE static void fix_query_cache_size(THD *thd, enum_var_type type) { -#ifdef HAVE_QUERY_CACHE ulong new_cache_size= query_cache.resize(query_cache_size); /* @@ -1148,11 +1152,35 @@ static void fix_query_cache_size(THD *thd, enum_var_type type) query_cache_size, new_cache_size); query_cache_size= new_cache_size; -#endif } -#ifdef HAVE_QUERY_CACHE +/** + Trigger before query_cache_type variable is updated. + @param thd Thread handler + @param var Pointer to the new variable status + + @return Status code + @retval 1 Failure + @retval 0 Success +*/ + +static int check_query_cache_type(THD *thd, set_var *var) +{ + /* + Don't allow changes of the query_cache_type if the query cache + is disabled. + */ + if (query_cache.is_disabled()) + { + my_error(ER_QUERY_CACHE_DISABLED,MYF(0)); + return 1; + } + + return 0; +} + + static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type) { query_cache_min_res_unit= @@ -3601,6 +3629,16 @@ bool not_all_support_one_shot(List<set_var_base> *var_list) Functions to handle SET mysql_internal_variable=const_expr *****************************************************************************/ +/** + Verify that the supplied value is correct. + + @param thd Thread handler + + @return status code + @retval -1 Failure + @retval 0 Success +*/ + int set_var::check(THD *thd) { if (var->is_readonly()) diff --git a/sql/set_var.h b/sql/set_var.h index a83de6425ae..c08097521d2 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -543,10 +543,16 @@ public: { chain_sys_var(chain); } bool check(THD *thd, set_var *var) { - int ret= 0; - if (check_func) - ret= (*check_func)(thd, var); - return ret ? ret : check_enum(thd, var, enum_names); + /* + check_enum fails if the character representation supplied was wrong + or that the integer value was wrong or missing. + */ + if (check_enum(thd, var, enum_names)) + return TRUE; + else if ((check_func && (*check_func)(thd, var))) + return TRUE; + else + return FALSE; } bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 2b2d60c0657..6a4dfc2d758 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6241,3 +6241,6 @@ ER_UNKNOWN_LOCALE ER_SLAVE_IGNORE_SERVER_IDS eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id" +ER_QUERY_CACHE_DISABLED + eng "Query cache is disabled; restart the server with query_cache_type=1 to enable it" + diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 1141f7009a7..6f550f92987 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -286,6 +286,7 @@ functions: if (and only if) this query has a registered result set writer (thd->net.query_cache_query). 4. Query_cache::invalidate + Query_cache::invalidate_locked_for_write - Called from various places to invalidate query cache based on data- base, table and myisam file name. During an on going invalidation the query cache is temporarily disabled. @@ -851,7 +852,7 @@ Query_cache::insert(Query_cache_tls *query_cache_tls, DBUG_ENTER("Query_cache::insert"); /* See the comment on double-check locking usage above. */ - if (query_cache_tls->first_query_block == NULL) + if (is_disabled() || query_cache_tls->first_query_block == NULL) DBUG_VOID_RETURN; DBUG_EXECUTE_IF("wait_in_query_cache_insert", @@ -913,7 +914,7 @@ Query_cache::abort(Query_cache_tls *query_cache_tls) THD *thd= current_thd; /* See the comment on double-check locking usage above. */ - if (query_cache_tls->first_query_block == NULL) + if (is_disabled() || query_cache_tls->first_query_block == NULL) DBUG_VOID_RETURN; if (try_lock()) @@ -1055,7 +1056,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg, min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)), def_query_hash_size(ALIGN_SIZE(def_query_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)) + ALIGN_SIZE(sizeof(Query_cache_block_table)) + @@ -1362,8 +1363,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) See also a note on double-check locking usage above. */ - if (thd->locked_tables || thd->variables.query_cache_type == 0 || - query_cache_size == 0) + if (is_disabled() || thd->locked_tables || + thd->variables.query_cache_type == 0 || query_cache_size == 0) goto err; if (!thd->lex->safe_to_cache_query) @@ -1669,6 +1670,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, my_bool using_transactions) { DBUG_ENTER("Query_cache::invalidate (table list)"); + if (is_disabled()) + DBUG_VOID_RETURN; using_transactions= using_transactions && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); @@ -1699,6 +1702,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) { DBUG_ENTER("Query_cache::invalidate (changed table list)"); + if (is_disabled()) + DBUG_VOID_RETURN; + THD *thd= current_thd; for (; tables_used; tables_used= tables_used->next) { @@ -1724,8 +1730,11 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used) */ void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used) { - THD *thd= current_thd; DBUG_ENTER("Query_cache::invalidate_locked_for_write"); + if (is_disabled()) + DBUG_VOID_RETURN; + + THD *thd= current_thd; for (; tables_used; tables_used= tables_used->next_local) { thd_proc_info(thd, "invalidating query cache entries (table)"); @@ -1746,7 +1755,9 @@ void Query_cache::invalidate(THD *thd, TABLE *table, my_bool using_transactions) { DBUG_ENTER("Query_cache::invalidate (table)"); - + if (is_disabled()) + DBUG_VOID_RETURN; + using_transactions= using_transactions && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); if (using_transactions && @@ -1763,6 +1774,8 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, my_bool using_transactions) { DBUG_ENTER("Query_cache::invalidate (key)"); + if (is_disabled()) + DBUG_VOID_RETURN; using_transactions= using_transactions && (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); @@ -1781,9 +1794,12 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, void Query_cache::invalidate(char *db) { - bool restart= FALSE; + DBUG_ENTER("Query_cache::invalidate (db)"); + if (is_disabled()) + DBUG_VOID_RETURN; + bool restart= FALSE; /* Lock the query cache and queue all invalidation attempts to avoid 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) void Query_cache::flush() { DBUG_ENTER("Query_cache::flush"); + if (is_disabled()) + DBUG_VOID_RETURN; + DBUG_EXECUTE_IF("wait_in_query_cache_flush1", debug_wait_for_kill("wait_in_query_cache_flush1");); @@ -1899,6 +1918,9 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit) { DBUG_ENTER("Query_cache::pack"); + if (is_disabled()) + DBUG_VOID_RETURN; + /* If the entire qc is being invalidated we can bail out early instead of waiting for the lock. @@ -1956,6 +1978,15 @@ void Query_cache::init() pthread_cond_init(&COND_cache_status_changed, NULL); m_cache_lock_status= Query_cache::UNLOCKED; initialized = 1; + /* + 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) + query_cache.disable_query_cache(); + DBUG_VOID_RETURN; } @@ -4660,3 +4691,4 @@ err2: #endif /* DBUG_OFF */ #endif /*HAVE_QUERY_CACHE*/ + diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 5a5f936c188..6b187ebd6c2 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -281,8 +281,11 @@ private: enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED }; Cache_lock_status m_cache_lock_status; + bool m_query_cache_is_disabled; + void free_query_internal(Query_cache_block *point); void invalidate_table_internal(THD *thd, uchar *key, uint32 key_length); + void disable_query_cache(void) { m_query_cache_is_disabled= TRUE; } protected: /* @@ -426,6 +429,8 @@ protected: uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE, uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE); + bool is_disabled(void) { return m_query_cache_is_disabled; } + /* initialize cache (mutex) */ void init(); /* resize query cache (return real query size, 0 if disabled) */ |