• MySQL Build Team's avatar
    Backport into build-200907211706-5.0.82sp1 · f6435cbf
    MySQL Build Team authored
    > ------------------------------------------------------------
    > 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.
    f6435cbf
index_merge.test 17.2 KB