Bug #38687 | AND optimization done without regard to memory consumption | ||
---|---|---|---|
Submitted: | 9 Aug 2008 1:05 | Modified: | 14 Aug 2008 20:58 |
Reporter: | Mark Callaghan | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
Version: | 5.0 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | and, Optimizer, query |
[9 Aug 2008 1:05]
Mark Callaghan
[9 Aug 2008 1:08]
Mark Callaghan
Making matters worse, it looks like this code only partially handles OOM errors as all callers of SEL_ARG::clone do not check that the return is NULL. Is it OK not to check or will that lead to a segfault later? SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) { SEL_ARG *tmp; if (type != KEY_RANGE) { if (!(tmp= new SEL_ARG(type))) return 0; // out of memory tmp->prev= *next_arg; // Link into next/prev chain (*next_arg)->next=tmp; (*next_arg)= tmp; } else { if (!(tmp= new SEL_ARG(field,part, min_value,max_value, min_flag, max_flag, maybe_flag))) return 0; // OOM tmp->parent=new_parent; tmp->next_key_part=next_key_part; if (left != &null_element) tmp->left=left->clone(tmp,next_arg); <-- does not check for OOM tmp->prev= *next_arg; // Link into next/prev chain (*next_arg)->next=tmp; (*next_arg)= tmp; if (right != &null_element) if (!(tmp->right= right->clone(tmp,next_arg))) return 0; // OOM } increment_use_count(1); tmp->color= color; tmp->elements= this->elements; return tmp; }
[9 Aug 2008 1:15]
Mark Callaghan
When alloc_root fails because I hardwired it to fail if a heap used more than 1GB, the server dies here. void sql_alloc_error_handler(void) { THD *thd=current_thd; if (thd) // QQ; To be removed thd->fatal_error(); /* purecov: inspected */ sql_print_error(ER(ER_OUT_OF_RESOURCES)); } }
[9 Aug 2008 1:20]
Mark Callaghan
SEL_ARG::clone_tree() might be a good place to check for excessive memory usage and return NULL. Where else might the problem occur?
[9 Aug 2008 2:00]
Mark Callaghan
When I hardwire my_alloc.c to fail (return NULL) when a given heap uses more than X MB of memory, the overloaded new operators that use sql_alloc cause the program to terminate. If the overloaded new operators used 'throw()' then they would return NULL. I doubt that is a better thing to do given the numerous uses of new in mysql source where the caller does not check for NULL on return. My fix is: 1) SEL_ARG::clone_tree checks for too many bytes allocated from the MEM_ROOT for the THD and fails if that is the case. 2) MEM_ROOT counts the number of bytes allocated per heap and fails when limit has been exceeded. The limit for 1) should be less than the limit for 2) to avoid a crash because there is a crash when 2) occurs.
[9 Aug 2008 2:38]
Marc ALFF
Please see related bug#38296 While 38296 is about the parser, this bug is about the optimizer. Both have the same root cause: robustness of the code in case of OOM.
[9 Aug 2008 17:18]
Sveta Smirnova
Probably related to bug #38006 also.
[13 Aug 2008 19:18]
Mark Callaghan
This may have been fixed in MySQL 5.1 with the addition of MAX_SEL_ARGS to opt_range.cc
[13 Aug 2008 23:34]
Mark Callaghan
And this also appears to be fixed in recent 5.0 versions. Alas, I still use 5.0.37 with a lot of backports.
[14 Aug 2008 20:58]
Gary Pendergast
This bug is a duplicate of Bug #26624.