Bug#17083851 BACKPORT BUG#11765744 TO 5.1, 5.5 AND 5.6
Description: Original fix Bug#11765744 changed mutex to read write lock to avoid multiple recursive lock acquire operation on LOCK_status mutex. On Windows, locking read-write lock recursively is not safe. Slim read-write locks, which MySQL uses if they are supported by Windows version, do not support recursion according to their documentation. For our own implementation of read-write lock, which is used in cases when Windows version doesn't support SRW, recursive locking of read-write lock can easily lead to deadlock if there are concurrent lock requests. Fix: This patch reverts the previous fix for bug#11765744 that used read-write locks. Instead problem of recursive locking for LOCK_status mutex is solved by tracking recursion level using counter in THD object and acquiring lock only once when we enter fill_status() function first time.
This commit is contained in:
parent
f7940e407a
commit
d95e57a328
@ -605,6 +605,7 @@ THD::THD()
|
|||||||
Open_tables_state(refresh_version), rli_fake(NULL), rli_slave(NULL),
|
Open_tables_state(refresh_version), rli_fake(NULL), rli_slave(NULL),
|
||||||
lock_id(&main_lock_id),
|
lock_id(&main_lock_id),
|
||||||
user_time(0), in_sub_stmt(0),
|
user_time(0), in_sub_stmt(0),
|
||||||
|
fill_status_recursion_level(0),
|
||||||
sql_log_bin_toplevel(false),
|
sql_log_bin_toplevel(false),
|
||||||
binlog_table_maps(0), binlog_flags(0UL),
|
binlog_table_maps(0), binlog_flags(0UL),
|
||||||
table_map_for_update(0),
|
table_map_for_update(0),
|
||||||
|
@ -1443,6 +1443,17 @@ public:
|
|||||||
|
|
||||||
/* <> 0 if we are inside of trigger or stored function. */
|
/* <> 0 if we are inside of trigger or stored function. */
|
||||||
uint in_sub_stmt;
|
uint in_sub_stmt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Used by fill_status() to avoid acquiring LOCK_status mutex twice
|
||||||
|
when this function is called recursively (e.g. queries
|
||||||
|
that contains SELECT on I_S.GLOBAL_STATUS with subquery on the
|
||||||
|
same I_S table).
|
||||||
|
Incremented each time fill_status() function is entered and
|
||||||
|
decremented each time before it returns from the function.
|
||||||
|
*/
|
||||||
|
uint fill_status_recursion_level;
|
||||||
|
|
||||||
/* TRUE when the current top has SQL_LOG_BIN ON */
|
/* TRUE when the current top has SQL_LOG_BIN ON */
|
||||||
bool sql_log_bin_toplevel;
|
bool sql_log_bin_toplevel;
|
||||||
|
|
||||||
|
@ -5569,14 +5569,20 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
|
|||||||
tmp1= &thd->status_var;
|
tmp1= &thd->status_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&LOCK_status);
|
/*
|
||||||
|
Avoid recursive acquisition of LOCK_status in cases when WHERE clause
|
||||||
|
represented by "cond" contains subquery on I_S.SESSION/GLOBAL_STATUS.
|
||||||
|
*/
|
||||||
|
if (thd->fill_status_recursion_level++ == 0)
|
||||||
|
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, cond);
|
||||||
pthread_mutex_unlock(&LOCK_status);
|
if (thd->fill_status_recursion_level-- == 1)
|
||||||
|
pthread_mutex_unlock(&LOCK_status);
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user