Bug #50402 | Optimizer producing wrong results when using Index Merge on InnoDB | ||
---|---|---|---|
Submitted: | 18 Jan 2010 2:41 | Modified: | 2 Nov 2010 14:02 |
Reporter: | Leandro Morgado | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S1 (Critical) |
Version: | 5.1.31sp1, 5.1.41, 5.1.49, 5.5.7 | OS: | Any |
Assigned to: | Sergei Glukhov | CPU Architecture: | Any |
[18 Jan 2010 2:41]
Leandro Morgado
[18 Jan 2010 2:57]
Leandro Morgado
File is too big to attach. Has been uploaded to FTP: http://ftp.mysql.com/pub/mysql/download/bug_data_50402.bz2
[18 Jan 2010 6:31]
Valeriy Kravchuk
Looks like a duplicate of Bug #50389. Please, check.
[18 Jan 2010 6:49]
Leandro Morgado
I agree it's a duplicate of bug #50389 , however, I think that bug has a wrong entry in it's description, namely: "The correct number of rows are returned in the following cases: * storage engine is MyISAM * query includes USE INDEX (PRIMARY) * query is SELECT COUNT(*) instead of SELECT *" --> This last entry is not true as my test case is using COUNT(*) and producing wrong results. So it's just a bug with Intersect index merge and Innodb, seem in both bug reports.
[18 Jan 2010 9:13]
Valeriy Kravchuk
Duplicate of bug #50389.
[18 Jan 2010 20:03]
MySQL Verification Team
Also this bug is in affect with only two indexes used in the index merge rather than 3. It also does not relate to field length, but to the number of comparisons on the primary key it seems. If you compare only one value using IN or equality then it gives a wrong result. However, on two or more using IN or multiple comparisons using AND/OR, it returns a correct result (non-empty).
[23 Jul 2010 17:28]
Leandro Morgado
I don't think this bug is fixed. I still get missing results if the table is InnoDB: mysql [localhost] {msandbox} (test) > ALTER TABLE JOB_ORDER ENGINE=MyISAM; Query OK, 7599 rows affected (0.09 sec) Records: 7599 Duplicates: 0 Warnings: 0 mysql [localhost] {msandbox} (test) > mysql [localhost] {msandbox} (test) > ALTER TABLE REFERRAL ENGINE=MyISAM; Query OK, 181215 rows affected (1.13 sec) Records: 181215 Duplicates: 0 Warnings: 0 mysql [localhost] {msandbox} (test) > SELECT this_.ID FROM job_order this_ WHERE CASE WHEN (SELECT COUNT(*) FROM -> job_order jo INNER JOIN referral ref ON jo.ID = ref.job_order_ID WHERE ref.REF_RESULT = -> 'h' AND jo.ID = this_.id) >= this_.NBR_JOB_OPENINGS THEN 'p' WHEN CURDATE() >= -> this_.DATE_ORDER_OPEN AND CURDATE() < this_.DATE_ORDER_CLOSE THEN 'o' END ='o' AND -> this_.ID = 6786; +------+ | ID | +------+ | 6786 | +------+ 1 row in set (0.00 sec) mysql [localhost] {msandbox} (test) > ALTER TABLE REFERRAL ENGINE=INNODB;Query OK, 181215 rows affected (2.85 sec)Records: 181215 Duplicates: 0 Warnings: 0 mysql [localhost] {msandbox} (test) > ALTER TABLE JOB_ORDER ENGINE=INNODB;Query OK, 7599 rows affected (0.15 sec)Records: 7599 Duplicates: 0 Warnings: 0 mysql [localhost] {msandbox} (test) > SELECT this_.ID FROM job_order this_ WHERE CASE WHEN (SELECT COUNT(*) FROM job_order jo INNER JOIN referral ref ON jo.ID = ref.job_order_ID WHERE ref.REF_RESULT = 'h' AND jo.ID = this_.id) >= this_.NBR_JOB_OPENINGS THEN 'p' WHEN CURDATE() >= this_.DATE_ORDER_OPEN AND CURDATE() < this_.DATE_ORDER_CLOSE THEN 'o' END ='o' AND this_.ID = 6786; Empty set (0.01 sec)
[23 Jul 2010 17:42]
Valeriy Kravchuk
Bug #50389 is fixed only in 5.1.49. What version is used in your sandbox?
[23 Jul 2010 17:51]
Leandro Morgado
Hi Valeriy, I tested precisely on this version: shell> ./my sql test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.49-enterprise-gpl-advanced MySQL Enterprise Server - Advanced Edition (GPL) Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to modify and redistribute it under the GPL v2 license Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql [localhost] {msandbox} (test) > SHOW VARIABLES LIKE "version%"; +-------------------------+--------------------------------------------------+| Variable_name | Value |+-------------------------+--------------------------------------------------+ | version | 5.1.49-enterprise-gpl-advanced | | version_comment | MySQL Enterprise Server - Advanced Edition (GPL) | | version_compile_machine | x86_64 | | version_compile_os | unknown-linux-gnu | +-------------------------+--------------------------------------------------+ 4 rows in set (0.00 sec)
[26 Jul 2010 14:00]
Leandro Morgado
Tested this again on 5.1.49 and the problem remains.
[10 Sep 2010 21:29]
MySQL Verification Team
in 5.1.50, this remains a very serious problem with index_merge: ------ drop table if exists t1; create table t1(a int,b int,key(a),key(b))engine=innodb; insert into t1 values (1,2),(1,2),(1,2),(1,2); select * from t1 force index(a,b) where a=1 and b=2; select * from t1 ignore index(a,b) where a=1 and b=2; ------ Both SELECT should return same results, but the one using index_merge gives empty result!
[13 Sep 2010 11:20]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/118067 3506 Sergey Glukhov 2010-09-13 Bug#50402 Optimizer producing wrong results when using Index Merge on InnoDB Subselect executes twice, at JOIN::optimize stage and at JOIN::execute stage. At optimize stage Innodb prebuilt struct which is used for the retrieval of column values is initialized in. ha_innobase::index_read(), prebuilt->sql_stat_start is true. After QUICK_ROR_INTERSECT_SELECT finished his job it restores read_set/write_set bitmaps with initial values and deactivates one of the handlers used by QUICK_ROR_INTERSECT_SELECT in JOIN::cleanup (it's the case when we reuse original handler as one of handlers required by QUICK_ROR_INTERSECT_SELECT object). On second subselect execution inactive handler is activated in QUICK_RANGE_SELECT::reset, file->ha_index_init(). In ha_index_init Innodb prebuilt struct is reinitialized with inappropriate read_set/write_set bitmaps. Further reinitialization in ha_innobase::index_read() does not happen as prebuilt->sql_stat_start is false. It leads to partial retrieval of required field values and we get a mix of field values from different records in the record buffer. The fix is to reset read_set/write_set bitmaps as these values are required for proper intialization of internal InnoDB struct which is used for the retrieval of column values (see build_template(), ha_innodb.cc) @ mysql-test/include/index_merge_ror_cpk.inc test case @ mysql-test/r/index_merge_innodb.result test result @ mysql-test/r/index_merge_myisam.result test result @ sql/opt_range.cc if ROR merge scan is used we need to reset read_set/write_set bitmaps as these values are required for proper intialization of internal InnoDB struct which is used for the retrieval of column values (see build_template(), ha_innodb.cc)
[16 Sep 2010 12:15]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/118395 3512 Sergey Glukhov 2010-09-16 Bug#50402 Optimizer producing wrong results when using Index Merge on InnoDB Subselect executes twice, at JOIN::optimize stage and at JOIN::execute stage. At optimize stage Innodb prebuilt struct which is used for the retrieval of column values is initialized in. ha_innobase::index_read(), prebuilt->sql_stat_start is true. After QUICK_ROR_INTERSECT_SELECT finished his job it restores read_set/write_set bitmaps with initial values and deactivates one of the handlers used by QUICK_ROR_INTERSECT_SELECT in JOIN::cleanup (it's the case when we reuse original handler as one of handlers required by QUICK_ROR_INTERSECT_SELECT object). On second subselect execution inactive handler is activated in QUICK_RANGE_SELECT::reset, file->ha_index_init(). In ha_index_init Innodb prebuilt struct is reinitialized with inappropriate read_set/write_set bitmaps. Further reinitialization in ha_innobase::index_read() does not happen as prebuilt->sql_stat_start is false. It leads to partial retrieval of required field values and we get a mix of field values from different records in the record buffer. The fix is to reset read_set/write_set bitmaps as these values are required for proper intialization of internal InnoDB struct which is used for the retrieval of column values (see build_template(), ha_innodb.cc) @ mysql-test/include/index_merge_ror_cpk.inc test case @ mysql-test/r/index_merge_innodb.result test case @ mysql-test/r/index_merge_myisam.result test case @ sql/opt_range.cc if ROR merge scan is used we need to reset read_set/write_set bitmaps as these values are required for proper intialization of internal InnoDB struct which is used for the retrieval of column values (see build_template(), ha_innodb.cc)
[27 Sep 2010 7:10]
Giuseppe Maxia
Bug #57019 was marked as duplicate of this one
[28 Sep 2010 15:40]
Bugs System
Pushed into mysql-trunk 5.6.1-m4 (revid:alik@sun.com-20100928153607-tdsxkdm5cmuym5sq) (version source revid:alik@sun.com-20100928153508-0saa6v93dinqx1u7) (merge vers: 5.6.1-m4) (pib:21)
[28 Sep 2010 15:42]
Bugs System
Pushed into mysql-next-mr (revid:alik@sun.com-20100928153646-pqp8o1a92mxtuj3h) (version source revid:alik@sun.com-20100928153532-lr3gtvnyp2en4y75) (pib:21)
[28 Sep 2010 15:45]
Bugs System
Pushed into mysql-5.5 5.5.7-rc (revid:alik@sun.com-20100928153459-4nudf4zgzlou4s7q) (version source revid:alik@sun.com-20100928153459-4nudf4zgzlou4s7q) (merge vers: 5.5.7-rc) (pib:21)
[30 Sep 2010 20:14]
Paul DuBois
Noted in 5.5.7, 5.6.1 changelogs. For some queries, the optimizer produced incorrect results using the Index Merge access method with InnoDB tables. Setting report to Need Merge pending push to 5.1.x.
[3 Oct 2010 1:33]
Paul DuBois
Setting report to Need Merge pending push to 5.1.x.
[7 Oct 2010 23:02]
Paul DuBois
Noted in 5.1.52 changelog.
[13 Oct 2010 16:44]
Valeriy Kravchuk
Bug #57434 was marked as a duplicate of this one.
[1 Nov 2010 19:01]
Bugs System
Pushed into mysql-5.1 5.1.53 (revid:build@mysql.com-20101101184443-o2olipi8vkaxzsqk) (version source revid:build@mysql.com-20101101184443-o2olipi8vkaxzsqk) (merge vers: 5.1.53) (pib:21)
[2 Nov 2010 14:57]
Leandro Morgado
See comment from 16 Sep 15:46 the problem described by Shane is fixed in Bug#56423, the fix is in 5.1.53 tree. Marking as a dupe of Bug #56423 .