Bug #57372 | Multi-table updates and deletes fail when running with ICP against InnoDB | ||
---|---|---|---|
Submitted: | 11 Oct 2010 13:53 | Modified: | 23 Nov 2010 3:33 |
Reporter: | Olav Sandstå | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
Version: | 5.6.99 | OS: | Any |
Assigned to: | Olav Sandstå | CPU Architecture: | Any |
Tags: | index_condition_pushdown, optimizer_switch |
[11 Oct 2010 13:53]
Olav Sandstå
[12 Oct 2010 8:50]
Olav Sandstå
In the multi-table update query given in the bug report the following condition will be pushed down to InnoDB when executing the "query" part of the statement for retrieving records from table t2: `test`.`t2`.`a` = (`test`.`t1`.`b` - 100) The results from the query part is (in this case) stored into two temporary tables. When the update part of the statement is done the content of these tempory tables are used for updating t1 and t2. The update of t1 is done correctly. But when trying to update t2 InnoDB reports that there are no records to update. The update is done in the function multi_update::do_updates() (in sql_update.cc). This function does the following to position on the first row to be updated: /* call ha_rnd_pos() using rowids from temporary table */ check_opt_it.rewind(); TABLE *tbl= table; uint field_num= 0; do { if((local_error= tbl->file->ha_rnd_pos(tbl->record[0], (uchar *) tmp_table->field[field_num]->ptr))) goto err; field_num++; } while((tbl= check_opt_it++)); In this case the call to tbl->file->ha_rnd_pos() returns an error that there are no records found. The cause for this is that when InnoDB is executing the tbl->file->ha_rnd_pos() call the handler object still contains the pushed index condition and this is evaluated. In this case it evaluates to FALSE and InnoDB skip this record and returns that the record is not found.
[12 Oct 2010 14:08]
Olav Sandstå
Some ideas for alternatives for fixing this: 1. Disable use of ICP if the query is either a multi-table update or delete 2. Disable the pushed condition before starting updating the table 2a: "faking it": push a new index condition function to the storage engine that always evaluates to true. 2b: "proper": extend the handler interface with a new method to inform the storage engine that ICP should no longer being used 3. Create a separate handler object for doing the updates Out of these alternative 1 seems to be the easiest and safest. Alternative 2 is doable but it might not solve all issues. There are cases where the updates to the table can be done "on the fly" without going through a temporary table (see the criteria in the safe_update_on_fly() function in sql_update.cc). Alternativ 3 is the one that likely would require most code changes and require setting up multiple handler objects for the same table.
[13 Oct 2010 7:54]
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/120629 3262 Olav Sandstaa 2010-10-13 Fix for Bug#57372 Multi-table updates and deletes fail when running with ICP against InnoDB For multi-table update and delete statements the same handler object is used for both doing the query part and the update part of the statement. When ICP is used a select condition will be pushed down to the storage engine. If this is accepted by the storage engine it will be used during execution of the query part of the statement but it might also be evaluated during the update part of the statement. This can lead to either not finding the record to update or result in wrong record being updated. Using ICP with InnoDB this has not given any issues this far as InnoDB has not accepted ICP for statements that updates the table. This restriction is about to be removed from InnoDB. After this change using ICP with InnoDB might cause wrong results if we have pushed an index condition for multi-table update and delete statements. This patch solves this issue by not pushing down index conditions to the storage engine when the statement is either a multi-table delete or update statement. @ mysql-test/include/icp_tests.inc Test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp_all.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp_none.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp_all.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp_none.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ sql/sql_select.cc For multi-table delete and update statements the same handler is used for both doing the query part and the update part. If an index condition has been pushed down to the storage engine it will be evaluated during execution of the query part but it might also be executed during the update part. This can lead to wrong result. This patch solves this problem by restricting the server to not push down index conditions if the statement is either a multi-table update or delete statement.
[26 Oct 2010 6:39]
Marko Mäkelä
The patch disables index condition pushdown for multi-table deletes and updates. Looks OK from the InnoDB point of view. What about multi-table replace or other multi-table operations, can ICP be attempted on them?
[28 Oct 2010 8:03]
Olav Sandstå
I have looked at "multi-table" INSERT/REPLACE (note that insert/replace can only update one table) and it seems like this is not an issue for these operations. A statement like: REPLACE/INSERT INTO t1 SELECT ... FROM t1,t2 WHERE ... can use ICP for execution of the SELECT part. The reason this does not cause issues when doing the REPLACE/INSERT part is that the replace/insert is done using a separate handler object instead of doing it using the same handler object as used for the select. For the above statement the server will create three table objects for "t1", "t1", "t2" each with a separate handler object. One of the "t1" table objects will be used for the select part and the other "t1" table object for the replace/insert part. For a multi-table update statement like: UPDATE t1, t2 SET ... WHERE... the server will create only two table objects "t1", "t2" which will be used both for the "select" part and the "update" part (and caused this problem).
[28 Oct 2010 8:09]
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/122180 3270 Olav Sandstaa 2010-10-28 Fix for Bug#57372 Multi-table updates and deletes fail when running with ICP against InnoDB For multi-table update and delete statements the same handler object is used for both doing the query part and the update part of the statement. When ICP is used a select condition will be pushed down to the storage engine. If this is accepted by the storage engine it will be used during execution of the query part of the statement but it might also be evaluated during the update part of the statement. This can lead to either not finding the record to update or result in wrong record being updated. Using ICP with InnoDB this has not given any issues this far as InnoDB has not accepted ICP for statements that updates the table. This restriction is about to be removed from InnoDB. After this change using ICP with InnoDB might cause wrong results if we have pushed an index condition for multi-table update and delete statements. This patch solves this issue by not pushing down index conditions to the storage engine when the statement is either a multi-table delete or update statement. @ mysql-test/include/icp_tests.inc Test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp_all.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/innodb_icp_none.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp_all.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ mysql-test/r/myisam_icp_none.result Result file for test case for Bug#57372 "Multi-table updates and deletes fail when running with ICP gainst InnoDB. @ sql/sql_select.cc For multi-table delete and update statements the same handler is used for both doing the query part and the update part. If an index condition has been pushed down to the storage engine it will be evaluated during execution of the query part but it might also be executed during the update part. This can lead to wrong result. This patch solves this problem by restricting the server to not push down index conditions if the statement is either a multi-table update or delete statement.
[28 Oct 2010 8:16]
Olav Sandstå
Patch pushed to mysql-next-mr-opt-backporting with revision id: olav.sandstaa@oracle.com-20101028080834-ghs007fm0geomvw3
[13 Nov 2010 16:07]
Bugs System
Pushed into mysql-trunk 5.6.99-m5 (revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (version source revid:alexander.nozdrin@oracle.com-20101113155825-czmva9kg4n31anmu) (merge vers: 5.6.99-m5) (pib:21)
[13 Nov 2010 16:37]
Bugs System
Pushed into mysql-next-mr (revid:alexander.nozdrin@oracle.com-20101113160336-atmtmfb3mzm4pz4i) (version source revid:alexander.nozdrin@oracle.com-20101113152540-gxro4g0v29l27f5x) (pib:21)
[23 Nov 2010 3:33]
Paul DuBois
Bug does not appear in any released 5.6.x version. No 5.6.1 changelog entry needed.