diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-02-09 15:49:50 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-02-09 15:49:50 +0200 |
commit | cce994057bf7e2bdb62686075de03aeb5db4bbda (patch) | |
tree | 0b1413d979a0c573de8d7c0721d2586b099ad275 /sql | |
parent | 1bed56400e19f39697332205038d0cb1d51b25aa (diff) | |
parent | fd101daa84ec5f70f09c48e3fb7a4ce8f6d26edb (diff) | |
download | mariadb-git-cce994057bf7e2bdb62686075de03aeb5db4bbda.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r-- | sql/backup.cc | 39 | ||||
-rw-r--r-- | sql/opt_range.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 78 | ||||
-rw-r--r-- | sql/sql_select.h | 14 |
4 files changed, 85 insertions, 48 deletions
diff --git a/sql/backup.cc b/sql/backup.cc index 84c3788a4d4..64fa91bdded 100644 --- a/sql/backup.cc +++ b/sql/backup.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, 2020, MariaDB Corporation. +/* Copyright (c) 2018, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. @@ -257,9 +257,13 @@ static bool backup_flush(THD *thd) This will probably require a callback from the InnoDB code. */ +/* Retry to get inital lock for 0.1 + 0.5 + 2.25 + 11.25 + 56.25 = 70.35 sec */ +#define MAX_RETRY_COUNT 5 + static bool backup_block_ddl(THD *thd) { PSI_stage_info org_stage; + uint sleep_time; DBUG_ENTER("backup_block_ddl"); kill_delayed_threads(); @@ -302,18 +306,33 @@ static bool backup_block_ddl(THD *thd) block new DDL's, in addition to all previous blocks We didn't do this lock above, as we wanted DDL's to be executed while we wait for non transactional tables (which may take a while). + + We do this lock in a loop as we can get a deadlock if there are multi-object + ddl statements like + RENAME TABLE t1 TO t2, t3 TO t3 + and the MDL happens in the middle of it. */ THD_STAGE_INFO(thd, stage_waiting_for_ddl); - if (thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, - MDL_BACKUP_WAIT_DDL, - thd->variables.lock_wait_timeout)) + sleep_time= 100; // Start with 0.1 seconds + for (uint i= 0 ; i <= MAX_RETRY_COUNT ; i++) { - /* - Could be a timeout. Downgrade lock to what is was before this function - was called so that this function can be called again - */ - backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH); - goto err; + if (!thd->mdl_context.upgrade_shared_lock(backup_flush_ticket, + MDL_BACKUP_WAIT_DDL, + thd->variables.lock_wait_timeout)) + break; + if (thd->get_stmt_da()->sql_errno() != ER_LOCK_DEADLOCK || thd->killed || + i == MAX_RETRY_COUNT) + { + /* + Could be a timeout. Downgrade lock to what is was before this function + was called so that this function can be called again + */ + backup_flush_ticket->downgrade_lock(MDL_BACKUP_FLUSH); + goto err; + } + thd->clear_error(); // Forget the DEADLOCK error + my_sleep(sleep_time); + sleep_time*= 5; // Wait a bit longer next time } /* There can't be anything more that needs to be logged to ddl log */ diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ce9c46572c7..6366b957377 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -14039,7 +14039,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) key_part_range[1]= last_part; /* Check if cur_part is referenced in the WHERE clause. */ - if (join->conds->walk(&Item::find_item_in_field_list_processor, 0, + if (join->conds->walk(&Item::find_item_in_field_list_processor, true, key_part_range)) { cause= "keypart reference from where clause"; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 44aa68198f5..b4ac18caafc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2021, MariaDB Corporation. + Copyright (c) 2009, 2022, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1730,7 +1730,8 @@ bool JOIN::prepare_stage2() #endif if (select_lex->olap == ROLLUP_TYPE && rollup_init()) goto err; - if (alloc_func_list()) + if (alloc_func_list() || + make_sum_func_list(all_fields, fields_list, false)) goto err; res= FALSE; @@ -2361,7 +2362,21 @@ JOIN::optimize_inner() If all items were resolved by opt_sum_query, there is no need to open any tables. */ - if ((res=opt_sum_query(thd, select_lex->leaf_tables, all_fields, conds))) + + /* + The following resetting and restoring of sum_funcs is needed to + go around a bug in spider where it assumes that + make_sum_func_list() has not been called yet and do logical + choices based on this if special handling of min/max functions should + be done. We disable this special handling while we are trying to find + out if we can replace MIN/MAX values with constants. + */ + Item_sum **save_func_sums= sum_funcs, *tmp_sum_funcs= 0; + sum_funcs= &tmp_sum_funcs; + res= opt_sum_query(thd, select_lex->leaf_tables, all_fields, conds); + sum_funcs= save_func_sums; + + if (res) { DBUG_ASSERT(res >= 0); if (res == HA_ERR_KEY_NOT_FOUND) @@ -2961,18 +2976,14 @@ int JOIN::optimize_stage2() } /* - Remove ORDER BY in the following cases: - - GROUP BY is more specific. Example GROUP BY a, b ORDER BY a - - If there are aggregate functions and no GROUP BY, this always leads - to one row result, no point in sorting. + We can ignore ORDER BY if it's a prefix of the GROUP BY list + (as MariaDB is by default sorting on GROUP BY) or + if there is no GROUP BY and aggregate functions are used + (as the result will only contain one row). */ - if (test_if_subpart(group_list, order) || - (!group_list && tmp_table_param.sum_func_count)) - { - order= 0; - if (is_indexed_agg_distinct(this, NULL)) - sort_and_group= 0; - } + if (order && (test_if_subpart(group_list, order) || + (!group_list && tmp_table_param.sum_func_count))) + order=0; // Can't use sort on head table if using join buffering if (full_join || hash_join) @@ -3004,7 +3015,6 @@ int JOIN::optimize_stage2() if (select_lex->have_window_funcs()) simple_order= FALSE; - /* If the hint FORCE INDEX FOR ORDER BY/GROUP BY is used for the table whose columns are required to be returned in a sorted order, then @@ -3737,7 +3747,7 @@ bool JOIN::make_aggr_tables_info() // for the first table if (group_list || tmp_table_param.sum_func_count) { - if (make_sum_func_list(*curr_all_fields, *curr_fields_list, true, true)) + if (make_sum_func_list(*curr_all_fields, *curr_fields_list, true)) DBUG_RETURN(true); if (prepare_sum_aggregators(thd, sum_funcs, !join_tab->is_using_agg_loose_index_scan())) @@ -3847,7 +3857,7 @@ bool JOIN::make_aggr_tables_info() last_tab->all_fields= &tmp_all_fields3; last_tab->fields= &tmp_fields_list3; } - if (make_sum_func_list(*curr_all_fields, *curr_fields_list, true, true)) + if (make_sum_func_list(*curr_all_fields, *curr_fields_list, true)) DBUG_RETURN(true); if (prepare_sum_aggregators(thd, sum_funcs, !join_tab || @@ -4064,8 +4074,6 @@ JOIN::create_postjoin_aggr_table(JOIN_TAB *tab, List<Item> *table_fields, } else { - if (make_sum_func_list(all_fields, fields_list, false)) - goto err; if (prepare_sum_aggregators(thd, sum_funcs, !join_tab->is_using_agg_loose_index_scan())) goto err; @@ -7317,8 +7325,7 @@ void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) Check for the presence of AGGFN(DISTINCT a) queries that may be subject to loose index scan. - - Check if the query is a subject to AGGFN(DISTINCT) using loose index scan + Check if the query is a subject to AGGFN(DISTINCT) using loose index scan (QUICK_GROUP_MIN_MAX_SELECT). Optionally (if out_args is supplied) will push the arguments of AGGFN(DISTINCT) to the list @@ -7351,14 +7358,11 @@ is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args) Item_sum **sum_item_ptr; bool result= false; - if (join->table_count != 1 || /* reference more than 1 table */ + if (join->table_count != 1 || /* reference more than 1 table */ join->select_distinct || /* or a DISTINCT */ join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */ return false; - if (join->make_sum_func_list(join->all_fields, join->fields_list, true)) - return false; - Bitmap<MAX_FIELDS> first_aggdistinct_fields; bool first_aggdistinct_fields_initialized= false; for (sum_item_ptr= join->sum_funcs; *sum_item_ptr; sum_item_ptr++) @@ -7460,16 +7464,23 @@ add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab) while ((item= select_items_it++)) item->walk(&Item::collect_item_field_processor, 0, &indexed_fields); } - else if (join->tmp_table_param.sum_func_count && - is_indexed_agg_distinct(join, &indexed_fields)) + else if (!join->tmp_table_param.sum_func_count || + !is_indexed_agg_distinct(join, &indexed_fields)) { - join->sort_and_group= 1; - } - else + /* + There where no GROUP BY fields and also either no aggregate + functions or not all aggregate functions where used with the + same DISTINCT (or MIN() / MAX() that works similarly). + Nothing to do there. + */ return; + } if (indexed_fields.elements == 0) + { + /* There where no index we could use to satisfy the GROUP BY */ return; + } /* Intersect the keys of all group fields. */ cur_item= indexed_fields_it++; @@ -25957,16 +25968,13 @@ bool JOIN::alloc_func_list() bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_result_set_metadata, - bool before_group_by, bool recompute) + bool before_group_by) { List_iterator_fast<Item> it(field_list); Item_sum **func; Item *item; DBUG_ENTER("make_sum_func_list"); - if (*sum_funcs && !recompute) - DBUG_RETURN(FALSE); /* We have already initialized sum_funcs. */ - func= sum_funcs; while ((item=it++)) { @@ -26113,7 +26121,7 @@ change_to_use_tmp_fields(THD *thd, Ref_ptr_array ref_pointer_array, Change all funcs to be fields in tmp table. @param thd THD pointer - @param ref_pointer_array array of pointers to top elements of filed list + @param ref_pointer_array array of pointers to top elements of field list @param res_selected_fields new list of items of select item list @param res_all_fields new list of all items @param elements number of elements in select item list diff --git a/sql/sql_select.h b/sql/sql_select.h index c8efb26684c..a8081b8d6e3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1206,7 +1206,17 @@ public: Indicates that grouping will be performed on the result set during query execution. This field belongs to query execution. - @see make_group_fields, alloc_group_fields, JOIN::exec + If 'sort_and_group' is set, then the optimizer is going to use on of + the following algorithms to resolve GROUP BY. + + - If one table, sort the table and then calculate groups on the fly. + - If more than one table, create a temporary table to hold the join, + sort it and then resolve group by on the fly. + + The 'on the fly' calculation is done in end_send_group() + + @see make_group_fields, alloc_group_fields, JOIN::exec, + setup_end_select_func */ bool sort_and_group; bool first_record,full_join, no_field_update; @@ -1585,7 +1595,7 @@ public: bool make_range_rowid_filters(); bool init_range_rowid_filters(); bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields, - bool before_group_by, bool recompute= FALSE); + bool before_group_by); /// Initialzes a slice, see comments for ref_ptrs above. Ref_ptr_array ref_ptr_array_slice(size_t slice_num) |