Rewritten patch of percona - switching query cache on and off, removing comments.
client/mysqltest.cc: Column names. mysql-test/r/grant_cache_no_prot.result: fix of text. mysql-test/r/grant_cache_ps_prot.result: Fix of test. mysql-test/r/query_cache.result: Switching on and off query cache. mysql-test/t/query_cache.test: Switching on and off query cache. mysys/charset.c: Fix of parser. sql/handler.cc: thd added to parameters. sql/log_event.cc: thd added to parameters. sql/log_event_old.cc: thd added to parameters. sql/mysql_priv.h: Fixed functions definitions. sql/mysqld.cc: Comments stripping. sql/set_var.cc: Switching on and off query cache. sql/set_var.h: Switching on and off query cache. sql/share/errmsg.txt: New errors. sql/sql_cache.cc: Switching query cache on and off, removing comments. sql/sql_cache.h: thd added to parameters. sql/sql_class.h: Comments stripping. sql/sql_db.cc: thd added to parameters. sql/sql_lex.cc: lex fixed. sql/sql_parse.cc: thd added to parameters.
This commit is contained in:
parent
0da2df248b
commit
1177bea2f1
@ -112,7 +112,7 @@ static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
|
|||||||
display_metadata= FALSE, display_result_sorted= FALSE;
|
display_metadata= FALSE, display_result_sorted= FALSE;
|
||||||
static my_bool disable_query_log= 0, disable_result_log= 0;
|
static my_bool disable_query_log= 0, disable_result_log= 0;
|
||||||
static my_bool disable_connect_log= 1;
|
static my_bool disable_connect_log= 1;
|
||||||
static my_bool disable_warnings= 0;
|
static my_bool disable_warnings= 0, disable_column_names= 0;
|
||||||
static my_bool prepare_warnings_enabled= 0;
|
static my_bool prepare_warnings_enabled= 0;
|
||||||
static my_bool disable_info= 1;
|
static my_bool disable_info= 1;
|
||||||
static my_bool abort_on_error= 1;
|
static my_bool abort_on_error= 1;
|
||||||
@ -298,6 +298,7 @@ enum enum_commands {
|
|||||||
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
|
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
|
||||||
Q_ENABLE_INFO, Q_DISABLE_INFO,
|
Q_ENABLE_INFO, Q_DISABLE_INFO,
|
||||||
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
|
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
|
||||||
|
Q_ENABLE_COLUMN_NAMES, Q_DISABLE_COLUMN_NAMES,
|
||||||
Q_EXEC, Q_DELIMITER,
|
Q_EXEC, Q_DELIMITER,
|
||||||
Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
|
Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
|
||||||
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
|
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
|
||||||
@ -371,6 +372,8 @@ const char *command_names[]=
|
|||||||
"disable_info",
|
"disable_info",
|
||||||
"enable_metadata",
|
"enable_metadata",
|
||||||
"disable_metadata",
|
"disable_metadata",
|
||||||
|
"enable_column_names",
|
||||||
|
"disable_column_names",
|
||||||
"exec",
|
"exec",
|
||||||
"delimiter",
|
"delimiter",
|
||||||
"disable_abort_on_error",
|
"disable_abort_on_error",
|
||||||
@ -6832,6 +6835,8 @@ void append_table_headings(DYNAMIC_STRING *ds,
|
|||||||
uint num_fields)
|
uint num_fields)
|
||||||
{
|
{
|
||||||
uint col_idx;
|
uint col_idx;
|
||||||
|
if (disable_column_names)
|
||||||
|
return;
|
||||||
for (col_idx= 0; col_idx < num_fields; col_idx++)
|
for (col_idx= 0; col_idx < num_fields; col_idx++)
|
||||||
{
|
{
|
||||||
if (col_idx)
|
if (col_idx)
|
||||||
@ -8344,6 +8349,14 @@ int main(int argc, char **argv)
|
|||||||
display_metadata= 0;
|
display_metadata= 0;
|
||||||
var_set_int("$ENABLED_METADATA", 0);
|
var_set_int("$ENABLED_METADATA", 0);
|
||||||
break;
|
break;
|
||||||
|
case Q_ENABLE_COLUMN_NAMES:
|
||||||
|
disable_column_names= 0;
|
||||||
|
var_set_int("$ENABLED_COLUMN_NAMES", 0);
|
||||||
|
break;
|
||||||
|
case Q_DISABLE_COLUMN_NAMES:
|
||||||
|
disable_column_names= 1;
|
||||||
|
var_set_int("$ENABLED_COLUMN_NAMES", 1);
|
||||||
|
break;
|
||||||
case Q_SOURCE: do_source(command); break;
|
case Q_SOURCE: do_source(command); break;
|
||||||
case Q_SLEEP: do_sleep(command, 0); break;
|
case Q_SLEEP: do_sleep(command, 0); break;
|
||||||
case Q_REAL_SLEEP: do_sleep(command, 1); break;
|
case Q_REAL_SLEEP: do_sleep(command, 1); break;
|
||||||
|
@ -148,7 +148,8 @@ enum my_lex_states
|
|||||||
MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR,
|
MY_LEX_USER_VARIABLE_DELIMITER, MY_LEX_SYSTEM_VAR,
|
||||||
MY_LEX_IDENT_OR_KEYWORD,
|
MY_LEX_IDENT_OR_KEYWORD,
|
||||||
MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR,
|
MY_LEX_IDENT_OR_HEX, MY_LEX_IDENT_OR_BIN, MY_LEX_IDENT_OR_NCHAR,
|
||||||
MY_LEX_STRING_OR_DELIMITER
|
MY_LEX_STRING_OR_DELIMITER, MY_LEX_MINUS_OR_COMMENT, MY_LEX_PLACEHOLDER,
|
||||||
|
MY_LEX_COMMA
|
||||||
};
|
};
|
||||||
|
|
||||||
struct charset_info_st;
|
struct charset_info_st;
|
||||||
|
@ -174,7 +174,7 @@ Variable_name Value
|
|||||||
Qcache_hits 7
|
Qcache_hits 7
|
||||||
show status like "Qcache_not_cached";
|
show status like "Qcache_not_cached";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_not_cached 7
|
Qcache_not_cached 4
|
||||||
----- establish connection user4 (user=mysqltest_1) -----
|
----- establish connection user4 (user=mysqltest_1) -----
|
||||||
select "user4";
|
select "user4";
|
||||||
user4
|
user4
|
||||||
@ -205,7 +205,7 @@ Variable_name Value
|
|||||||
Qcache_hits 8
|
Qcache_hits 8
|
||||||
show status like "Qcache_not_cached";
|
show status like "Qcache_not_cached";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_not_cached 8
|
Qcache_not_cached 5
|
||||||
----- close connections -----
|
----- close connections -----
|
||||||
----- switch to connection default -----
|
----- switch to connection default -----
|
||||||
set names binary;
|
set names binary;
|
||||||
|
@ -174,7 +174,7 @@ Variable_name Value
|
|||||||
Qcache_hits 7
|
Qcache_hits 7
|
||||||
show status like "Qcache_not_cached";
|
show status like "Qcache_not_cached";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_not_cached 4
|
Qcache_not_cached 3
|
||||||
----- establish connection user4 (user=mysqltest_1) -----
|
----- establish connection user4 (user=mysqltest_1) -----
|
||||||
select "user4";
|
select "user4";
|
||||||
user4
|
user4
|
||||||
@ -205,7 +205,7 @@ Variable_name Value
|
|||||||
Qcache_hits 8
|
Qcache_hits 8
|
||||||
show status like "Qcache_not_cached";
|
show status like "Qcache_not_cached";
|
||||||
Variable_name Value
|
Variable_name Value
|
||||||
Qcache_not_cached 5
|
Qcache_not_cached 4
|
||||||
----- close connections -----
|
----- close connections -----
|
||||||
----- switch to connection default -----
|
----- switch to connection default -----
|
||||||
set names binary;
|
set names binary;
|
||||||
|
@ -1639,6 +1639,7 @@ set GLOBAL query_cache_type=default;
|
|||||||
set GLOBAL query_cache_limit=default;
|
set GLOBAL query_cache_limit=default;
|
||||||
set GLOBAL query_cache_min_res_unit=default;
|
set GLOBAL query_cache_min_res_unit=default;
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
set local query_cache_type=default;
|
||||||
FLUSH STATUS;
|
FLUSH STATUS;
|
||||||
SET GLOBAL query_cache_size=10*1024*1024;
|
SET GLOBAL query_cache_size=10*1024*1024;
|
||||||
SET @save_concurrent_insert= @@concurrent_insert;
|
SET @save_concurrent_insert= @@concurrent_insert;
|
||||||
@ -1823,3 +1824,33 @@ SELECT 1 FROM t1 GROUP BY
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET GLOBAL query_cache_size= default;
|
SET GLOBAL query_cache_size= default;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
New query cache switching OFF mechanism test
|
||||||
|
set global query_cache_size=1024*1024*20;
|
||||||
|
set global query_cache_type=on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
20971520 ON ON
|
||||||
|
set global query_cache_size=0;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
0 ON ON
|
||||||
|
set global query_cache_size=1024*1024*20;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
20971520 ON ON
|
||||||
|
set global query_cache_type=off;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
20971520 OFF OFF
|
||||||
|
set global query_cache_type=on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
20971520 ON OFF
|
||||||
|
set local query_cache_type= on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
@@query_cache_size @@global.query_cache_type @@local.query_cache_type
|
||||||
|
20971520 ON ON
|
||||||
|
restore defaults
|
||||||
|
SET GLOBAL query_cache_type= default;
|
||||||
|
SET GLOBAL query_cache_size= default;
|
||||||
|
SET LOCAL query_cache_type= default;
|
||||||
|
@ -1255,6 +1255,7 @@ set GLOBAL query_cache_type=default;
|
|||||||
set GLOBAL query_cache_limit=default;
|
set GLOBAL query_cache_limit=default;
|
||||||
set GLOBAL query_cache_min_res_unit=default;
|
set GLOBAL query_cache_min_res_unit=default;
|
||||||
set GLOBAL query_cache_size=default;
|
set GLOBAL query_cache_size=default;
|
||||||
|
set local query_cache_type=default;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Bug#33756 - query cache with concurrent_insert=0 appears broken
|
# Bug#33756 - query cache with concurrent_insert=0 appears broken
|
||||||
@ -1515,3 +1516,23 @@ SET GLOBAL query_cache_size= default;
|
|||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
|
||||||
|
--echo New query cache switching OFF mechanism test
|
||||||
|
set global query_cache_size=1024*1024*20;
|
||||||
|
set global query_cache_type=on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
set global query_cache_size=0;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
set global query_cache_size=1024*1024*20;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
set global query_cache_type=off;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
set global query_cache_type=on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
set local query_cache_type= on;
|
||||||
|
select @@query_cache_size, @@global.query_cache_type, @@local.query_cache_type;
|
||||||
|
|
||||||
|
|
||||||
|
--echo restore defaults
|
||||||
|
SET GLOBAL query_cache_type= default;
|
||||||
|
SET GLOBAL query_cache_size= default;
|
||||||
|
SET LOCAL query_cache_type= default;
|
||||||
|
@ -97,6 +97,9 @@ static my_bool init_state_maps(struct charset_info_st *cs)
|
|||||||
state_map[(uchar)'@']= (uchar) MY_LEX_USER_END;
|
state_map[(uchar)'@']= (uchar) MY_LEX_USER_END;
|
||||||
state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER;
|
state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER;
|
||||||
state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER;
|
state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER;
|
||||||
|
state_map[(uchar)'-']= (uchar) MY_LEX_MINUS_OR_COMMENT;
|
||||||
|
state_map[(uchar)',']= (uchar) MY_LEX_COMMA;
|
||||||
|
state_map[(uchar)'?']= (uchar) MY_LEX_PLACEHOLDER;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a second map to make it faster to find identifiers
|
Create a second map to make it faster to find identifiers
|
||||||
|
@ -1311,7 +1311,7 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
if (thd->transaction.changed_tables)
|
if (thd->transaction.changed_tables)
|
||||||
query_cache.invalidate(thd->transaction.changed_tables);
|
query_cache.invalidate(thd, thd->transaction.changed_tables);
|
||||||
#endif
|
#endif
|
||||||
thd->variables.tx_isolation=thd->session_tx_isolation;
|
thd->variables.tx_isolation=thd->session_tx_isolation;
|
||||||
}
|
}
|
||||||
|
@ -7964,7 +7964,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache.invalidate_locked_for_write(rli->tables_to_lock);
|
query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
|
|||||||
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache.invalidate_locked_for_write(rli->tables_to_lock);
|
query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1636,7 +1636,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache.invalidate_locked_for_write(rli->tables_to_lock);
|
query_cache.invalidate_locked_for_write(thd, rli->tables_to_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,7 +989,7 @@ struct Query_cache_query_flags
|
|||||||
#define query_cache_resize(A) query_cache.resize(A)
|
#define query_cache_resize(A) query_cache.resize(A)
|
||||||
#define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A)
|
#define query_cache_set_min_res_unit(A) query_cache.set_min_res_unit(A)
|
||||||
#define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C)
|
#define query_cache_invalidate3(A, B, C) query_cache.invalidate(A, B, C)
|
||||||
#define query_cache_invalidate1(A) query_cache.invalidate(A)
|
#define query_cache_invalidate1(A,B) query_cache.invalidate(A,B)
|
||||||
#define query_cache_send_result_to_client(A, B, C) \
|
#define query_cache_send_result_to_client(A, B, C) \
|
||||||
query_cache.send_result_to_client(A, B, C)
|
query_cache.send_result_to_client(A, B, C)
|
||||||
#define query_cache_invalidate_by_MyISAM_filename_ref \
|
#define query_cache_invalidate_by_MyISAM_filename_ref \
|
||||||
@ -1011,9 +1011,8 @@ struct Query_cache_query_flags
|
|||||||
#define query_cache_invalidate1(A) do { } while(0)
|
#define query_cache_invalidate1(A) do { } while(0)
|
||||||
#define query_cache_send_result_to_client(A, B, C) 0
|
#define query_cache_send_result_to_client(A, B, C) 0
|
||||||
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
|
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
|
||||||
|
#define query_cache_abort(A) do { } while(0)
|
||||||
#define query_cache_abort(A)
|
#define query_cache_end_of_result(A) do { } while(0)
|
||||||
#define query_cache_end_of_result(A)
|
|
||||||
#define query_cache_maybe_disabled(T) 1
|
#define query_cache_maybe_disabled(T) 1
|
||||||
#define query_cache_is_cacheable_query(L) 0
|
#define query_cache_is_cacheable_query(L) 0
|
||||||
#endif /*HAVE_QUERY_CACHE*/
|
#endif /*HAVE_QUERY_CACHE*/
|
||||||
@ -2145,6 +2144,7 @@ extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
|
|||||||
extern my_bool opt_secure_auth, debug_assert_if_crashed_table;
|
extern my_bool opt_secure_auth, debug_assert_if_crashed_table;
|
||||||
extern char* opt_secure_file_priv;
|
extern char* opt_secure_file_priv;
|
||||||
extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements;
|
extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements;
|
||||||
|
extern my_bool opt_query_cache_strip_comments;
|
||||||
extern my_bool sp_automatic_privileges, opt_noacl;
|
extern my_bool sp_automatic_privileges, opt_noacl;
|
||||||
extern my_bool opt_old_style_user_limits, trust_function_creators;
|
extern my_bool opt_old_style_user_limits, trust_function_creators;
|
||||||
extern uint opt_crash_binlog_innodb;
|
extern uint opt_crash_binlog_innodb;
|
||||||
|
@ -587,6 +587,7 @@ my_bool opt_secure_auth= 0;
|
|||||||
char* opt_secure_file_priv= 0;
|
char* opt_secure_file_priv= 0;
|
||||||
my_bool opt_log_slow_admin_statements= 0;
|
my_bool opt_log_slow_admin_statements= 0;
|
||||||
my_bool opt_log_slow_slave_statements= 0;
|
my_bool opt_log_slow_slave_statements= 0;
|
||||||
|
my_bool opt_query_cache_strip_comments = 0;
|
||||||
my_bool lower_case_file_system= 0;
|
my_bool lower_case_file_system= 0;
|
||||||
my_bool opt_large_pages= 0;
|
my_bool opt_large_pages= 0;
|
||||||
my_bool opt_myisam_use_mmap= 0;
|
my_bool opt_myisam_use_mmap= 0;
|
||||||
@ -6113,7 +6114,8 @@ enum options_mysqld
|
|||||||
OPT_DEFAULT_CHARACTER_SET_OLD,
|
OPT_DEFAULT_CHARACTER_SET_OLD,
|
||||||
OPT_MAX_LONG_DATA_SIZE,
|
OPT_MAX_LONG_DATA_SIZE,
|
||||||
OPT_MASTER_VERIFY_CHECKSUM,
|
OPT_MASTER_VERIFY_CHECKSUM,
|
||||||
OPT_SLAVE_SQL_VERIFY_CHECKSUM
|
OPT_SLAVE_SQL_VERIFY_CHECKSUM,
|
||||||
|
OPT_QUERY_CACHE_STRIP_COMMENTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -7552,6 +7554,13 @@ each time the SQL thread starts.",
|
|||||||
&query_cache_size, &query_cache_size, 0, GET_ULONG,
|
&query_cache_size, &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
|
#ifdef HAVE_QUERY_CACHE
|
||||||
|
{"query_cache_strip_comments", OPT_QUERY_CACHE_STRIP_COMMENTS,
|
||||||
|
"Enable and disable optimisation \"strip comment for query cache\" - "
|
||||||
|
"optimisation strip all comments from query while search query result "
|
||||||
|
"in query cache",
|
||||||
|
(uchar**) &opt_query_cache_strip_comments,
|
||||||
|
(uchar**) &opt_query_cache_strip_comments,
|
||||||
|
0, GET_BOOL, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
|
||||||
{"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 "
|
"0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results "
|
||||||
"except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT "
|
"except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT "
|
||||||
|
@ -128,9 +128,11 @@ 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_write_timeout(THD *thd, enum_var_type type);
|
||||||
static void fix_net_retry_count(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);
|
static void fix_max_join_size(THD *thd, enum_var_type type);
|
||||||
static void fix_query_cache_size(THD *thd, enum_var_type type);
|
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#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);
|
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
|
||||||
|
static int check_query_cache_type(THD *thd, set_var *var);
|
||||||
|
static void fix_query_cache_type(THD *thd, enum_var_type type);
|
||||||
#endif
|
#endif
|
||||||
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
|
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_binlog_size(THD *thd, enum_var_type type);
|
||||||
@ -565,9 +567,6 @@ static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment",
|
|||||||
&SV::div_precincrement);
|
&SV::div_precincrement);
|
||||||
static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
|
static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
|
||||||
&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",
|
static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size",
|
||||||
&SV::range_alloc_block_size);
|
&SV::range_alloc_block_size);
|
||||||
@ -635,14 +634,20 @@ sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
|
|||||||
&thread_handling_typelib);
|
&thread_handling_typelib);
|
||||||
|
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#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",
|
static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit",
|
||||||
&query_cache.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",
|
static sys_var_long_ptr
|
||||||
|
sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
|
||||||
&query_cache_min_res_unit,
|
&query_cache_min_res_unit,
|
||||||
fix_query_cache_min_res_unit);
|
fix_query_cache_min_res_unit);
|
||||||
static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type",
|
static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type",
|
||||||
&SV::query_cache_type,
|
&SV::query_cache_type,
|
||||||
&query_cache_type_typelib);
|
&query_cache_type_typelib,
|
||||||
|
fix_query_cache_type,
|
||||||
|
check_query_cache_type);
|
||||||
static sys_var_thd_bool
|
static sys_var_thd_bool
|
||||||
sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
|
sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
|
||||||
&SV::query_cache_wlock_invalidate);
|
&SV::query_cache_wlock_invalidate);
|
||||||
@ -938,6 +943,8 @@ static sys_var_const_str_ptr sys_log_basename(&vars, "log_basename",
|
|||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
static sys_var_const_str_ptr sys_repl_report_host(&vars, "report_host", &report_host);
|
static sys_var_const_str_ptr sys_repl_report_host(&vars, "report_host", &report_host);
|
||||||
static sys_var_const_str_ptr sys_repl_report_user(&vars, "report_user", &report_user);
|
static sys_var_const_str_ptr sys_repl_report_user(&vars, "report_user", &report_user);
|
||||||
|
static sys_var_bool_ptr sys_query_cache_strip_comments(&vars, "query_cache_strip_comments",
|
||||||
|
&opt_query_cache_strip_comments);
|
||||||
static sys_var_const_str_ptr sys_repl_report_password(&vars, "report_password", &report_password);
|
static sys_var_const_str_ptr sys_repl_report_password(&vars, "report_password", &report_password);
|
||||||
|
|
||||||
static uchar *slave_get_report_port(THD *thd)
|
static uchar *slave_get_report_port(THD *thd)
|
||||||
@ -1227,10 +1234,9 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)),
|
|||||||
{}
|
{}
|
||||||
#endif /* HAVE_REPLICATION */
|
#endif /* HAVE_REPLICATION */
|
||||||
|
|
||||||
|
#ifdef HAVE_QUERY_CACHE
|
||||||
static void fix_query_cache_size(THD *thd, enum_var_type type)
|
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);
|
ulong new_cache_size= query_cache.resize(query_cache_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1244,11 +1250,60 @@ static void fix_query_cache_size(THD *thd, enum_var_type type)
|
|||||||
query_cache_size, new_cache_size);
|
query_cache_size, new_cache_size);
|
||||||
|
|
||||||
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 TRUE Failure
|
||||||
|
@retval FALSE 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_disable_in_progress())
|
||||||
|
{
|
||||||
|
my_error(ER_QUERY_CACHE_IS_DISABLED, MYF(0));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (var->type != OPT_GLOBAL &&
|
||||||
|
global_system_variables.query_cache_type == 0 &&
|
||||||
|
var->value->val_int() != 0)
|
||||||
|
{
|
||||||
|
my_error(ER_QUERY_CACHE_IS_GLOBALY_DISABLED, MYF(0));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fix_query_cache_type(THD *thd, enum_var_type type)
|
||||||
|
{
|
||||||
|
if (type == OPT_GLOBAL)
|
||||||
|
{
|
||||||
|
if (global_system_variables.query_cache_type != 0 &&
|
||||||
|
query_cache.is_disabled())
|
||||||
|
{
|
||||||
|
/* if disabling in progress variable will not be set */
|
||||||
|
DBUG_ASSERT(!query_cache.is_disable_in_progress());
|
||||||
|
/* Enable query cache because it was disabled */
|
||||||
|
fix_query_cache_size(thd, type);
|
||||||
|
}
|
||||||
|
else if (global_system_variables.query_cache_type == 0)
|
||||||
|
query_cache.disable_query_cache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
|
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
|
||||||
{
|
{
|
||||||
query_cache_min_res_unit=
|
query_cache_min_res_unit=
|
||||||
@ -3672,6 +3727,16 @@ bool not_all_support_one_shot(List<set_var_base> *var_list)
|
|||||||
Functions to handle SET mysql_internal_variable=const_expr
|
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)
|
int set_var::check(THD *thd)
|
||||||
{
|
{
|
||||||
if (var->is_readonly())
|
if (var->is_readonly())
|
||||||
|
@ -516,10 +516,15 @@ public:
|
|||||||
{ chain_sys_var(chain); }
|
{ chain_sys_var(chain); }
|
||||||
bool check(THD *thd, set_var *var)
|
bool check(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
int ret= 0;
|
/*
|
||||||
if (check_func)
|
check_enum fails if the character representation supplied was wrong
|
||||||
ret= (*check_func)(thd, var);
|
or that the integer value was wrong or missing.
|
||||||
return ret ? ret : check_enum(thd, var, enum_names);
|
*/
|
||||||
|
if (check_enum(thd, var, enum_names))
|
||||||
|
return TRUE;
|
||||||
|
if ((check_func && (*check_func)(thd, var)))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
bool update(THD *thd, set_var *var);
|
bool update(THD *thd, set_var *var);
|
||||||
void set_default(THD *thd, enum_var_type type);
|
void set_default(THD *thd, enum_var_type type);
|
||||||
|
@ -6271,3 +6271,7 @@ ER_DYN_COL_WRONG_CHARSET
|
|||||||
eng "Dynamic column contains unknown character set"
|
eng "Dynamic column contains unknown character set"
|
||||||
ER_ILLEGAL_SUBQUERY_OPTIMIZER_SWITCHES
|
ER_ILLEGAL_SUBQUERY_OPTIMIZER_SWITCHES
|
||||||
eng "At least one of the 'in_to_exists' or 'materialization' optimizer_switch flags must be 'on'."
|
eng "At least one of the 'in_to_exists' or 'materialization' optimizer_switch flags must be 'on'."
|
||||||
|
ER_QUERY_CACHE_IS_DISABLED
|
||||||
|
eng "Query cache is disabled (resize or similar command in progress); repeat this command later"
|
||||||
|
ER_QUERY_CACHE_IS_GLOBALY_DISABLED
|
||||||
|
eng "Query cache is globally disabled and you can't enable it only for this session"
|
||||||
|
515
sql/sql_cache.cc
515
sql/sql_cache.cc
@ -286,6 +286,7 @@ functions:
|
|||||||
if (and only if) this query has a registered result set writer
|
if (and only if) this query has a registered result set writer
|
||||||
(thd->net.query_cache_query).
|
(thd->net.query_cache_query).
|
||||||
4. Query_cache::invalidate
|
4. Query_cache::invalidate
|
||||||
|
Query_cache::invalidate_locked_for_write
|
||||||
- Called from various places to invalidate query cache based on data-
|
- Called from various places to invalidate query cache based on data-
|
||||||
base, table and myisam file name. During an on going invalidation
|
base, table and myisam file name. During an on going invalidation
|
||||||
the query cache is temporarily disabled.
|
the query cache is temporarily disabled.
|
||||||
@ -334,6 +335,8 @@ TODO list:
|
|||||||
#include "../storage/myisammrg/ha_myisammrg.h"
|
#include "../storage/myisammrg/ha_myisammrg.h"
|
||||||
#include "../storage/myisammrg/myrg_def.h"
|
#include "../storage/myisammrg/myrg_def.h"
|
||||||
|
|
||||||
|
const uchar *query_state_map;
|
||||||
|
|
||||||
#ifdef EMBEDDED_LIBRARY
|
#ifdef EMBEDDED_LIBRARY
|
||||||
#include "emb_qcache.h"
|
#include "emb_qcache.h"
|
||||||
#endif
|
#endif
|
||||||
@ -422,6 +425,136 @@ TYPELIB query_cache_type_typelib=
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if character is a white space.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline bool is_white_space(char c)
|
||||||
|
{
|
||||||
|
return (query_state_map[(uint) ((uchar) c)] == MY_LEX_SKIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Generate a query_string without query comments or duplicated space
|
||||||
|
|
||||||
|
@param new_query New query without 'fluff' is stored here
|
||||||
|
@param query Original query
|
||||||
|
@param query_length Length of original query
|
||||||
|
@param additional_length Extra space for query cache we need to allocate
|
||||||
|
in new_query buffer.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
If there is no space to allocate new_query, we will put original query
|
||||||
|
into new_query.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void make_base_query(String *new_query,
|
||||||
|
const char *query, size_t query_length,
|
||||||
|
size_t additional_length)
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
const char *query_end, *last_space;
|
||||||
|
|
||||||
|
/* The following is guaranteed by the query_cache interface */
|
||||||
|
DBUG_ASSERT(query[query_length] == 0);
|
||||||
|
DBUG_ASSERT(!is_white_space(query[0]));
|
||||||
|
|
||||||
|
if (new_query->realloc(query_length + additional_length))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We could not allocate the query. Use original query for
|
||||||
|
the query cache; Better than nothing....
|
||||||
|
*/
|
||||||
|
new_query->set(query, query_length, system_charset_info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer= (char*) new_query->ptr(); // Store base query here
|
||||||
|
query_end= query + query_length;
|
||||||
|
last_space= 0; // No space found yet
|
||||||
|
|
||||||
|
while (query < query_end)
|
||||||
|
{
|
||||||
|
char current = *(query++);
|
||||||
|
switch (current) {
|
||||||
|
case '\'':
|
||||||
|
case '`':
|
||||||
|
case '"':
|
||||||
|
*(buffer++)= current; // copy first quote
|
||||||
|
while (query < query_end)
|
||||||
|
{
|
||||||
|
*(buffer++)= *query;
|
||||||
|
if (*(query++) == current) // found pair quote
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue; // Continue with next symbol
|
||||||
|
case '/': // Start of comment ?
|
||||||
|
/*
|
||||||
|
Comment of format /#!number #/, must be skipped.
|
||||||
|
These may include '"' and other comments, but it should
|
||||||
|
be safe to parse the content as a normal string.
|
||||||
|
*/
|
||||||
|
if (query[0] != '*' || query[1] == '!')
|
||||||
|
break;
|
||||||
|
|
||||||
|
query++; // skip "/"
|
||||||
|
while (++query < query_end)
|
||||||
|
{
|
||||||
|
if (query[0] == '*' && query[1] == '/')
|
||||||
|
{
|
||||||
|
query+= 2;
|
||||||
|
goto insert_space;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; // Will end outer loop
|
||||||
|
case '-':
|
||||||
|
if (*query != '-' || !is_white_space(query[1])) // Not a comment
|
||||||
|
break;
|
||||||
|
query++; // skip second "-", and go to search of "\n"
|
||||||
|
/* fall through */
|
||||||
|
case '#':
|
||||||
|
while (query < query_end)
|
||||||
|
{
|
||||||
|
if (*(query++) == '\n')
|
||||||
|
goto insert_space;
|
||||||
|
}
|
||||||
|
continue; // Will end outer loop
|
||||||
|
default:
|
||||||
|
if (is_white_space(current))
|
||||||
|
goto insert_space;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*(buffer++)= current;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
insert_space:
|
||||||
|
if (buffer != last_space)
|
||||||
|
{
|
||||||
|
*(buffer++)= ' ';
|
||||||
|
last_space= buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (buffer == last_space)
|
||||||
|
buffer--; // Remove the last space
|
||||||
|
*buffer= 0;
|
||||||
|
new_query->length((size_t) (buffer - new_query->ptr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check and change local variable if global one is switched
|
||||||
|
|
||||||
|
@param thd thread handle
|
||||||
|
*/
|
||||||
|
|
||||||
|
void inline fix_local_query_cache_mode(THD *thd)
|
||||||
|
{
|
||||||
|
if (global_system_variables.query_cache_type == 0)
|
||||||
|
thd->variables.query_cache_type= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Serialize access to the query cache.
|
Serialize access to the query cache.
|
||||||
If the lock cannot be granted the thread hangs in a conditional wait which
|
If the lock cannot be granted the thread hangs in a conditional wait which
|
||||||
@ -431,31 +564,47 @@ TYPELIB query_cache_type_typelib=
|
|||||||
effect by another thread. This enables a quick path in execution to skip waits
|
effect by another thread. This enables a quick path in execution to skip waits
|
||||||
when the outcome is known.
|
when the outcome is known.
|
||||||
|
|
||||||
@param use_timeout TRUE if the lock can abort because of a timeout.
|
@param mode TIMEOUT the lock can abort because of a timeout
|
||||||
|
TRY the lock can abort because it is locked now
|
||||||
|
WAIT wait for lock (default)
|
||||||
|
|
||||||
@note use_timeout is optional and default value is FALSE.
|
@note mode is optional and default value is WAIT.
|
||||||
|
|
||||||
@return
|
@return
|
||||||
@retval FALSE An exclusive lock was taken
|
@retval FALSE An exclusive lock was taken
|
||||||
@retval TRUE The locking attempt failed
|
@retval TRUE The locking attempt failed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Query_cache::try_lock(bool use_timeout)
|
bool Query_cache::try_lock(THD *thd, Cache_try_lock_mode mode)
|
||||||
{
|
{
|
||||||
bool interrupt= FALSE;
|
bool interrupt= TRUE;
|
||||||
|
const char* old_proc_info;
|
||||||
DBUG_ENTER("Query_cache::try_lock");
|
DBUG_ENTER("Query_cache::try_lock");
|
||||||
|
|
||||||
|
old_proc_info= thd->proc_info;
|
||||||
|
thd_proc_info(thd,"Waiting on query cache mutex");
|
||||||
|
|
||||||
pthread_mutex_lock(&structure_guard_mutex);
|
pthread_mutex_lock(&structure_guard_mutex);
|
||||||
|
DBUG_EXECUTE_IF("status_wait_query_cache_mutex_sleep", {
|
||||||
|
sleep(5);
|
||||||
|
});
|
||||||
|
if (m_cache_status == DISABLED)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&structure_guard_mutex);
|
||||||
|
thd->proc_info= old_proc_info;
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
m_requests_in_progress++;
|
||||||
|
fix_local_query_cache_mode(thd);
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (m_cache_lock_status == Query_cache::UNLOCKED)
|
if (m_cache_lock_status == Query_cache::UNLOCKED)
|
||||||
{
|
{
|
||||||
m_cache_lock_status= Query_cache::LOCKED;
|
m_cache_lock_status= Query_cache::LOCKED;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
THD *thd= current_thd;
|
|
||||||
if (thd)
|
|
||||||
m_cache_lock_thread_id= thd->thread_id;
|
m_cache_lock_thread_id= thd->thread_id;
|
||||||
#endif
|
#endif
|
||||||
|
interrupt= FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (m_cache_lock_status == Query_cache::LOCKED_NO_WAIT)
|
else if (m_cache_lock_status == Query_cache::LOCKED_NO_WAIT)
|
||||||
@ -464,7 +613,6 @@ bool Query_cache::try_lock(bool use_timeout)
|
|||||||
If query cache is protected by a LOCKED_NO_WAIT lock this thread
|
If query cache is protected by a LOCKED_NO_WAIT lock this thread
|
||||||
should avoid using the query cache as it is being evicted.
|
should avoid using the query cache as it is being evicted.
|
||||||
*/
|
*/
|
||||||
interrupt= TRUE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -474,25 +622,36 @@ bool Query_cache::try_lock(bool use_timeout)
|
|||||||
To prevent send_result_to_client() and query_cache_insert() from
|
To prevent send_result_to_client() and query_cache_insert() from
|
||||||
blocking execution for too long a timeout is put on the lock.
|
blocking execution for too long a timeout is put on the lock.
|
||||||
*/
|
*/
|
||||||
if (use_timeout)
|
if (mode == WAIT)
|
||||||
|
{
|
||||||
|
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
||||||
|
}
|
||||||
|
else if (mode == TIMEOUT)
|
||||||
{
|
{
|
||||||
struct timespec waittime;
|
struct timespec waittime;
|
||||||
set_timespec_nsec(waittime,(ulong)(50000000L)); /* Wait for 50 msec */
|
set_timespec_nsec(waittime,(ulong)(50000000L)); /* Wait for 50 msec */
|
||||||
int res= pthread_cond_timedwait(&COND_cache_status_changed,
|
int res= pthread_cond_timedwait(&COND_cache_status_changed,
|
||||||
&structure_guard_mutex,&waittime);
|
&structure_guard_mutex,&waittime);
|
||||||
if (res == ETIMEDOUT)
|
if (res == ETIMEDOUT)
|
||||||
{
|
|
||||||
interrupt= TRUE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
/**
|
||||||
|
If we are here, then mode is == TRY and there was someone else using
|
||||||
|
the query cache. (m_cache_lock_status != Query_cache::UNLOCKED).
|
||||||
|
Signal that we didn't get a lock.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(m_requests_in_progress > 1);
|
||||||
|
DBUG_ASSERT(mode == TRY);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (interrupt)
|
||||||
|
m_requests_in_progress--;
|
||||||
pthread_mutex_unlock(&structure_guard_mutex);
|
pthread_mutex_unlock(&structure_guard_mutex);
|
||||||
|
thd->proc_info = old_proc_info;
|
||||||
|
|
||||||
DBUG_RETURN(interrupt);
|
DBUG_RETURN(interrupt);
|
||||||
}
|
}
|
||||||
@ -514,10 +673,12 @@ void Query_cache::lock_and_suspend(void)
|
|||||||
DBUG_ENTER("Query_cache::lock_and_suspend");
|
DBUG_ENTER("Query_cache::lock_and_suspend");
|
||||||
|
|
||||||
pthread_mutex_lock(&structure_guard_mutex);
|
pthread_mutex_lock(&structure_guard_mutex);
|
||||||
|
m_requests_in_progress++;
|
||||||
while (m_cache_lock_status != Query_cache::UNLOCKED)
|
while (m_cache_lock_status != Query_cache::UNLOCKED)
|
||||||
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
||||||
m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
|
m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
/* Here thd may not be set during shutdown */
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
if (thd)
|
if (thd)
|
||||||
m_cache_lock_thread_id= thd->thread_id;
|
m_cache_lock_thread_id= thd->thread_id;
|
||||||
@ -537,17 +698,17 @@ void Query_cache::lock_and_suspend(void)
|
|||||||
It is used by all methods which invalidates one or more tables.
|
It is used by all methods which invalidates one or more tables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Query_cache::lock(void)
|
void Query_cache::lock(THD *thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::lock");
|
DBUG_ENTER("Query_cache::lock");
|
||||||
|
|
||||||
pthread_mutex_lock(&structure_guard_mutex);
|
pthread_mutex_lock(&structure_guard_mutex);
|
||||||
|
m_requests_in_progress++;
|
||||||
|
fix_local_query_cache_mode(thd);
|
||||||
while (m_cache_lock_status != Query_cache::UNLOCKED)
|
while (m_cache_lock_status != Query_cache::UNLOCKED)
|
||||||
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
|
||||||
m_cache_lock_status= Query_cache::LOCKED;
|
m_cache_lock_status= Query_cache::LOCKED;
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
THD *thd= current_thd;
|
|
||||||
if (thd)
|
|
||||||
m_cache_lock_thread_id= thd->thread_id;
|
m_cache_lock_thread_id= thd->thread_id;
|
||||||
#endif
|
#endif
|
||||||
pthread_mutex_unlock(&structure_guard_mutex);
|
pthread_mutex_unlock(&structure_guard_mutex);
|
||||||
@ -565,6 +726,7 @@ void Query_cache::unlock(void)
|
|||||||
DBUG_ENTER("Query_cache::unlock");
|
DBUG_ENTER("Query_cache::unlock");
|
||||||
pthread_mutex_lock(&structure_guard_mutex);
|
pthread_mutex_lock(&structure_guard_mutex);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
/* Thd may not be set in resize() at mysqld start */
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
if (thd)
|
if (thd)
|
||||||
DBUG_ASSERT(m_cache_lock_thread_id == thd->thread_id);
|
DBUG_ASSERT(m_cache_lock_thread_id == thd->thread_id);
|
||||||
@ -574,6 +736,14 @@ void Query_cache::unlock(void)
|
|||||||
m_cache_lock_status= Query_cache::UNLOCKED;
|
m_cache_lock_status= Query_cache::UNLOCKED;
|
||||||
DBUG_PRINT("Query_cache",("Sending signal"));
|
DBUG_PRINT("Query_cache",("Sending signal"));
|
||||||
pthread_cond_signal(&COND_cache_status_changed);
|
pthread_cond_signal(&COND_cache_status_changed);
|
||||||
|
DBUG_ASSERT(m_requests_in_progress > 0);
|
||||||
|
m_requests_in_progress--;
|
||||||
|
if (m_requests_in_progress == 0 && m_cache_status == DISABLE_REQUEST)
|
||||||
|
{
|
||||||
|
/* No clients => just free query cache */
|
||||||
|
free_cache();
|
||||||
|
m_cache_status= DISABLED;
|
||||||
|
}
|
||||||
pthread_mutex_unlock(&structure_guard_mutex);
|
pthread_mutex_unlock(&structure_guard_mutex);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -590,25 +760,24 @@ void Query_cache::unlock(void)
|
|||||||
@retval FALSE No directive found.
|
@retval FALSE No directive found.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool has_no_cache_directive(char *sql)
|
static bool has_no_cache_directive(const char *sql)
|
||||||
{
|
{
|
||||||
int i=0;
|
while (is_white_space(*sql))
|
||||||
while (sql[i] == ' ')
|
sql++;
|
||||||
++i;
|
|
||||||
|
|
||||||
if (my_toupper(system_charset_info, sql[i]) == 'S' &&
|
if (my_toupper(system_charset_info, sql[0]) == 'S' &&
|
||||||
my_toupper(system_charset_info, sql[i+1]) == 'Q' &&
|
my_toupper(system_charset_info, sql[1]) == 'Q' &&
|
||||||
my_toupper(system_charset_info, sql[i+2]) == 'L' &&
|
my_toupper(system_charset_info, sql[2]) == 'L' &&
|
||||||
my_toupper(system_charset_info, sql[i+3]) == '_' &&
|
my_toupper(system_charset_info, sql[3]) == '_' &&
|
||||||
my_toupper(system_charset_info, sql[i+4]) == 'N' &&
|
my_toupper(system_charset_info, sql[4]) == 'N' &&
|
||||||
my_toupper(system_charset_info, sql[i+5]) == 'O' &&
|
my_toupper(system_charset_info, sql[5]) == 'O' &&
|
||||||
my_toupper(system_charset_info, sql[i+6]) == '_' &&
|
my_toupper(system_charset_info, sql[6]) == '_' &&
|
||||||
my_toupper(system_charset_info, sql[i+7]) == 'C' &&
|
my_toupper(system_charset_info, sql[7]) == 'C' &&
|
||||||
my_toupper(system_charset_info, sql[i+8]) == 'A' &&
|
my_toupper(system_charset_info, sql[8]) == 'A' &&
|
||||||
my_toupper(system_charset_info, sql[i+9]) == 'C' &&
|
my_toupper(system_charset_info, sql[9]) == 'C' &&
|
||||||
my_toupper(system_charset_info, sql[i+10]) == 'H' &&
|
my_toupper(system_charset_info, sql[10]) == 'H' &&
|
||||||
my_toupper(system_charset_info, sql[i+11]) == 'E' &&
|
my_toupper(system_charset_info, sql[11]) == 'E' &&
|
||||||
my_toupper(system_charset_info, sql[i+12]) == ' ')
|
my_isspace(system_charset_info, sql[12]))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -866,14 +1035,23 @@ 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. */
|
|
||||||
if (net->query_cache_query == 0)
|
if (net->query_cache_query == 0)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
DBUG_ASSERT(current_thd);
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
|
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
|
||||||
debug_wait_for_kill("wait_in_query_cache_insert"); );
|
debug_wait_for_kill("wait_in_query_cache_insert"); );
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
/* First we check if query cache is disable without doing a mutex lock */
|
||||||
|
if(query_cache.is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Lock the cache with try_lock(). try_lock() will fail if
|
||||||
|
cache was disabled between the above test and lock.
|
||||||
|
*/
|
||||||
|
if (query_cache.try_lock(current_thd, Query_cache::WAIT))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
Query_cache_block *query_block= (Query_cache_block*)net->query_cache_query;
|
Query_cache_block *query_block= (Query_cache_block*)net->query_cache_query;
|
||||||
@ -931,7 +1109,7 @@ void query_cache_abort(NET *net)
|
|||||||
if (net->query_cache_query == 0)
|
if (net->query_cache_query == 0)
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
if (query_cache.try_lock(current_thd, Query_cache::WAIT))
|
||||||
{
|
{
|
||||||
net->query_cache_query = 0;
|
net->query_cache_query = 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -984,7 +1162,7 @@ void query_cache_end_of_result(THD *thd)
|
|||||||
emb_count_querycache_size(thd));
|
emb_count_querycache_size(thd));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (query_cache.try_lock())
|
if (query_cache.try_lock(thd, Query_cache::WAIT))
|
||||||
{
|
{
|
||||||
thd->net.query_cache_query= 0;
|
thd->net.query_cache_query= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -1073,6 +1251,7 @@ Query_cache::Query_cache(ulong query_cache_limit_arg,
|
|||||||
query_cache_limit(query_cache_limit_arg),
|
query_cache_limit(query_cache_limit_arg),
|
||||||
queries_in_cache(0), hits(0), inserts(0), refused(0),
|
queries_in_cache(0), hits(0), inserts(0), refused(0),
|
||||||
total_blocks(0), lowmem_prunes(0),
|
total_blocks(0), lowmem_prunes(0),
|
||||||
|
m_cache_status(OK),
|
||||||
min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)),
|
min_allocation_unit(ALIGN_SIZE(min_allocation_unit_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)),
|
||||||
@ -1096,6 +1275,12 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
|
|||||||
query_cache_size_arg));
|
query_cache_size_arg));
|
||||||
DBUG_ASSERT(initialized);
|
DBUG_ASSERT(initialized);
|
||||||
|
|
||||||
|
if (global_system_variables.query_cache_type == 0)
|
||||||
|
{
|
||||||
|
my_error(ER_QUERY_CACHE_IS_DISABLED, MYF(0));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
lock_and_suspend();
|
lock_and_suspend();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1128,8 +1313,17 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
|
|||||||
query_cache_size= query_cache_size_arg;
|
query_cache_size= query_cache_size_arg;
|
||||||
new_query_cache_size= init_cache();
|
new_query_cache_size= init_cache();
|
||||||
|
|
||||||
|
/*
|
||||||
|
m_cache_status is internal query cache switch so switching it on/off
|
||||||
|
will not be reflected on global_system_variables.query_cache_type
|
||||||
|
*/
|
||||||
if (new_query_cache_size)
|
if (new_query_cache_size)
|
||||||
|
{
|
||||||
DBUG_EXECUTE("check_querycache",check_integrity(1););
|
DBUG_EXECUTE("check_querycache",check_integrity(1););
|
||||||
|
m_cache_status= OK; // size > 0 => enable cache
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_cache_status= DISABLED; // size 0 means the cache disabled
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
DBUG_RETURN(new_query_cache_size);
|
DBUG_RETURN(new_query_cache_size);
|
||||||
@ -1148,6 +1342,9 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
|
|||||||
{
|
{
|
||||||
TABLE_COUNTER_TYPE local_tables;
|
TABLE_COUNTER_TYPE local_tables;
|
||||||
ulong tot_length;
|
ulong tot_length;
|
||||||
|
const char *query;
|
||||||
|
size_t query_length;
|
||||||
|
uint8 tables_type;
|
||||||
DBUG_ENTER("Query_cache::store_query");
|
DBUG_ENTER("Query_cache::store_query");
|
||||||
/*
|
/*
|
||||||
Testing 'query_cache_size' without a lock here is safe: the thing
|
Testing 'query_cache_size' without a lock here is safe: the thing
|
||||||
@ -1157,12 +1354,23 @@ 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 (!thd->query_cache_is_applicable || query_cache_size == 0)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("qcache", ("Query cache not ready"));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
uint8 tables_type= 0;
|
}
|
||||||
|
if (thd->lex->sql_command != SQLCOM_SELECT)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("qcache", ("Ignoring not SELECT command"));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
if ((local_tables= is_cacheable(thd, thd->query_length(),
|
/* The following assert fails if we haven't called send_result_to_client */
|
||||||
thd->query(), thd->lex, tables_used,
|
DBUG_ASSERT(thd->base_query.is_alloced() ||
|
||||||
|
thd->base_query.ptr() == thd->query());
|
||||||
|
|
||||||
|
tables_type= 0;
|
||||||
|
if ((local_tables= is_cacheable(thd, thd->lex, tables_used,
|
||||||
&tables_type)))
|
&tables_type)))
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
@ -1239,7 +1447,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
The 'TRUE' parameter indicate that the lock is allowed to timeout
|
The 'TRUE' parameter indicate that the lock is allowed to timeout
|
||||||
|
|
||||||
*/
|
*/
|
||||||
if (try_lock(TRUE))
|
if (try_lock(thd, Query_cache::WAIT))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
if (query_cache_size == 0)
|
if (query_cache_size == 0)
|
||||||
{
|
{
|
||||||
@ -1255,11 +1463,13 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query= thd->base_query.ptr();
|
||||||
|
query_length= thd->base_query.length();
|
||||||
|
|
||||||
/* Key is query + database + flag */
|
/* Key is query + database + flag */
|
||||||
if (thd->db_length)
|
if (thd->db_length)
|
||||||
{
|
{
|
||||||
memcpy(thd->query() + thd->query_length() + 1, thd->db,
|
memcpy((char*) (query + query_length + 1), thd->db, thd->db_length);
|
||||||
thd->db_length);
|
|
||||||
DBUG_PRINT("qcache", ("database: %s length: %u",
|
DBUG_PRINT("qcache", ("database: %s length: %u",
|
||||||
thd->db, (unsigned) thd->db_length));
|
thd->db, (unsigned) thd->db_length));
|
||||||
}
|
}
|
||||||
@ -1267,24 +1477,24 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("No active database"));
|
DBUG_PRINT("qcache", ("No active database"));
|
||||||
}
|
}
|
||||||
tot_length= thd->query_length() + thd->db_length + 1 +
|
tot_length= query_length + thd->db_length + 1 +
|
||||||
QUERY_CACHE_FLAGS_SIZE;
|
QUERY_CACHE_FLAGS_SIZE;
|
||||||
/*
|
/*
|
||||||
We should only copy structure (don't use it location directly)
|
We should only copy structure (don't use it location directly)
|
||||||
because of alignment issue
|
because of alignment issue
|
||||||
*/
|
*/
|
||||||
memcpy((void*) (thd->query() + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
|
memcpy((void*) (query + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
|
||||||
&flags, QUERY_CACHE_FLAGS_SIZE);
|
&flags, QUERY_CACHE_FLAGS_SIZE);
|
||||||
|
|
||||||
/* Check if another thread is processing the same query? */
|
/* Check if another thread is processing the same query? */
|
||||||
Query_cache_block *competitor = (Query_cache_block *)
|
Query_cache_block *competitor = (Query_cache_block *)
|
||||||
hash_search(&queries, (uchar*) thd->query(), tot_length);
|
hash_search(&queries, (uchar*) query, tot_length);
|
||||||
DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor));
|
DBUG_PRINT("qcache", ("competitor 0x%lx", (ulong) competitor));
|
||||||
if (competitor == 0)
|
if (competitor == 0)
|
||||||
{
|
{
|
||||||
/* Query is not in cache and no one is working with it; Store it */
|
/* Query is not in cache and no one is working with it; Store it */
|
||||||
Query_cache_block *query_block;
|
Query_cache_block *query_block;
|
||||||
query_block= write_block_data(tot_length, (uchar*) thd->query(),
|
query_block= write_block_data(tot_length, (uchar*) query,
|
||||||
ALIGN_SIZE(sizeof(Query_cache_query)),
|
ALIGN_SIZE(sizeof(Query_cache_query)),
|
||||||
Query_cache_block::QUERY, local_tables);
|
Query_cache_block::QUERY, local_tables);
|
||||||
if (query_block != 0)
|
if (query_block != 0)
|
||||||
@ -1341,7 +1551,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
DBUG_PRINT("qcache", ("Another thread process same query"));
|
DBUG_PRINT("qcache", ("Another thread process same query"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (thd->lex->sql_command == SQLCOM_SELECT)
|
else
|
||||||
statistic_increment(refused, &structure_guard_mutex);
|
statistic_increment(refused, &structure_guard_mutex);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -1416,7 +1626,7 @@ send_data_in_chunks(NET *net, const uchar *packet, ulong len)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
|
||||||
{
|
{
|
||||||
ulonglong engine_data;
|
ulonglong engine_data;
|
||||||
Query_cache_query *query;
|
Query_cache_query *query;
|
||||||
@ -1427,6 +1637,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
Query_cache_block_table *block_table, *block_table_end;
|
Query_cache_block_table *block_table, *block_table_end;
|
||||||
ulong tot_length;
|
ulong tot_length;
|
||||||
Query_cache_query_flags flags;
|
Query_cache_query_flags flags;
|
||||||
|
const char *sql, *sql_end;
|
||||||
DBUG_ENTER("Query_cache::send_result_to_client");
|
DBUG_ENTER("Query_cache::send_result_to_client");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1436,43 +1647,89 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
|
|
||||||
See also a note on double-check locking usage above.
|
See also a note on double-check locking usage above.
|
||||||
*/
|
*/
|
||||||
if (thd->locked_tables || thd->variables.query_cache_type == 0 ||
|
if (is_disabled() || thd->locked_tables ||
|
||||||
query_cache_size == 0)
|
thd->variables.query_cache_type == 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
DBUG_ASSERT(query_cache_size != 0); // otherwise cache would be disabled
|
||||||
|
|
||||||
if (!thd->lex->safe_to_cache_query)
|
thd->query_cache_is_applicable= 1;
|
||||||
|
sql= org_sql; sql_end= sql + query_length;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Skip all comments at start of query. The following tests is false for
|
||||||
|
all normal queries.
|
||||||
|
*/
|
||||||
|
if (!my_isalpha(system_charset_info, *sql))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("SELECT is non-cacheable"));
|
while (sql < sql_end)
|
||||||
goto err;
|
{
|
||||||
|
char current= *sql;
|
||||||
|
switch (current) {
|
||||||
|
case '/':
|
||||||
|
if (sql[1] != '*')
|
||||||
|
break;
|
||||||
|
sql+= 2; // Skip '/*'
|
||||||
|
if (*sql == '!')
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Found / *!number comment; Skip number to see if sql
|
||||||
|
starts with 'select'
|
||||||
|
*/
|
||||||
|
sql++;
|
||||||
|
while (my_isdigit(system_charset_info, *sql))
|
||||||
|
sql++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
uint i= 0;
|
while (sql++ < sql_end)
|
||||||
/*
|
{
|
||||||
Skip '(' characters in queries like following:
|
if (sql[-1] == '*' && *sql == '/')
|
||||||
(select a from t1) union (select a from t1);
|
{
|
||||||
*/
|
sql++;
|
||||||
while (sql[i]=='(')
|
break;
|
||||||
i++;
|
}
|
||||||
|
}
|
||||||
/*
|
}
|
||||||
Test if the query is a SELECT
|
continue;
|
||||||
(pre-space is removed in dispatch_command).
|
case '-':
|
||||||
|
if (sql[1] != '-' || !is_white_space(sql[2])) // Not a comment
|
||||||
First '/' looks like comment before command it is not
|
break;
|
||||||
frequently appeared in real life, consequently we can
|
sql++; // Skip first '-'
|
||||||
check all such queries, too.
|
/* Fall through */
|
||||||
*/
|
case '#':
|
||||||
if ((my_toupper(system_charset_info, sql[i]) != 'S' ||
|
while (++sql < sql_end)
|
||||||
my_toupper(system_charset_info, sql[i + 1]) != 'E' ||
|
{
|
||||||
my_toupper(system_charset_info, sql[i + 2]) != 'L') &&
|
if (*sql == '\n')
|
||||||
sql[i] != '/')
|
{
|
||||||
|
sql++; // Skip '\n'
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Continue with analyzing current symbol */
|
||||||
|
continue;
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
case ' ':
|
||||||
|
case '(': // To handle (select a from t1) union (select a from t1);
|
||||||
|
sql++;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* We only come here when we found the first word of the sql */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((my_toupper(system_charset_info, sql[0]) != 'S' ||
|
||||||
|
my_toupper(system_charset_info, sql[1]) != 'E' ||
|
||||||
|
my_toupper(system_charset_info, sql[2]) != 'L'))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
|
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query_length > 20 && has_no_cache_directive(&sql[i+6]))
|
if ((sql_end - sql) > 20 && has_no_cache_directive(sql+6))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We do not increase 'refused' statistics here since it will be done
|
We do not increase 'refused' statistics here since it will be done
|
||||||
@ -1481,16 +1738,15 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive"));
|
DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive"));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Try to obtain an exclusive lock on the query cache. If the cache is
|
Try to obtain an exclusive lock on the query cache. If the cache is
|
||||||
disabled or if a full cache flush is in progress, the attempt to
|
disabled or if a full cache flush is in progress, the attempt to
|
||||||
get the lock is aborted.
|
get the lock is aborted.
|
||||||
|
|
||||||
The 'TRUE' parameter indicate that the lock is allowed to timeout
|
The WAIT parameter indicate that the lock is allowed to timeout.
|
||||||
*/
|
*/
|
||||||
if (try_lock(TRUE))
|
if (try_lock(thd, Query_cache::WAIT))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (query_cache_size == 0)
|
if (query_cache_size == 0)
|
||||||
@ -1503,11 +1759,23 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
|
|||||||
DBUG_ASSERT(thd->net.query_cache_query == 0);
|
DBUG_ASSERT(thd->net.query_cache_query == 0);
|
||||||
|
|
||||||
Query_cache_block *query_block;
|
Query_cache_block *query_block;
|
||||||
|
if (opt_query_cache_strip_comments)
|
||||||
|
{
|
||||||
|
make_base_query(&thd->base_query, sql, (size_t) (sql_end - sql),
|
||||||
|
thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE);
|
||||||
|
sql= thd->base_query.ptr();
|
||||||
|
query_length= thd->base_query.length();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql= org_sql;
|
||||||
|
thd->base_query.set(sql, query_length, system_charset_info);
|
||||||
|
}
|
||||||
|
|
||||||
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
|
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
|
||||||
if (thd->db_length)
|
if (thd->db_length)
|
||||||
{
|
{
|
||||||
memcpy(sql+query_length+1, thd->db, thd->db_length);
|
memcpy((char*) (sql+query_length+1), thd->db, thd->db_length);
|
||||||
DBUG_PRINT("qcache", ("database: '%s' length: %u",
|
DBUG_PRINT("qcache", ("database: '%s' length: %u",
|
||||||
thd->db, (unsigned)thd->db_length));
|
thd->db, (unsigned)thd->db_length));
|
||||||
}
|
}
|
||||||
@ -1638,7 +1906,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
temporary tables => assign following variable to make check
|
temporary tables => assign following variable to make check
|
||||||
faster.
|
faster.
|
||||||
*/
|
*/
|
||||||
thd->lex->safe_to_cache_query=0;
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
BLOCK_UNLOCK_RD(query_block);
|
BLOCK_UNLOCK_RD(query_block);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
@ -1654,7 +1922,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
("probably no SELECT access to %s.%s => return to normal processing",
|
("probably no SELECT access to %s.%s => return to normal processing",
|
||||||
table_list.db, table_list.alias));
|
table_list.db, table_list.alias));
|
||||||
unlock();
|
unlock();
|
||||||
thd->lex->safe_to_cache_query=0; // Don't try to cache this
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
BLOCK_UNLOCK_RD(query_block);
|
BLOCK_UNLOCK_RD(query_block);
|
||||||
DBUG_RETURN(-1); // Privilege error
|
DBUG_RETURN(-1); // Privilege error
|
||||||
}
|
}
|
||||||
@ -1663,7 +1931,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
|
DBUG_PRINT("qcache", ("Need to check column privileges for %s.%s",
|
||||||
table_list.db, table_list.alias));
|
table_list.db, table_list.alias));
|
||||||
BLOCK_UNLOCK_RD(query_block);
|
BLOCK_UNLOCK_RD(query_block);
|
||||||
thd->lex->safe_to_cache_query= 0; // Don't try to cache this
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
goto err_unlock; // Parse query
|
goto err_unlock; // Parse query
|
||||||
}
|
}
|
||||||
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
|
#endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
|
||||||
@ -1687,7 +1955,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
table->key_length());
|
table->key_length());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
thd->lex->safe_to_cache_query= 0; // Don't try to cache this
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
goto err_unlock; // Parse query
|
goto err_unlock; // Parse query
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1738,12 +2006,15 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
|
|||||||
|
|
||||||
err_unlock:
|
err_unlock:
|
||||||
unlock();
|
unlock();
|
||||||
err:
|
|
||||||
/*
|
/*
|
||||||
query_plan_flags doesn't have to be changed here as it contains
|
query_plan_flags doesn't have to be changed here as it contains
|
||||||
QPLAN_QC_NO by default
|
QPLAN_QC_NO by default
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(0); // Query was not cached
|
DBUG_RETURN(0); // Query was not cached
|
||||||
|
|
||||||
|
err:
|
||||||
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
|
DBUG_RETURN(0); // Query was not cached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1755,6 +2026,8 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
|
|||||||
my_bool using_transactions)
|
my_bool using_transactions)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::invalidate (table list)");
|
DBUG_ENTER("Query_cache::invalidate (table list)");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
using_transactions= using_transactions &&
|
using_transactions= using_transactions &&
|
||||||
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
||||||
@ -1782,10 +2055,12 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
|
void Query_cache::invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::invalidate (changed table list)");
|
DBUG_ENTER("Query_cache::invalidate (changed table list)");
|
||||||
THD *thd= current_thd;
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
for (; tables_used; tables_used= tables_used->next)
|
for (; tables_used; tables_used= tables_used->next)
|
||||||
{
|
{
|
||||||
thd_proc_info(thd, "invalidating query cache entries (table list)");
|
thd_proc_info(thd, "invalidating query cache entries (table list)");
|
||||||
@ -1808,10 +2083,13 @@ void Query_cache::invalidate(CHANGED_TABLE_LIST *tables_used)
|
|||||||
NOTE
|
NOTE
|
||||||
can be used only for opened tables
|
can be used only for opened tables
|
||||||
*/
|
*/
|
||||||
void Query_cache::invalidate_locked_for_write(TABLE_LIST *tables_used)
|
void Query_cache::invalidate_locked_for_write(THD *thd,
|
||||||
|
TABLE_LIST *tables_used)
|
||||||
{
|
{
|
||||||
THD *thd= current_thd;
|
|
||||||
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
|
DBUG_ENTER("Query_cache::invalidate_locked_for_write");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
for (; tables_used; tables_used= tables_used->next_local)
|
for (; tables_used; tables_used= tables_used->next_local)
|
||||||
{
|
{
|
||||||
thd_proc_info(thd, "invalidating query cache entries (table)");
|
thd_proc_info(thd, "invalidating query cache entries (table)");
|
||||||
@ -1832,6 +2110,8 @@ void Query_cache::invalidate(THD *thd, TABLE *table,
|
|||||||
my_bool using_transactions)
|
my_bool using_transactions)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::invalidate (table)");
|
DBUG_ENTER("Query_cache::invalidate (table)");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
using_transactions= using_transactions &&
|
using_transactions= using_transactions &&
|
||||||
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
||||||
@ -1849,6 +2129,8 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
|
|||||||
my_bool using_transactions)
|
my_bool using_transactions)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::invalidate (key)");
|
DBUG_ENTER("Query_cache::invalidate (key)");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
using_transactions= using_transactions &&
|
using_transactions= using_transactions &&
|
||||||
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN));
|
||||||
@ -1865,18 +2147,19 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
|
|||||||
Remove all cached queries that uses the given database.
|
Remove all cached queries that uses the given database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Query_cache::invalidate(char *db)
|
void Query_cache::invalidate(THD *thd, char *db)
|
||||||
{
|
{
|
||||||
bool restart= FALSE;
|
bool restart;
|
||||||
DBUG_ENTER("Query_cache::invalidate (db)");
|
DBUG_ENTER("Query_cache::invalidate (db)");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
|
restart= FALSE;
|
||||||
/*
|
/*
|
||||||
Lock the query cache and queue all invalidation attempts to avoid
|
Lock the query cache and queue all invalidation attempts to avoid
|
||||||
the risk of a race between invalidation, cache inserts and flushes.
|
the risk of a race between invalidation, cache inserts and flushes.
|
||||||
*/
|
*/
|
||||||
lock();
|
lock(thd);
|
||||||
|
|
||||||
THD *thd= current_thd;
|
|
||||||
|
|
||||||
if (query_cache_size > 0)
|
if (query_cache_size > 0)
|
||||||
{
|
{
|
||||||
@ -1954,6 +2237,9 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
|
|||||||
void Query_cache::flush()
|
void Query_cache::flush()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::flush");
|
DBUG_ENTER("Query_cache::flush");
|
||||||
|
if (is_disabled())
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
|
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
|
||||||
debug_wait_for_kill("wait_in_query_cache_flush1"););
|
debug_wait_for_kill("wait_in_query_cache_flush1"););
|
||||||
|
|
||||||
@ -1981,7 +2267,7 @@ void Query_cache::flush()
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Query_cache::pack(ulong join_limit, uint iteration_limit)
|
void Query_cache::pack(THD *thd, ulong join_limit, uint iteration_limit)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Query_cache::pack");
|
DBUG_ENTER("Query_cache::pack");
|
||||||
|
|
||||||
@ -1989,7 +2275,7 @@ void Query_cache::pack(ulong join_limit, uint iteration_limit)
|
|||||||
If the entire qc is being invalidated we can bail out early
|
If the entire qc is being invalidated we can bail out early
|
||||||
instead of waiting for the lock.
|
instead of waiting for the lock.
|
||||||
*/
|
*/
|
||||||
if (try_lock())
|
if (try_lock(thd, Query_cache::WAIT))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
if (query_cache_size == 0)
|
if (query_cache_size == 0)
|
||||||
@ -2026,11 +2312,25 @@ void Query_cache::destroy()
|
|||||||
pthread_cond_destroy(&COND_cache_status_changed);
|
pthread_cond_destroy(&COND_cache_status_changed);
|
||||||
pthread_mutex_destroy(&structure_guard_mutex);
|
pthread_mutex_destroy(&structure_guard_mutex);
|
||||||
initialized = 0;
|
initialized = 0;
|
||||||
|
DBUG_ASSERT(m_requests_in_progress == 0);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Query_cache::disable_query_cache(void)
|
||||||
|
{
|
||||||
|
m_cache_status= DISABLE_REQUEST;
|
||||||
|
/*
|
||||||
|
If there is no requests in progress try to free buffer.
|
||||||
|
try_lock(TRY) will exit immediately if there is lock.
|
||||||
|
unlock() should free block.
|
||||||
|
*/
|
||||||
|
if (m_requests_in_progress == 0 && !try_lock(current_thd, TRY))
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
init/destroy
|
init/destroy
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@ -2041,7 +2341,19 @@ void Query_cache::init()
|
|||||||
pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST);
|
pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST);
|
||||||
pthread_cond_init(&COND_cache_status_changed, NULL);
|
pthread_cond_init(&COND_cache_status_changed, NULL);
|
||||||
m_cache_lock_status= Query_cache::UNLOCKED;
|
m_cache_lock_status= Query_cache::UNLOCKED;
|
||||||
|
m_cache_status= Query_cache::OK;
|
||||||
|
m_requests_in_progress= 0;
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
|
query_state_map= default_charset_info->state_map;
|
||||||
|
/*
|
||||||
|
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;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2747,7 +3059,7 @@ void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
|
|||||||
Lock the query cache and queue all invalidation attempts to avoid
|
Lock the query cache and queue all invalidation attempts to avoid
|
||||||
the risk of a race between invalidation, cache inserts and flushes.
|
the risk of a race between invalidation, cache inserts and flushes.
|
||||||
*/
|
*/
|
||||||
lock();
|
lock(thd);
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate2",
|
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate2",
|
||||||
debug_wait_for_kill("wait_in_query_cache_invalidate2"); );
|
debug_wait_for_kill("wait_in_query_cache_invalidate2"); );
|
||||||
@ -3528,7 +3840,7 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
|
|||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("Don't cache statement as it refers to "
|
DBUG_PRINT("qcache", ("Don't cache statement as it refers to "
|
||||||
"tables with column privileges."));
|
"tables with column privileges."));
|
||||||
thd->lex->safe_to_cache_query= 0;
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3593,13 +3905,13 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE_COUNTER_TYPE
|
TABLE_COUNTER_TYPE
|
||||||
Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex,
|
Query_cache::is_cacheable(THD *thd, LEX *lex,
|
||||||
TABLE_LIST *tables_used, uint8 *tables_type)
|
TABLE_LIST *tables_used, uint8 *tables_type)
|
||||||
{
|
{
|
||||||
TABLE_COUNTER_TYPE table_count;
|
TABLE_COUNTER_TYPE table_count;
|
||||||
DBUG_ENTER("Query_cache::is_cacheable");
|
DBUG_ENTER("Query_cache::is_cacheable");
|
||||||
|
|
||||||
if (query_cache_is_cacheable_query(lex) &&
|
if (thd->lex->safe_to_cache_query &&
|
||||||
(thd->variables.query_cache_type == 1 ||
|
(thd->variables.query_cache_type == 1 ||
|
||||||
(thd->variables.query_cache_type == 2 && (lex->select_lex.options &
|
(thd->variables.query_cache_type == 2 && (lex->select_lex.options &
|
||||||
OPTION_TO_QUERY_CACHE))))
|
OPTION_TO_QUERY_CACHE))))
|
||||||
@ -3664,7 +3976,7 @@ my_bool Query_cache::ask_handler_allowance(THD *thd,
|
|||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
|
DBUG_PRINT("qcache", ("Handler does not allow caching for %s.%s",
|
||||||
tables_used->db, tables_used->alias));
|
tables_used->db, tables_used->alias));
|
||||||
thd->lex->safe_to_cache_query= 0; // Don't try to cache this
|
thd->query_cache_is_applicable= 0; // Query can't be cached
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4757,3 +5069,4 @@ err2:
|
|||||||
#endif /* DBUG_OFF */
|
#endif /* DBUG_OFF */
|
||||||
|
|
||||||
#endif /*HAVE_QUERY_CACHE*/
|
#endif /*HAVE_QUERY_CACHE*/
|
||||||
|
|
||||||
|
@ -276,8 +276,11 @@ private:
|
|||||||
my_thread_id m_cache_lock_thread_id;
|
my_thread_id m_cache_lock_thread_id;
|
||||||
#endif
|
#endif
|
||||||
pthread_cond_t COND_cache_status_changed;
|
pthread_cond_t COND_cache_status_changed;
|
||||||
|
uint m_requests_in_progress;
|
||||||
enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED };
|
enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED };
|
||||||
Cache_lock_status m_cache_lock_status;
|
Cache_lock_status m_cache_lock_status;
|
||||||
|
enum Cache_staus {OK, DISABLE_REQUEST, DISABLED};
|
||||||
|
Cache_staus m_cache_status;
|
||||||
|
|
||||||
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);
|
||||||
@ -292,7 +295,7 @@ protected:
|
|||||||
2. query block (for operation inside query (query block/results))
|
2. query block (for operation inside query (query block/results))
|
||||||
|
|
||||||
Thread doing cache flush releases the mutex once it sets
|
Thread doing cache flush releases the mutex once it sets
|
||||||
m_cache_status flag, so other threads may bypass the cache as
|
m_cache_lock_status flag, so other threads may bypass the cache as
|
||||||
if it is disabled, not waiting for reset to finish. The exception
|
if it is disabled, not waiting for reset to finish. The exception
|
||||||
is other threads that were going to do cache flush---they'll wait
|
is other threads that were going to do cache flush---they'll wait
|
||||||
till the end of a flush operation.
|
till the end of a flush operation.
|
||||||
@ -407,7 +410,7 @@ protected:
|
|||||||
If query is cacheable return number tables in query
|
If query is cacheable return number tables in query
|
||||||
(query without tables not cached)
|
(query without tables not cached)
|
||||||
*/
|
*/
|
||||||
TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query,
|
TABLE_COUNTER_TYPE is_cacheable(THD *thd,
|
||||||
LEX *lex, TABLE_LIST *tables_used,
|
LEX *lex, TABLE_LIST *tables_used,
|
||||||
uint8 *tables_type);
|
uint8 *tables_type);
|
||||||
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
|
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
|
||||||
@ -423,6 +426,10 @@ protected:
|
|||||||
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
|
uint def_query_hash_size = QUERY_CACHE_DEF_QUERY_HASH_SIZE,
|
||||||
uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
|
uint def_table_hash_size = QUERY_CACHE_DEF_TABLE_HASH_SIZE);
|
||||||
|
|
||||||
|
bool is_disabled(void) { return m_cache_status != OK; }
|
||||||
|
bool is_disable_in_progress(void)
|
||||||
|
{ return m_cache_status == DISABLE_REQUEST; }
|
||||||
|
|
||||||
/* initialize cache (mutex) */
|
/* initialize cache (mutex) */
|
||||||
void init();
|
void init();
|
||||||
/* resize query cache (return real query size, 0 if disabled) */
|
/* resize query cache (return real query size, 0 if disabled) */
|
||||||
@ -442,22 +449,23 @@ protected:
|
|||||||
int send_result_to_client(THD *thd, char *query, uint query_length);
|
int send_result_to_client(THD *thd, char *query, uint query_length);
|
||||||
|
|
||||||
/* Remove all queries that uses any of the listed following tables */
|
/* Remove all queries that uses any of the listed following tables */
|
||||||
void invalidate(THD* thd, TABLE_LIST *tables_used,
|
void invalidate(THD *thd, TABLE_LIST *tables_used,
|
||||||
my_bool using_transactions);
|
my_bool using_transactions);
|
||||||
void invalidate(CHANGED_TABLE_LIST *tables_used);
|
void invalidate(THD *thd, CHANGED_TABLE_LIST *tables_used);
|
||||||
void invalidate_locked_for_write(TABLE_LIST *tables_used);
|
void invalidate_locked_for_write(THD *thd, TABLE_LIST *tables_used);
|
||||||
void invalidate(THD* thd, TABLE *table, my_bool using_transactions);
|
void invalidate(THD *thd, TABLE *table, my_bool using_transactions);
|
||||||
void invalidate(THD *thd, const char *key, uint32 key_length,
|
void invalidate(THD *thd, const char *key, uint32 key_length,
|
||||||
my_bool using_transactions);
|
my_bool using_transactions);
|
||||||
|
|
||||||
/* Remove all queries that uses any of the tables in following database */
|
/* Remove all queries that uses any of the tables in following database */
|
||||||
void invalidate(char *db);
|
void invalidate(THD *thd, char *db);
|
||||||
|
|
||||||
/* Remove all queries that uses any of the listed following table */
|
/* Remove all queries that uses any of the listed following table */
|
||||||
void invalidate_by_MyISAM_filename(const char *filename);
|
void invalidate_by_MyISAM_filename(const char *filename);
|
||||||
|
|
||||||
void flush();
|
void flush();
|
||||||
void pack(ulong join_limit = QUERY_CACHE_PACK_LIMIT,
|
void pack(THD *thd,
|
||||||
|
ulong join_limit = QUERY_CACHE_PACK_LIMIT,
|
||||||
uint iteration_limit = QUERY_CACHE_PACK_ITERATION);
|
uint iteration_limit = QUERY_CACHE_PACK_ITERATION);
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
@ -485,10 +493,13 @@ protected:
|
|||||||
const char *name);
|
const char *name);
|
||||||
my_bool in_blocks(Query_cache_block * point);
|
my_bool in_blocks(Query_cache_block * point);
|
||||||
|
|
||||||
bool try_lock(bool use_timeout= FALSE);
|
enum Cache_try_lock_mode {WAIT, TIMEOUT, TRY};
|
||||||
void lock(void);
|
bool try_lock(THD *thd, Cache_try_lock_mode mode= WAIT);
|
||||||
|
void lock(THD *thd);
|
||||||
void lock_and_suspend(void);
|
void lock_and_suspend(void);
|
||||||
void unlock(void);
|
void unlock(void);
|
||||||
|
|
||||||
|
void disable_query_cache(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Query_cache query_cache;
|
extern Query_cache query_cache;
|
||||||
|
@ -767,8 +767,12 @@ public:
|
|||||||
ENGINE INNODB STATUS.
|
ENGINE INNODB STATUS.
|
||||||
*/
|
*/
|
||||||
LEX_STRING query_string;
|
LEX_STRING query_string;
|
||||||
|
/*
|
||||||
|
If opt_query_cache_strip_comments is set, this contains query without
|
||||||
|
comments. If not set, it contains pointer to query_string.
|
||||||
|
*/
|
||||||
|
String base_query;
|
||||||
Server_side_cursor *cursor;
|
Server_side_cursor *cursor;
|
||||||
|
|
||||||
inline char *query() { return query_string.str; }
|
inline char *query() { return query_string.str; }
|
||||||
inline uint32 query_length() { return (uint32)query_string.length; }
|
inline uint32 query_length() { return (uint32)query_string.length; }
|
||||||
void set_query_inner(char *query_arg, uint32 query_length_arg);
|
void set_query_inner(char *query_arg, uint32 query_length_arg);
|
||||||
@ -789,7 +793,8 @@ public:
|
|||||||
char *db;
|
char *db;
|
||||||
size_t db_length;
|
size_t db_length;
|
||||||
|
|
||||||
public:
|
/* This is set to 1 of last call to send_result_to_client() was ok */
|
||||||
|
my_bool query_cache_is_applicable;
|
||||||
|
|
||||||
/* This constructor is called for backup statements */
|
/* This constructor is called for backup statements */
|
||||||
Statement() {}
|
Statement() {}
|
||||||
|
@ -973,7 +973,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||||||
{
|
{
|
||||||
ha_drop_database(path);
|
ha_drop_database(path);
|
||||||
tmp_disable_binlog(thd);
|
tmp_disable_binlog(thd);
|
||||||
query_cache_invalidate1(db);
|
query_cache_invalidate1(thd, db);
|
||||||
(void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
|
(void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
|
||||||
#ifdef HAVE_EVENT_SCHEDULER
|
#ifdef HAVE_EVENT_SCHEDULER
|
||||||
Events::drop_schema_events(thd, db);
|
Events::drop_schema_events(thd, db);
|
||||||
|
@ -818,21 +818,38 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
yylval->lex_str.length=2;
|
yylval->lex_str.length=2;
|
||||||
return NULL_SYM;
|
return NULL_SYM;
|
||||||
}
|
}
|
||||||
|
/* Fall through */
|
||||||
case MY_LEX_CHAR: // Unknown or single char token
|
case MY_LEX_CHAR: // Unknown or single char token
|
||||||
case MY_LEX_SKIP: // This should not happen
|
case MY_LEX_SKIP: // This should not happen
|
||||||
if (c == '-' && lip->yyPeek() == '-' &&
|
if (c != ')')
|
||||||
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
|
return((int) c);
|
||||||
|
|
||||||
|
case MY_LEX_MINUS_OR_COMMENT:
|
||||||
|
if (lip->yyPeek() == '-' &&
|
||||||
(my_isspace(cs,lip->yyPeekn(1)) ||
|
(my_isspace(cs,lip->yyPeekn(1)) ||
|
||||||
my_iscntrl(cs,lip->yyPeekn(1))))
|
my_iscntrl(cs,lip->yyPeekn(1))))
|
||||||
{
|
{
|
||||||
state=MY_LEX_COMMENT;
|
state=MY_LEX_COMMENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != ')')
|
|
||||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
|
return((int) c);
|
||||||
|
|
||||||
if (c == ',')
|
case MY_LEX_PLACEHOLDER:
|
||||||
{
|
/*
|
||||||
|
Check for a placeholder: it should not precede a possible identifier
|
||||||
|
because of binlogging: when a placeholder is replaced with
|
||||||
|
its value in a query for the binlog, the query must stay
|
||||||
|
grammatically correct.
|
||||||
|
*/
|
||||||
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
|
if (lip->stmt_prepare_mode && !ident_map[(uchar) lip->yyPeek()])
|
||||||
|
return(PARAM_MARKER);
|
||||||
|
return((int) c);
|
||||||
|
|
||||||
|
case MY_LEX_COMMA:
|
||||||
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
/*
|
/*
|
||||||
Warning:
|
Warning:
|
||||||
This is a work around, to make the "remember_name" rule in
|
This is a work around, to make the "remember_name" rule in
|
||||||
@ -843,20 +860,6 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
first token of expr2.
|
first token of expr2.
|
||||||
*/
|
*/
|
||||||
lip->restart_token();
|
lip->restart_token();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Check for a placeholder: it should not precede a possible identifier
|
|
||||||
because of binlogging: when a placeholder is replaced with
|
|
||||||
its value in a query for the binlog, the query must stay
|
|
||||||
grammatically correct.
|
|
||||||
*/
|
|
||||||
if (c == '?' && lip->stmt_prepare_mode &&
|
|
||||||
!ident_map[(uchar) lip->yyPeek()])
|
|
||||||
return(PARAM_MARKER);
|
|
||||||
}
|
|
||||||
|
|
||||||
return((int) c);
|
return((int) c);
|
||||||
|
|
||||||
case MY_LEX_IDENT_OR_NCHAR:
|
case MY_LEX_IDENT_OR_NCHAR:
|
||||||
|
@ -1055,7 +1055,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_running++;
|
thread_running++;
|
||||||
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1252,15 +1251,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
thd->set_query(beginning_of_next_stmt, length);
|
thd->set_query(beginning_of_next_stmt, length);
|
||||||
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
|
||||||
/*
|
/*
|
||||||
Count each statement from the client.
|
Count each statement from the client.
|
||||||
*/
|
*/
|
||||||
statistic_increment(thd->status_var.questions, &LOCK_status);
|
statistic_increment(thd->status_var.questions, &LOCK_status);
|
||||||
|
thd->set_time(); /* Reset the query start time for next query. */
|
||||||
|
VOID(pthread_mutex_lock(&LOCK_thread_count));
|
||||||
thd->query_id= next_query_id();
|
thd->query_id= next_query_id();
|
||||||
thd->set_time(); /* Reset the query start time. */
|
|
||||||
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
|
||||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||||
|
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
||||||
mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
|
mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3552,7 +3551,7 @@ end_with_restore_list:
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
if (thd->variables.query_cache_wlock_invalidate)
|
if (thd->variables.query_cache_wlock_invalidate)
|
||||||
query_cache.invalidate_locked_for_write(first_table);
|
query_cache.invalidate_locked_for_write(thd, first_table);
|
||||||
#endif /*HAVE_QUERY_CACHE*/
|
#endif /*HAVE_QUERY_CACHE*/
|
||||||
thd->locked_tables=thd->lock;
|
thd->locked_tables=thd->lock;
|
||||||
thd->lock=0;
|
thd->lock=0;
|
||||||
@ -7010,7 +7009,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
|||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
if (options & REFRESH_QUERY_CACHE_FREE)
|
if (options & REFRESH_QUERY_CACHE_FREE)
|
||||||
{
|
{
|
||||||
query_cache.pack(); // FLUSH QUERY CACHE
|
query_cache.pack(thd); // FLUSH QUERY CACHE
|
||||||
options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
|
options &= ~REFRESH_QUERY_CACHE; // Don't flush cache, just free memory
|
||||||
}
|
}
|
||||||
if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
|
if (options & (REFRESH_TABLES | REFRESH_QUERY_CACHE))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user