Skip to content

Commit 240b4e8

Browse files
spetruniavuvova
authored andcommitted
MDEV-37913: disable_index_merge_plans causes SELECT data loss when more than 100 ORs
(Variant 2) SEL_TREE* tree_or(SEL_TREE *X, SEL_TREE *Y) tries to conserve memory by reusing object *X for the return value when possible. MDEV-34620 has added logic to disable construction of index_merge plans for N-way ORs with large N. That logic interfered with object reuse logic: for the parameters of: X = SEL_TREE{ trees=[key1_treeA, key2_treeB]} Y = SEL_TREE{ trees=[key1_treeC]} we would decide to reuse object X. For key1, we would produce key_or(key1_treeA, key1_treeC) but key2_treeB would be just left there. Then, we would construct a range scan from key2_treeB. Fixed by moving the "disable building index_merge plans" logic into a location where it would not interfere with object reuse logic.
1 parent 292bab3 commit 240b4e8

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

mysql-test/main/range.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,6 +3736,27 @@ DROP TABLE t1;
37363736
#
37373737
# End of 10.5 tests
37383738
#
3739+
#
3740+
# MDEV-37913: disable_index_merge_plans causes SELECT data loss when more than 100 ORs
3741+
#
3742+
CREATE TABLE t1 (
3743+
id int primary key,
3744+
key1 int,
3745+
index(key1)
3746+
);
3747+
INSERT INTO t1 VALUES
3748+
(1, 1),
3749+
(2, 1),
3750+
(3, 2);
3751+
$query;
3752+
id key1
3753+
1 1
3754+
2 1
3755+
3 2
3756+
drop table t1;
3757+
#
3758+
# End of 10.11 tests
3759+
#
37393760
set global innodb_stats_persistent= @innodb_stats_persistent_save;
37403761
set global innodb_stats_persistent_sample_pages=
37413762
@innodb_stats_persistent_sample_pages_save;

mysql-test/main/range.test

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2533,6 +2533,32 @@ DROP TABLE t1;
25332533
--echo # End of 10.5 tests
25342534
--echo #
25352535

2536+
--echo #
2537+
--echo # MDEV-37913: disable_index_merge_plans causes SELECT data loss when more than 100 ORs
2538+
--echo #
2539+
CREATE TABLE t1 (
2540+
id int primary key,
2541+
key1 int,
2542+
index(key1)
2543+
);
2544+
2545+
INSERT INTO t1 VALUES
2546+
(1, 1),
2547+
(2, 1),
2548+
(3, 2);
2549+
2550+
let $query=`
2551+
select concat('select * from t1 where (key1 = 2 AND id = 3) ',
2552+
REPEAT(' OR (key1 = 1)', 100))
2553+
`;
2554+
2555+
evalp $query;
2556+
2557+
drop table t1;
2558+
2559+
--echo #
2560+
--echo # End of 10.11 tests
2561+
--echo #
25362562
set global innodb_stats_persistent= @innodb_stats_persistent_save;
25372563
set global innodb_stats_persistent_sample_pages=
25382564
@innodb_stats_persistent_sample_pages_save;

mysql-test/main/range_mrr_icp.result

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,6 +3725,27 @@ DROP TABLE t1;
37253725
#
37263726
# End of 10.5 tests
37273727
#
3728+
#
3729+
# MDEV-37913: disable_index_merge_plans causes SELECT data loss when more than 100 ORs
3730+
#
3731+
CREATE TABLE t1 (
3732+
id int primary key,
3733+
key1 int,
3734+
index(key1)
3735+
);
3736+
INSERT INTO t1 VALUES
3737+
(1, 1),
3738+
(2, 1),
3739+
(3, 2);
3740+
$query;
3741+
id key1
3742+
1 1
3743+
2 1
3744+
3 2
3745+
drop table t1;
3746+
#
3747+
# End of 10.11 tests
3748+
#
37283749
set global innodb_stats_persistent= @innodb_stats_persistent_save;
37293750
set global innodb_stats_persistent_sample_pages=
37303751
@innodb_stats_persistent_sample_pages_save;

sql/opt_range.cc

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9974,8 +9974,6 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
99749974
{
99759975
bool must_be_ored= sel_trees_must_be_ored(param, tree1, tree2, ored_keys);
99769976
no_imerge_from_ranges= must_be_ored;
9977-
if (param->disable_index_merge_plans)
9978-
no_imerge_from_ranges= true;
99799977

99809978
if (no_imerge_from_ranges && no_merges1 && no_merges2)
99819979
{
@@ -10025,6 +10023,13 @@ tree_or(RANGE_OPT_PARAM *param,SEL_TREE *tree1,SEL_TREE *tree2)
1002510023
DBUG_RETURN(result);
1002610024
}
1002710025

10026+
/*
10027+
Ok, the result now has the ranges that one gets for (RT1 OR RT2).
10028+
If construction of SEL_IMERGE is disabled, stop right here.
10029+
*/
10030+
if (param->disable_index_merge_plans)
10031+
DBUG_RETURN(result);
10032+
1002810033
SEL_IMERGE *imerge_from_ranges;
1002910034
if (!(imerge_from_ranges= new SEL_IMERGE()))
1003010035
result= NULL;

0 commit comments

Comments
 (0)