1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Backport into build-200907211706-5.0.82sp1

> ------------------------------------------------------------
> revno: 2772
> revision-id: joro@sun.com-20090615133815-eb007p5793in33p5
> parent: joro@sun.com-20090612140659-4hj1tta9p8wvcw4k
> committer: Georgi Kodinov <joro@sun.com>
> branch nick: B44810-5.0-bugteam
> timestamp: Mon 2009-06-15 16:38:15 +0300
> message:
>   Bug #44810: index merge and order by with low sort_buffer_size
>   crashes server!
>   
>   The problem affects the scenario when index merge is followed by a filesort
>   and the sort buffer is not big enough for all the sort keys.
>   In this case the filesort function will read the data to the end through the 
>   index merge quick access method (and thus closing the cursor etc), 
>   but will leave the pointer to the quick select method in place.
>   It will then create a temporary file to hold the results of the filesort and
>   will add it as a sort output file (in sort.io_cache).
>   Note that filesort will copy the original 'sort' structure in an automatic
>   variable and restore it after it's done.
>   As a result at exiting filesort() we have a sort.io_cache filled in and 
>   nothing else (as a result of close of the cursors at end of reading data 
>   through index merge).
>   Now create_sort_index() will note that there is a select and will clean it up
>   (as it's been used already by filesort() reading the data in). While doing that
>   a special case in the index merge destructor will clean up the sort.io_cache,
>   assuming it's an output of the index merge method and is not needed anymore.
>   As a result the code that tries to read the data back from the filesort output 
>   will get no data in both memory and disk and will crash.
>         
>   Fixed similarly to how filesort() does it : by copying the sort.io_cache structure
>   to a local variable, removing the pointer to the io_cache (so that it's not freed 
>   by QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT) and restoring the original 
>   structure (together with the valid pointer) after the cleanup is done.
>   This is a safe thing to do because all the structures are already cleaned up by
>   hitting the end of the index merge's read method (QUICK_INDEX_MERGE_SELECT::get_next()) 
>   and the cleanup code being written in a way that tolerates repeating cleanups.
This commit is contained in:
MySQL Build Team
2009-07-21 19:59:04 +02:00
parent ae2380452f
commit f6435cbff1
3 changed files with 65 additions and 0 deletions

View File

@ -555,4 +555,28 @@ a
1
2
drop table t0, t1, t2, t3;
#
# BUG#44810: index merge and order by with low sort_buffer_size
# crashes server!
#
CREATE TABLE t1(a VARCHAR(128),b VARCHAR(128),KEY(A),KEY(B));
INSERT INTO t1 VALUES (REPEAT('a',128),REPEAT('b',128));
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
SET SESSION sort_buffer_size=1;
Warnings:
Warning 1292 Truncated incorrect sort_buffer_size value: '1'
EXPLAIN
SELECT * FROM t1 FORCE INDEX(a,b) WHERE a LIKE 'a%' OR b LIKE 'b%'
ORDER BY a,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 131,131 NULL 64 Using sort_union(a,b); Using where; Using filesort
SELECT * FROM t1 FORCE INDEX(a,b) WHERE a LIKE 'a%' OR b LIKE 'b%'
ORDER BY a,b;
SET SESSION sort_buffer_size=DEFAULT;
DROP TABLE t1;
End of 5.0 tests

View File

@ -503,4 +503,30 @@ where exists (select 1 from t2, t3
drop table t0, t1, t2, t3;
--echo #
--echo # BUG#44810: index merge and order by with low sort_buffer_size
--echo # crashes server!
--echo #
CREATE TABLE t1(a VARCHAR(128),b VARCHAR(128),KEY(A),KEY(B));
INSERT INTO t1 VALUES (REPEAT('a',128),REPEAT('b',128));
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT * FROM t1;
SET SESSION sort_buffer_size=1;
EXPLAIN
SELECT * FROM t1 FORCE INDEX(a,b) WHERE a LIKE 'a%' OR b LIKE 'b%'
ORDER BY a,b;
# we don't actually care about the result : we're checking if it crashes
--disable_result_log
SELECT * FROM t1 FORCE INDEX(a,b) WHERE a LIKE 'a%' OR b LIKE 'b%'
ORDER BY a,b;
--enable_result_log
SET SESSION sort_buffer_size=DEFAULT;
DROP TABLE t1;
--echo End of 5.0 tests