Bug#17405466: USE_COUNT: WRONG COUNT FOR KEY AT 0X27547278,
3 SHOULD BE 4
Consider an index (kp1, kp2, kp3), and a WHERE clause involving
all three keyparts ('kpx_pred' represents a predicate usable by
the range access method on keypart 'x'):
"WHERE (kp2_pred OR kp2_pred) AND kp3_pred AND (kp1_pred OR kp1_pred)"
The range optimizer first creates a SEL_ARG tree for kp2 with
two SEL_ARGs, then another SEL_ARG tree for kp3. Both SEL_ARGs
for kp2 will point to this kp3-SEL_ARG via the next_key_part
pointer. The use_count of the root of the SEL_ARG tree for
kp2 is now 1 (it is pointed to by SEL_TREE::keys[]), and
the use_count of the root of the SEL_ARG tree for kp3 is 2
(next_key_part pointers from both kp2 SEL_ARGs).
Now the range optimizer creates a SEL_ARG tree with two
SEL_ARGs for kp1. Both these need to point to the SEL_ARG tree
for kp2 via the next_key_part pointer. This should increase the
use_count of the kp2 SEL_ARG tree by 1 (+2 next_key_part
pointers for the kp1 SEL_ARG tree, -1 since SEL_TREE::keys[]
now points to the kp1 SEL_ARG tree and not directly to the
kp2 SEL_ARG tree).
This increase in use_count also needs to be propagated to the
kp3 SEL_ARG tree, and this is where the bug was: instead of
increasing the use count for each next_key_part pointing to
the kp3 SEL_ARG tree, only the next_key_part of the root of
kp2 SEL_ARG tree was increased. The fix is to propagate the
increase to all SEL_ARG trees pointed to by all SEL_ARGs.
Debugging this without printing the full SEL_ARG range trees
would have been very hard. The patch therefore also adds a
parameter to print_tree() so that a full printout is done when
printing to the debug trace but not when printing to optimizer
trace.
Reverting the following commit makes the crash go away.
commit 951d0e82aa562f0 5c4b7859a2906ae e7bc2e8639
Author: Jorgen Loland <email address hidden>
Date: Thu Oct 10 13:55:38 2013 +0200
Bug#17405466: USE_COUNT: WRONG COUNT FOR KEY AT 0X27547278,
3 SHOULD BE 4
Consider an index (kp1, kp2, kp3), and a WHERE clause involving
all three keyparts ('kpx_pred' represents a predicate usable by
the range access method on keypart 'x'):
"WHERE (kp2_pred OR kp2_pred) AND
kp3_ pred AND
(kp1_ pred OR kp1_pred)"
The range optimizer first creates a SEL_ARG tree for kp2 with
two SEL_ARGs, then another SEL_ARG tree for kp3. Both SEL_ARGs
for kp2 will point to this kp3-SEL_ARG via the next_key_part
pointer. The use_count of the root of the SEL_ARG tree for
kp2 is now 1 (it is pointed to by SEL_TREE::keys[]), and
the use_count of the root of the SEL_ARG tree for kp3 is 2
(next_key_part pointers from both kp2 SEL_ARGs).
Now the range optimizer creates a SEL_ARG tree with two
SEL_ARGs for kp1. Both these need to point to the SEL_ARG tree
for kp2 via the next_key_part pointer. This should increase the
use_count of the kp2 SEL_ARG tree by 1 (+2 next_key_part
pointers for the kp1 SEL_ARG tree, -1 since SEL_TREE::keys[]
now points to the kp1 SEL_ARG tree and not directly to the
kp2 SEL_ARG tree).
This increase in use_count also needs to be propagated to the
kp3 SEL_ARG tree, and this is where the bug was: instead of
increasing the use count for each next_key_part pointing to
the kp3 SEL_ARG tree, only the next_key_part of the root of
kp2 SEL_ARG tree was increased. The fix is to propagate the
increase to all SEL_ARG trees pointed to by all SEL_ARGs.
Debugging this without printing the full SEL_ARG range trees
would have been very hard. The patch therefore also adds a
parameter to print_tree() so that a full printout is done when
printing to the debug trace but not when printing to optimizer
trace.