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.
This commit is contained in:
parent
2e11ca36f2
commit
43c6953fa1
8
mysql-test/r/information_schema2.result
Normal file
8
mysql-test/r/information_schema2.result
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
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
|
9
mysql-test/t/information_schema2.test
Normal file
9
mysql-test/t/information_schema2.test
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
#
|
||||||
|
# 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');
|
||||||
|
|
@ -2260,7 +2260,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;
|
||||||
@ -2274,7 +2273,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++)
|
||||||
{
|
{
|
||||||
@ -2297,13 +2295,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
|
||||||
@ -5562,9 +5560,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);
|
||||||
|
|
||||||
rw_rdlock(&LOCK_system_variables_hash);
|
rw_rdlock(&LOCK_system_variables_hash);
|
||||||
res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
|
res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars),
|
||||||
option_type, NULL, "", tables->table, upper_case_names, cond);
|
option_type, NULL, "", tables->table, upper_case_names,
|
||||||
|
partial_cond);
|
||||||
rw_unlock(&LOCK_system_variables_hash);
|
rw_unlock(&LOCK_system_variables_hash);
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
@ -5601,13 +5602,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();
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_status);
|
pthread_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);
|
||||||
pthread_mutex_unlock(&LOCK_status);
|
pthread_mutex_unlock(&LOCK_status);
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user