Skip to content

Commit 8d0d445

Browse files
committed
Backport to 10.0: MDEV-8779: mysqld got signal 11 in sql/opt_range_mrr.cc:100(step_down_to)
The crash was caused by range optimizer using RANGE_OPT_PARAM::min_key (and max_key) to store keys. Buffer size was a good upper bound for range analysis and partition pruning, but not for EITS selectivity calculations. Fixed by making these buffers variable-size. The sizes are calculated from [pseudo]indexes used for range analysis.
1 parent abd31ca commit 8d0d445

File tree

3 files changed

+73
-4
lines changed

3 files changed

+73
-4
lines changed

mysql-test/r/selectivity_no_engine.result

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,23 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
276276
Warnings:
277277
Note 1003 select `test`.`ta`.`a` AS `a`,`test`.`tb`.`a` AS `a` from `test`.`t1` `ta` join `test`.`t2` `tb` where ((`test`.`tb`.`a` = `test`.`ta`.`a`) and (`test`.`ta`.`a` < 40) and (`test`.`ta`.`a` < 100))
278278
drop table t0,t1,t2;
279+
#
280+
# MDEV-8779: mysqld got signal 11 in sql/opt_range_mrr.cc:100(step_down_to)
281+
#
282+
set @tmp_mdev8779=@@optimizer_use_condition_selectivity;
283+
set optimizer_use_condition_selectivity=5;
284+
CREATE TABLE t1 (
285+
i int(10) unsigned NOT NULL AUTO_INCREMENT,
286+
n varchar(2048) NOT NULL,
287+
d tinyint(1) unsigned NOT NULL,
288+
p int(10) unsigned NOT NULL,
289+
PRIMARY KEY (i)
290+
) DEFAULT CHARSET=utf8;
291+
insert into t1 values (1,'aaa',1,1), (2,'bbb',2,2);
292+
SELECT * FROM t1 WHERE t1.d = 0 AND t1.p = '1' AND t1.i != '-1' AND t1.n = 'some text';
293+
i n d p
294+
set optimizer_use_condition_selectivity= @tmp_mdev8779;
295+
DROP TABLE t1;
279296
#
280297
# End of the test file
281298
#

mysql-test/t/selectivity_no_engine.test

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,23 @@ explain extended select * from t1 ta, t2 tb where ta.a < 40 and tb.a < 100 and t
210210

211211
drop table t0,t1,t2;
212212

213+
--echo #
214+
--echo # MDEV-8779: mysqld got signal 11 in sql/opt_range_mrr.cc:100(step_down_to)
215+
--echo #
216+
set @tmp_mdev8779=@@optimizer_use_condition_selectivity;
217+
set optimizer_use_condition_selectivity=5;
218+
CREATE TABLE t1 (
219+
i int(10) unsigned NOT NULL AUTO_INCREMENT,
220+
n varchar(2048) NOT NULL,
221+
d tinyint(1) unsigned NOT NULL,
222+
p int(10) unsigned NOT NULL,
223+
PRIMARY KEY (i)
224+
) DEFAULT CHARSET=utf8;
225+
insert into t1 values (1,'aaa',1,1), (2,'bbb',2,2);
226+
SELECT * FROM t1 WHERE t1.d = 0 AND t1.p = '1' AND t1.i != '-1' AND t1.n = 'some text';
227+
set optimizer_use_condition_selectivity= @tmp_mdev8779;
228+
DROP TABLE t1;
229+
213230
--echo #
214231
--echo # End of the test file
215232
--echo #

sql/opt_range.cc

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -876,8 +876,8 @@ class RANGE_OPT_PARAM
876876
Used to store 'current key tuples', in both range analysis and
877877
partitioning (list) analysis
878878
*/
879-
uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
880-
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
879+
uchar *min_key;
880+
uchar *max_key;
881881

882882
/* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
883883
uint alloced_sel_args;
@@ -3066,13 +3066,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
30663066
DBUG_RETURN(0); // Can't use range
30673067
}
30683068
key_parts= param.key_parts;
3069-
thd->mem_root= &alloc;
30703069

30713070
/*
30723071
Make an array with description of all key parts of all table keys.
30733072
This is used in get_mm_parts function.
30743073
*/
30753074
key_info= head->key_info;
3075+
uint max_key_len= 0;
30763076
for (idx=0 ; idx < head->s->keys ; idx++, key_info++)
30773077
{
30783078
KEY_PART_INFO *key_part_info;
@@ -3085,13 +3085,15 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
30853085

30863086
param.key[param.keys]=key_parts;
30873087
key_part_info= key_info->key_part;
3088+
uint cur_key_len= 0;
30883089
for (uint part= 0 ; part < n_key_parts ;
30893090
part++, key_parts++, key_part_info++)
30903091
{
30913092
key_parts->key= param.keys;
30923093
key_parts->part= part;
30933094
key_parts->length= key_part_info->length;
30943095
key_parts->store_length= key_part_info->store_length;
3096+
cur_key_len += key_part_info->store_length;
30953097
key_parts->field= key_part_info->field;
30963098
key_parts->null_bit= key_part_info->null_bit;
30973099
key_parts->image_type =
@@ -3100,10 +3102,21 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
31003102
key_parts->flag= (uint8) key_part_info->key_part_flag;
31013103
}
31023104
param.real_keynr[param.keys++]=idx;
3105+
if (cur_key_len > max_key_len)
3106+
max_key_len= cur_key_len;
31033107
}
31043108
param.key_parts_end=key_parts;
31053109
param.alloced_sel_args= 0;
31063110

3111+
if (!(param.min_key= (uchar*)alloc_root(&alloc,max_key_len)) ||
3112+
!(param.max_key= (uchar*)alloc_root(&alloc,max_key_len)))
3113+
{
3114+
thd->no_errors=0;
3115+
free_root(&alloc,MYF(0)); // Return memory & allocator
3116+
DBUG_RETURN(0); // Can't use range
3117+
}
3118+
3119+
thd->mem_root= &alloc;
31073120
/* Calculate cost of full index read for the shortest covering index */
31083121
if (!head->covering_keys.is_clear_all())
31093122
{
@@ -3327,7 +3340,7 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
33273340
return TRUE;
33283341

33293342
param->key_parts= key_part;
3330-
3343+
uint max_key_len= 0;
33313344
for (field_ptr= table->field; *field_ptr; field_ptr++)
33323345
{
33333346
if (bitmap_is_set(used_fields, (*field_ptr)->field_index))
@@ -3342,6 +3355,8 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
33423355
store_length+= HA_KEY_NULL_LENGTH;
33433356
if (field->real_type() == MYSQL_TYPE_VARCHAR)
33443357
store_length+= HA_KEY_BLOB_LENGTH;
3358+
if (max_key_len < store_length)
3359+
max_key_len= store_length;
33453360
key_part->store_length= store_length;
33463361
key_part->field= field;
33473362
key_part->image_type= Field::itRAW;
@@ -3351,6 +3366,12 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
33513366
key_part++;
33523367
}
33533368
}
3369+
3370+
if (!(param->min_key= (uchar*)alloc_root(param->mem_root, max_key_len)) ||
3371+
!(param->max_key= (uchar*)alloc_root(param->mem_root, max_key_len)))
3372+
{
3373+
return true;
3374+
}
33543375
param->keys= keys;
33553376
param->key_parts_end= key_part;
33563377

@@ -4899,12 +4920,15 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
48994920
Field **field= (ppar->part_fields)? part_info->part_field_array :
49004921
part_info->subpart_field_array;
49014922
bool in_subpart_fields= FALSE;
4923+
uint max_key_len= 0;
4924+
uint cur_key_len;
49024925
for (uint part= 0; part < total_parts; part++, key_part++)
49034926
{
49044927
key_part->key= 0;
49054928
key_part->part= part;
49064929
key_part->length= (uint16)(*field)->key_length();
49074930
key_part->store_length= (uint16)get_partition_field_store_length(*field);
4931+
cur_key_len += key_part->store_length;
49084932

49094933
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
49104934
key_part->length, key_part->store_length));
@@ -4930,10 +4954,21 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
49304954
{
49314955
field= part_info->subpart_field_array;
49324956
in_subpart_fields= TRUE;
4957+
max_key_len= cur_key_len;
4958+
cur_key_len= 0;
49334959
}
49344960
}
49354961
range_par->key_parts_end= key_part;
49364962

4963+
if (cur_key_len > max_key_len)
4964+
max_key_len= cur_key_len;
4965+
4966+
if (!(range_par->min_key= (uchar*)alloc_root(alloc,max_key_len)) ||
4967+
!(range_par->max_key= (uchar*)alloc_root(alloc,max_key_len)))
4968+
{
4969+
return true;
4970+
}
4971+
49374972
DBUG_EXECUTE("info", print_partitioning_index(range_par->key_parts,
49384973
range_par->key_parts_end););
49394974
return FALSE;

0 commit comments

Comments
 (0)