diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ae191a1a9d3..32461202346 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4656,7 +4656,8 @@ restart: have failed to open since closing tables can trigger removal of elements from the table list (if MERGE tables are involved), */ - close_tables_for_reopen(thd, start, ot_ctx.start_of_statement_svp()); + close_tables_for_reopen(thd, start, ot_ctx.start_of_statement_svp(), + ot_ctx.remove_implicitly_used_deps()); /* Here we rely on the fact that 'tables' still points to the valid @@ -4724,10 +4725,10 @@ restart: /* F.ex. deadlock happened */ if (ot_ctx.can_recover_from_failed_open()) { - DBUG_ASSERT(ot_ctx.get_action() != - Open_table_context::OT_ADD_HISTORY_PARTITION); + DBUG_ASSERT(ot_ctx.remove_implicitly_used_deps()); close_tables_for_reopen(thd, start, - ot_ctx.start_of_statement_svp()); + ot_ctx.start_of_statement_svp(), + ot_ctx.remove_implicitly_used_deps()); if (ot_ctx.recover_from_failed_open()) goto error; @@ -6017,27 +6018,34 @@ bool restart_trans_for_tables(THD *thd, TABLE_LIST *table) trying to reopen tables. NULL if no metadata locks were held and thus all metadata locks should be released. + @param[in] remove_implicit_deps True in case routines and tables implicitly + used by a statement should be removed. */ void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, - const MDL_savepoint &start_of_statement_svp) + const MDL_savepoint &start_of_statement_svp, + bool remove_implicit_deps) { TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); TABLE_LIST *tmp; - /* - If table list consists only from tables from prelocking set, table list - for new attempt should be empty, so we have to update list's root pointer. - */ - if (first_not_own_table == *tables) - *tables= 0; - thd->lex->chop_off_not_own_tables(); - /* Reset MDL tickets for procedures/functions */ - for (Sroutine_hash_entry *rt= - (Sroutine_hash_entry*)thd->lex->sroutines_list.first; - rt; rt= rt->next) - rt->mdl_request.ticket= NULL; - sp_remove_not_own_routines(thd->lex); + if (remove_implicit_deps) + { + /* + If table list consists only from tables from prelocking set, table list + for new attempt should be empty, so we have to update list's root pointer. + */ + if (first_not_own_table == *tables) + *tables= 0; + thd->lex->chop_off_not_own_tables(); + + /* Reset MDL tickets for procedures/functions */ + for (Sroutine_hash_entry *rt= + (Sroutine_hash_entry*)thd->lex->sroutines_list.first; + rt; rt= rt->next) + rt->mdl_request.ticket= NULL; + sp_remove_not_own_routines(thd->lex); + } for (tmp= *tables; tmp; tmp= tmp->next_global) { tmp->table= 0; diff --git a/sql/sql_base.h b/sql/sql_base.h index f80c38a806c..e476880ae81 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -156,7 +156,8 @@ thr_lock_type read_lock_type_for_table(THD *thd, my_bool mysql_rm_tmp_tables(void); void close_tables_for_reopen(THD *thd, TABLE_LIST **tables, - const MDL_savepoint &start_of_statement_svp); + const MDL_savepoint &start_of_statement_svp, + bool remove_implicit_dependencies); bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db, LEX_CSTRING *table, thr_lock_type lock_type); TABLE_LIST *find_table_in_list(TABLE_LIST *table, @@ -566,9 +567,21 @@ public: return m_timeout; } - enum_open_table_action get_action() const + /** + Return true in case tables and routines the statement implicilty + dependent on should be removed, else return false. + + @note The use case when routines and tables the statement implicitly + dependent on shouldn't be removed is the one when a new partition be + created on handling the INSERT statement against a versioning partitioned + table. For this case re-opening a versioning table would result in adding + implicitly dependent routines (e.g. table's triggers) that lead to + allocation of memory on PS mem_root and so leaking a memory until the PS + statement be deallocated. + */ + bool remove_implicitly_used_deps() const { - return m_action; + return m_action != OT_ADD_HISTORY_PARTITION; } uint get_flags() const { return m_flags; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4c9657522d8..a32265f44aa 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2945,7 +2945,7 @@ retry: Deadlock occurred during upgrade of metadata lock. Let us restart acquring and opening tables for LOCK TABLES. */ - close_tables_for_reopen(thd, &tables, mdl_savepoint); + close_tables_for_reopen(thd, &tables, mdl_savepoint, true); if (thd->open_temporary_tables(tables)) goto err; goto retry;