Bug #27870 | join and subselect crash server | ||
---|---|---|---|
Submitted: | 17 Apr 2007 3:44 | Modified: | 24 Apr 2007 1:05 |
Reporter: | Adam Dixon | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S1 (Critical) |
Version: | 5.0.40, 5.1.18 | OS: | Any |
Assigned to: | Igor Babaev | CPU Architecture: | Any |
Tags: | bfsm_2007_04_19, crash, join, regression, Signal 11, subselect |
[17 Apr 2007 3:44]
Adam Dixon
[17 Apr 2007 7:02]
MySQL Verification Team
Verified, here's a stack trace: mysqld-nt.exe!Item_in_optimizer::val_int() mysqld-nt.exe!Item::val_bool() mysqld-nt.exe!Item_func_not::val_int() mysqld-nt.exe!evaluate_join_record() mysqld-nt.exe!sub_select() mysqld-nt.exe!do_select() mysqld-nt.exe!JOIN::exec() mysqld-nt.exe!mysql_select() mysqld-nt.exe!handle_select() mysqld-nt.exe!mysql_execute_command() mysqld-nt.exe!mysql_parse() mysqld-nt.exe!dispatch_command() mysqld-nt.exe!do_command() mysqld-nt.exe!handle_one_connection() mysqld-nt.exe!_pthread_start() mysqld-nt.exe!_threadstart() kernel32.dll!FlsSetValue()
[17 Apr 2007 7:05]
MySQL Verification Team
This is a regression! 5.0.27 and 5.0.24a don't crash.
[17 Apr 2007 7:38]
MySQL Verification Team
testcase: drop table if exists `t1`; drop table if exists `t2`; create table `t1` (`a` int); create table `t2` (`b` int,primary key(`b`)); insert into `t1` values (),(); insert into `t2` values (1),(2); select 1 from `t1`, `t2` where `a`=`b` and (`b` not in (select 1 from `t1`));
[17 Apr 2007 7:46]
Valeriy Kravchuk
Same stack trace on Linux: openxs@suse:~/dbs/5.0> bin/resolve_stack_dump -s /tmp/mysqld5.sym 27870.stack 0x81bbd46 handle_segfault + 646 0x8154a53 _ZN17Item_in_optimizer7val_intEv + 339 0x811eb09 _ZN4Item8val_boolEv + 121 0x8153f55 _ZN13Item_func_not7val_intEv + 21 0x8213372 _Z20evaluate_join_recordP4JOINP13st_join_tableiPc + 114 0x8213662 _Z10sub_selectP4JOINP13st_join_tableb + 354 0x821a5c1 _Z9do_selectP4JOINP4ListI4ItemEP8st_tableP9Procedure + 353 0x822c4e8 _ZN4JOIN4execEv + 4536 0x8228cc8 _Z12mysql_selectP3THDPPP4ItemP13st_table_listjR4ListIS1_ES2_jP8st_orde rSB_S2_SB_yP13select_resultP18st_select_lex_unitP13st_sel + 184 0x822d497 _Z13handle_selectP3THDP6st_lexP13select_resultm + 359 0x81d7b73 _Z21mysql_execute_commandP3THD + 16451 0x81dd5c1 _Z11mysql_parseP3THDPcj + 369 0x81df4ee _Z16dispatch_command19enum_server_commandP3THDPcj + 2366 0x81e0f0f handle_one_connection + 1919 0x40050aa7 _end + 932670611 0x40247c2e _end + 934731290
[17 Apr 2007 9:12]
Sergey Petrunya
The problem is caused by interplay between NULL-IN-SELECT() query handling and equality propagation. The query is: SELECT distinct t1.uid FROM t1, t2 WHERE t2.id = t1.typeid and (t2.id not in (select parentid from t2 where id = 101)); NULL-IN-SELECT rewrite code sees subquery's left_expr t2.id is may not be NULL and does not make any provisions for execution of NULL IN (SELECT ...). Then join order of (t1, t2) gets choosen. Equality propagation uses "t2.id = t1.typeid" to change t2.id NOT IN ... into t1.typeid NOT IN ... This allows to attach the subquery predicate to table t1. t1.typeid maybe NULL, and we get a crash when we try to evaluate the NULL IN (SELECT ...)
[17 Apr 2007 11:38]
Sergey Petrunya
Fix suggestion 1 ================ Equality propagation guarantees that the partial row combination we're considering won't be in the query output. Therefore, we can just return arbitrary value (e.g. NULL) as the value of subquery predicate. Fix suggestion 2 ================ Create an IS NOT NULL predicate and attach it to the appropriate table. That is, suppose we have Item_equal(t1.col1, t2.col2, ..., tN.colN). Let's order them by the join order (suppose it's t1,t2,...) t1.col1 t2.col2 ... The check "t1.col1=t2.col2" is performed as soon as we get records for t1 and t2. However, if we got t1.col1==NULL, we can discard t1 row immediately. This can be achieved by injecting the appropriate IS NOT NULL predicate. The rule will be: for each Item_equal // there is a list of them somewhere { In the list of equal fields, find tableX.columnY with minimal tableX.position_in_join_order; tableX.join_tab.cond "tableX.columnY IS NOT NULL" AND tableX.join_tab.cond; } In addition to this rule we will also need to make this fix in the equal field substitution: - when calculating condition of table X, do not substitute X.col with some_preceding_table.col .
[18 Apr 2007 0:34]
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/24734 ChangeSet@1.2456, 2007-04-17 17:35:29-07:00, igor@olga.mysql.com +3 -0 Fixed bug #27870. The bug that causes crashes manifests itself at some conditions when executing an equijoin query with WHERE condition containing a subquery predicate of the form join_attr NOT IN (SELECT ...). To resolve a problem of the correct evaluation of the expression attr NOT IN (SELECT ...) an array of guards is created to make it possible to filter out some predicates of the EXISTS subquery into which the original subquery predicate is transformed, in the cases when a takes the NULL value. If attr is defined as a field that cannot be NULL than such an array is not needed and is not created. However if the field a occurred also an an equijoin predicate t2.a=t1.b and table t1 is accessed before table t2 then it may happen that the the EXISTS subquery is pushed down to the condition evaluated just after table t1 has been accessed. In this case any occurrence of t2.a is substituted for t1.b. When t1.b takes the value of NULL an attempt is made to turn on the corresponding guard. This action caused a crash as no guard array had been created. Now the code of Item_in_subselect::set_cond_guard_var checks that the guard array has been created before setting a guard variable on. Otherwise the method does nothing. It cannot results in returning a row that could be rejected as the condition t2.a=t1.b will be checked later anyway.
[18 Apr 2007 23:47]
Sergey Petrunya
The fix for this bug is an implementation of Fix suggestion #1. Fix Suggestion #2 aims for slightly better performance but actually it is trying to fix two problems at once - the 1st is the described crash, the second is the absense of NULL filtering. Solving one problem doesn't solve the other, so the second problem will be adressed separately as BUG#27939.
[19 Apr 2007 20:56]
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/24953 ChangeSet@1.2464, 2007-04-19 22:56:04+02:00, kent@mysql.com +2 -0 mysql.sln: Enable 'mysys' build if target 'Enterprise' item_subselect.h: Fixed bug #27870. The bug that causes crashes manifests itself at some conditions when executing an equijoin query with WHERE condition containing a subquery predicate of the form join_attr NOT IN (SELECT ...).
[19 Apr 2007 20:57]
Mads Martin Joergensen
This have gone into 5.0.40 release clone. When documented in 5.0.40 changelog, please set it back to Patch Queued.
[21 Apr 2007 15:19]
Bugs System
Pushed into 5.1.18-beta
[21 Apr 2007 15:20]
Bugs System
Pushed into 5.0.42
[24 Apr 2007 1:05]
Paul DuBois
Noted in 5.0.42, 5.1.18 changelogs. Some equi-joins containing a WHERE clause that included a NOT IN subquery caused a server crash.
[27 Apr 2007 9:21]
Bugs System
Pushed into 5.1.18-beta
[27 Apr 2007 9:24]
Bugs System
Pushed into 5.0.42
[1 May 2007 12:50]
Paul DuBois
Moved the 5.0.x changelog entry from 5.0.42 to 5.0.40.