MDEV-3798: [SHOW] EXPLAIN UPDATE/DELETE, Memory leak in binlog.binlog_base64_flag:
- It turns out, there are statements that will call lex_start(thd->lex) after parsing has been finished. lex_start() will set lex->explain=NULL, which will lose the pointer to already allocated Explain_plan object. - To get rid of this, switch to lazy creation of lex->explain. Now, it is created only when we get a part ot query plan.
This commit is contained in:
parent
207f008220
commit
4bed7aa858
@ -86,6 +86,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info
|
|||||||
call might reset the value of current_stmt_binlog_format, so
|
call might reset the value of current_stmt_binlog_format, so
|
||||||
we need to do any changes to that value after this function.
|
we need to do any changes to that value after this function.
|
||||||
*/
|
*/
|
||||||
|
delete_explain_query(thd->lex);
|
||||||
lex_start(ev_thd);
|
lex_start(ev_thd);
|
||||||
mysql_reset_thd_for_next_command(ev_thd, 0);
|
mysql_reset_thd_for_next_command(ev_thd, 0);
|
||||||
|
|
||||||
|
@ -3246,7 +3246,6 @@ sp_instr_set::execute(THD *thd, uint *nextp)
|
|||||||
int
|
int
|
||||||
sp_instr_set::exec_core(THD *thd, uint *nextp)
|
sp_instr_set::exec_core(THD *thd, uint *nextp)
|
||||||
{
|
{
|
||||||
create_explain_query(thd->lex, thd->mem_root);
|
|
||||||
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
|
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
|
@ -228,6 +228,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
query_plan.using_filesort= FALSE;
|
query_plan.using_filesort= FALSE;
|
||||||
DBUG_ENTER("mysql_delete");
|
DBUG_ENTER("mysql_delete");
|
||||||
|
|
||||||
|
create_explain_query(thd->lex, thd->mem_root);
|
||||||
if (open_and_lock_tables(thd, table_list, TRUE, 0))
|
if (open_and_lock_tables(thd, table_list, TRUE, 0))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
@ -946,3 +946,9 @@ void create_explain_query(LEX *lex, MEM_ROOT *mem_root)
|
|||||||
lex->explain->mem_root= mem_root;
|
lex->explain->mem_root= mem_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root)
|
||||||
|
{
|
||||||
|
if (!lex->explain)
|
||||||
|
create_explain_query(lex, mem_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -719,6 +719,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
Item *unused_conds= 0;
|
Item *unused_conds= 0;
|
||||||
DBUG_ENTER("mysql_insert");
|
DBUG_ENTER("mysql_insert");
|
||||||
|
|
||||||
|
create_explain_query(thd->lex, thd->mem_root);
|
||||||
/*
|
/*
|
||||||
Upgrade lock type if the requested lock is incompatible with
|
Upgrade lock type if the requested lock is incompatible with
|
||||||
the current connection mode or table operation.
|
the current connection mode or table operation.
|
||||||
|
@ -448,7 +448,7 @@ void lex_start(THD *thd)
|
|||||||
|
|
||||||
lex->thd= lex->unit.thd= thd;
|
lex->thd= lex->unit.thd= thd;
|
||||||
|
|
||||||
lex->explain= NULL;
|
DBUG_ASSERT(!lex->explain);
|
||||||
|
|
||||||
lex->context_stack.empty();
|
lex->context_stack.empty();
|
||||||
lex->unit.init_query();
|
lex->unit.init_query();
|
||||||
|
@ -622,6 +622,7 @@ class Explain_query;
|
|||||||
|
|
||||||
void delete_explain_query(LEX *lex);
|
void delete_explain_query(LEX *lex);
|
||||||
void create_explain_query(LEX *lex, MEM_ROOT *mem_root);
|
void create_explain_query(LEX *lex, MEM_ROOT *mem_root);
|
||||||
|
void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root);
|
||||||
bool print_explain_query(LEX *lex, THD *thd, String *str);
|
bool print_explain_query(LEX *lex, THD *thd, String *str);
|
||||||
|
|
||||||
class st_select_lex_unit: public st_select_lex_node {
|
class st_select_lex_unit: public st_select_lex_node {
|
||||||
|
@ -2201,8 +2201,6 @@ mysql_execute_command(THD *thd)
|
|||||||
thd->mdl_context.release_transactional_locks();
|
thd->mdl_context.release_transactional_locks();
|
||||||
}
|
}
|
||||||
|
|
||||||
create_explain_query(thd->lex, thd->mem_root);
|
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (lex->sql_command != SQLCOM_SET_OPTION)
|
if (lex->sql_command != SQLCOM_SET_OPTION)
|
||||||
DEBUG_SYNC(thd,"before_execute_sql_command");
|
DEBUG_SYNC(thd,"before_execute_sql_command");
|
||||||
|
@ -1020,6 +1020,7 @@ int JOIN::optimize()
|
|||||||
*/
|
*/
|
||||||
if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED)
|
if (was_optimized != optimized && !res && have_query_plan != QEP_DELETED)
|
||||||
{
|
{
|
||||||
|
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
|
||||||
have_query_plan= QEP_AVAILABLE;
|
have_query_plan= QEP_AVAILABLE;
|
||||||
save_explain_data(thd->lex->explain, false /* can overwrite */,
|
save_explain_data(thd->lex->explain, false /* can overwrite */,
|
||||||
need_tmp,
|
need_tmp,
|
||||||
|
@ -632,7 +632,9 @@ bool st_select_lex_unit::exec()
|
|||||||
|
|
||||||
saved_error= optimize();
|
saved_error= optimize();
|
||||||
|
|
||||||
if (!saved_error && !was_executed && thd->lex->explain)
|
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
|
||||||
|
|
||||||
|
if (!saved_error && !was_executed)
|
||||||
save_union_explain(thd->lex->explain);
|
save_union_explain(thd->lex->explain);
|
||||||
|
|
||||||
if (uncacheable || !item || !item->assigned() || describe)
|
if (uncacheable || !item || !item->assigned() || describe)
|
||||||
@ -782,7 +784,7 @@ bool st_select_lex_unit::exec()
|
|||||||
if (!fake_select_lex->ref_pointer_array)
|
if (!fake_select_lex->ref_pointer_array)
|
||||||
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
|
fake_select_lex->n_child_sum_items+= global_parameters->n_sum_items;
|
||||||
|
|
||||||
if (!was_executed && thd->lex->explain)
|
if (!was_executed)
|
||||||
save_union_explain_part2(thd->lex->explain);
|
save_union_explain_part2(thd->lex->explain);
|
||||||
|
|
||||||
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
|
||||||
|
@ -281,6 +281,7 @@ int mysql_update(THD *thd,
|
|||||||
query_plan.using_filesort= FALSE;
|
query_plan.using_filesort= FALSE;
|
||||||
DBUG_ENTER("mysql_update");
|
DBUG_ENTER("mysql_update");
|
||||||
|
|
||||||
|
create_explain_query(thd->lex, thd->mem_root);
|
||||||
if (open_tables(thd, &table_list, &table_count, 0))
|
if (open_tables(thd, &table_list, &table_count, 0))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user