Commit cc74bb31 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-4029 SELECT on information_schema using a subquery locks up the...

MDEV-4029 SELECT on information_schema using a subquery locks up the information_schema table due to incorrect mutexes handling

Early evaluation of subqueries in the WHERE conditions on I_S.*_STATUS tables,
otherwise the subquery on this same table will try to acquire LOCK_status twice.

sql/item.h:
  remove unused method
parent 48bf57b0
select variable_name from information_schema.session_status where variable_name =
(select variable_name from information_schema.session_status where variable_name = 'uptime');
variable_name
UPTIME
select variable_name from information_schema.session_variables where variable_name =
(select variable_name from information_schema.session_variables where variable_name = 'basedir');
variable_name
BASEDIR
#
# MDEV-4029 SELECT on information_schema using a subquery locks up the information_schema table due to incorrect mutexes handling
#
select variable_name from information_schema.session_status where variable_name =
(select variable_name from information_schema.session_status where variable_name = 'uptime');
select variable_name from information_schema.session_variables where variable_name =
(select variable_name from information_schema.session_variables where variable_name = 'basedir');
...@@ -1445,7 +1445,6 @@ public: ...@@ -1445,7 +1445,6 @@ public:
*/ */
virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; } virtual bool is_outer_field() const { DBUG_ASSERT(fixed); return FALSE; }
Item* set_expr_cache(THD *thd); Item* set_expr_cache(THD *thd);
virtual Item *get_cached_item() { return NULL; }
virtual Item_equal *get_item_equal() { return NULL; } virtual Item_equal *get_item_equal() { return NULL; }
virtual void set_item_equal(Item_equal *item_eq) {}; virtual void set_item_equal(Item_equal *item_eq) {};
......
...@@ -2595,7 +2595,6 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2595,7 +2595,6 @@ static bool show_status_array(THD *thd, const char *wild,
int len; int len;
LEX_STRING null_lex_str; LEX_STRING null_lex_str;
SHOW_VAR tmp, *var; SHOW_VAR tmp, *var;
COND *partial_cond= 0;
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
bool res= FALSE; bool res= FALSE;
CHARSET_INFO *charset= system_charset_info; CHARSET_INFO *charset= system_charset_info;
...@@ -2609,7 +2608,6 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2609,7 +2608,6 @@ static bool show_status_array(THD *thd, const char *wild,
if (*prefix) if (*prefix)
*prefix_end++= '_'; *prefix_end++= '_';
len=name_buffer + sizeof(name_buffer) - prefix_end; len=name_buffer + sizeof(name_buffer) - prefix_end;
partial_cond= make_cond_for_info_schema(cond, table->pos_in_table_list);
for (; variables->name; variables++) for (; variables->name; variables++)
{ {
...@@ -2632,13 +2630,13 @@ static bool show_status_array(THD *thd, const char *wild, ...@@ -2632,13 +2630,13 @@ static bool show_status_array(THD *thd, const char *wild,
if (show_type == SHOW_ARRAY) if (show_type == SHOW_ARRAY)
{ {
show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type, show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type,
status_var, name_buffer, table, ucase_names, partial_cond); status_var, name_buffer, table, ucase_names, cond);
} }
else else
{ {
if (!(wild && wild[0] && wild_case_compare(system_charset_info, if (!(wild && wild[0] && wild_case_compare(system_charset_info,
name_buffer, wild)) && name_buffer, wild)) &&
(!partial_cond || partial_cond->val_int())) (!cond || cond->val_int()))
{ {
char *value=var->value; char *value=var->value;
const char *pos, *end; // We assign a lot of const's const char *pos, *end; // We assign a lot of const's
...@@ -6898,9 +6896,12 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6898,9 +6896,12 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
schema_table_idx == SCH_GLOBAL_VARIABLES) schema_table_idx == SCH_GLOBAL_VARIABLES)
option_type= OPT_GLOBAL; option_type= OPT_GLOBAL;
COND *partial_cond= make_cond_for_info_schema(cond, tables);
mysql_rwlock_rdlock(&LOCK_system_variables_hash); mysql_rwlock_rdlock(&LOCK_system_variables_hash);
res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, option_type), res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, option_type),
option_type, NULL, "", tables->table, upper_case_names, cond); option_type, NULL, "", tables->table,
upper_case_names, partial_cond);
mysql_rwlock_unlock(&LOCK_system_variables_hash); mysql_rwlock_unlock(&LOCK_system_variables_hash);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
...@@ -6937,13 +6938,18 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -6937,13 +6938,18 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
tmp1= &thd->status_var; tmp1= &thd->status_var;
} }
COND *partial_cond= make_cond_for_info_schema(cond, tables);
// Evaluate and cache const subqueries now, before the mutex.
if (partial_cond)
partial_cond->val_int();
mysql_mutex_lock(&LOCK_status); mysql_mutex_lock(&LOCK_status);
if (option_type == OPT_GLOBAL) if (option_type == OPT_GLOBAL)
calc_sum_of_all_status(&tmp); calc_sum_of_all_status(&tmp);
res= show_status_array(thd, wild, res= show_status_array(thd, wild,
(SHOW_VAR *)all_status_vars.buffer, (SHOW_VAR *)all_status_vars.buffer,
option_type, tmp1, "", tables->table, option_type, tmp1, "", tables->table,
upper_case_names, cond); upper_case_names, partial_cond);
mysql_mutex_unlock(&LOCK_status); mysql_mutex_unlock(&LOCK_status);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment