From e38e30d0f6c78d17e8e191ee7a824bdafd997b17 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 25 Mar 2010 15:18:14 +0400 Subject: [PATCH 1/3] BUG#47598 - MyISAM may write uninitialized data to disk When MyISAM writes newly created index page it may be initialized partially. In other words some bytes of sensible data and uninitialized tail of the page may go into index file. Under certain rare circumstances these hunks of memory may contain data that would be otherwise inaccessible to user, like passwords or data from other tables. Fixed by initializing memory for temporary MyISAM key buffer to '\0'. No test case for this fix as it is heavily covered by existing tests. --- storage/myisam/mi_open.c | 3 +++ storage/myisam/mi_page.c | 7 ------- storage/myisam/mi_write.c | 2 +- storage/myisam/rt_index.c | 10 +--------- storage/myisam/rt_split.c | 11 ++--------- 5 files changed, 7 insertions(+), 26 deletions(-) diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index e18146f2357..f2f390862bd 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -652,6 +652,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) myisam_open_list=list_add(myisam_open_list,&m_info->open_list); pthread_mutex_unlock(&THR_LOCK_myisam); + + bzero(info.buff, share->base.max_key_block_length * 2); + if (myisam_log_file >= 0) { intern_filename(name_buff,share->index_file_name); diff --git a/storage/myisam/mi_page.c b/storage/myisam/mi_page.c index 23a2526f756..76fac8688a7 100644 --- a/storage/myisam/mi_page.c +++ b/storage/myisam/mi_page.c @@ -86,13 +86,6 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo, if ((length=keyinfo->block_length) > IO_SIZE*2 && info->state->key_file_length != page+length) length= ((mi_getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1)); -#ifdef HAVE_purify - { - length=mi_getint(buff); - bzero((uchar*) buff+length,keyinfo->block_length-length); - length=keyinfo->block_length; - } -#endif DBUG_RETURN((key_cache_write(info->s->key_cache, info->s->kfile,page, level, (uchar*) buff,length, (uint) keyinfo->block_length, diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c index 624c31e57ff..72a4e006cc6 100644 --- a/storage/myisam/mi_write.c +++ b/storage/myisam/mi_write.c @@ -825,7 +825,7 @@ static int _mi_balance_page(register MI_INFO *info, MI_KEYDEF *keyinfo, (size_t) (length=new_left_length - left_length - k_length)); pos=buff+2+length; memcpy((uchar*) father_key_pos,(uchar*) pos,(size_t) k_length); - bmove((uchar*) buff+2,(uchar*) pos+k_length,new_right_length); + bmove((uchar*) buff + 2, (uchar*) pos + k_length, new_right_length - 2); } else { /* Move keys -> buff */ diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c index 31241a83228..410badd3145 100644 --- a/storage/myisam/rt_index.c +++ b/storage/myisam/rt_index.c @@ -641,18 +641,12 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, } case 1: /* root was split, grow a new root */ { - uchar *new_root_buf; + uchar *new_root_buf= info->buff + info->s->base.max_key_block_length; my_off_t new_root; uchar *new_key; uint nod_flag = info->s->base.key_reflength; DBUG_PRINT("rtree", ("root was split, grow a new root")); - if (!(new_root_buf = (uchar*)my_alloca((uint)keyinfo->block_length + - MI_MAX_KEY_BUFF))) - { - my_errno = HA_ERR_OUT_OF_MEM; - DBUG_RETURN(-1); /* purecov: inspected */ - } mi_putint(new_root_buf, 2, nod_flag); if ((new_root = _mi_new(info, keyinfo, DFLT_INIT_HITS)) == @@ -680,10 +674,8 @@ static int rtree_insert_level(MI_INFO *info, uint keynr, uchar *key, DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u", (ulong) new_root, 0, mi_test_if_nod(new_root_buf))); - my_afree((uchar*)new_root_buf); break; err1: - my_afree((uchar*)new_root_buf); DBUG_RETURN(-1); /* purecov: inspected */ } default: diff --git a/storage/myisam/rt_split.c b/storage/myisam/rt_split.c index ef988dbd048..88cf643faf9 100644 --- a/storage/myisam/rt_split.c +++ b/storage/myisam/rt_split.c @@ -258,7 +258,7 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, double *old_coord; int n_dim; uchar *source_cur, *cur1, *cur2; - uchar *new_page; + uchar *new_page= info->buff; int err_code= 0; uint nod_flag= mi_test_if_nod(page); uint full_length= key_length + (nod_flag ? nod_flag : @@ -304,12 +304,7 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, goto split_err; } - if (!(new_page = (uchar*)my_alloca((uint)keyinfo->block_length))) - { - err_code= -1; - goto split_err; - } - + info->buff_used= 1; stop = task + (max_keys + 1); cur1 = rt_PAGE_FIRST_KEY(page, nod_flag); cur2 = rt_PAGE_FIRST_KEY(new_page, nod_flag); @@ -345,8 +340,6 @@ int rtree_split_page(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, DFLT_INIT_HITS, new_page); DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs)); - my_afree((uchar*)new_page); - split_err: my_afree((uchar*) coord_buf); DBUG_RETURN(err_code); From ba33a3357dc347091f12ab212aadefb93a2f86b3 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 25 Mar 2010 15:49:01 +0400 Subject: [PATCH 2/3] BUG#51877 - HANDLER interface causes invalid memory read Invalid memory read if HANDLER ... READ NEXT is executed after failed (e.g. empty table) HANDLER ... READ FIRST. The problem was that we attempted to perform READ NEXT, whereas there is no pivot available from failed READ FIRST. With this fix READ NEXT after failed READ FIRST equals to READ FIRST. This bug affects MyISAM tables only. --- mysql-test/r/gis-rtree.result | 7 +++++++ mysql-test/r/handler_myisam.result | 13 +++++++++++++ mysql-test/t/gis-rtree.test | 15 ++++++++------- mysql-test/t/handler_myisam.test | 11 +++++++++++ storage/myisam/mi_rnext.c | 17 ++++++++++++++++- 5 files changed, 55 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index 58c603673df..eb9c350f589 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -1540,5 +1540,12 @@ a HANDLER t1 READ a LAST; a HANDLER t1 CLOSE; +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +a +INSERT INTO t1 VALUES (GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))')); +# should not crash +HANDLER t1 READ a NEXT; +HANDLER t1 CLOSE; DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index 90a1bdfe6be..a970e20a2c0 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -756,4 +756,17 @@ TRUNCATE t1; HANDLER t1 READ FIRST; ERROR 42S02: Unknown table 't1' in HANDLER DROP TABLE t1; +# +# BUG#51877 - HANDLER interface causes invalid memory read +# +CREATE TABLE t1(a INT, KEY(a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +a +INSERT INTO t1 VALUES(1); +HANDLER t1 READ a NEXT; +a +1 +HANDLER t1 CLOSE; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index c5d5bfee861..b006096528e 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -914,14 +914,15 @@ HANDLER t1 READ a PREV; HANDLER t1 READ a LAST; HANDLER t1 CLOSE; -#TODO: re-enable this test please when bug #51877 is solved # second crash fixed when the tree has changed since the last search. -#HANDLER t1 OPEN; -#HANDLER t1 READ a FIRST; -#INSERT INTO t1 VALUES (GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))')); -#HANDLER t1 READ a NEXT; -#HANDLER t1 CLOSE; -#TODO: end of the 51877 dependent section +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +INSERT INTO t1 VALUES (GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))')); +--echo # should not crash +--disable_result_log +HANDLER t1 READ a NEXT; +--enable_result_log +HANDLER t1 CLOSE; DROP TABLE t1; diff --git a/mysql-test/t/handler_myisam.test b/mysql-test/t/handler_myisam.test index da02a90af0f..868ba14480a 100644 --- a/mysql-test/t/handler_myisam.test +++ b/mysql-test/t/handler_myisam.test @@ -37,4 +37,15 @@ TRUNCATE t1; HANDLER t1 READ FIRST; DROP TABLE t1; +--echo # +--echo # BUG#51877 - HANDLER interface causes invalid memory read +--echo # +CREATE TABLE t1(a INT, KEY(a)); +HANDLER t1 OPEN; +HANDLER t1 READ a FIRST; +INSERT INTO t1 VALUES(1); +HANDLER t1 READ a NEXT; +HANDLER t1 CLOSE; +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c index 7ce66d41e0f..b9bbda3cacb 100644 --- a/storage/myisam/mi_rnext.c +++ b/storage/myisam/mi_rnext.c @@ -28,6 +28,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) { int error,changed; uint flag; + uint update_mask= HA_STATE_NEXT_FOUND; DBUG_ENTER("mi_rnext"); if ((inx = _mi_check_index(info,inx)) < 0) @@ -55,6 +56,20 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) info->s->state.key_root[inx]); break; } + /* + "search first" failed. This means we have no pivot for + "search next", or in other words MI_INFO::lastkey is + likely uninitialized. + + Normally SQL layer would never request "search next" if + "search first" failed. But HANDLER may do anything. + + As mi_rnext() without preceeding mi_rkey()/mi_rfirst() + equals to mi_rfirst(), we must restore original state + as if failing mi_rfirst() was not called. + */ + if (error) + update_mask|= HA_STATE_PREV_FOUND; } else { @@ -100,7 +115,7 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx) } /* Don't clear if database-changed */ info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - info->update|= HA_STATE_NEXT_FOUND; + info->update|= update_mask; if (error) { From 3f641968fc91950bf974a8dbfe0cd6d913cab75a Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 25 Mar 2010 16:08:21 +0400 Subject: [PATCH 3/3] BUG#51866 - crash with repair by sort and fulltext keys Repairing MyISAM table with fulltext indexes and low myisam_sort_buffer_size may crash the server. Estimation of number of index entries was done incorrectly, causing further assertion failure or server crash. Docs note: min value for myisam_sort_buffer_size has been changed from 4 to 4096. --- mysql-test/r/fulltext.result | 13 +++++++ mysql-test/r/myisam.result | 4 ++ mysql-test/r/variables.result | 2 + .../r/myisam_sort_buffer_size_basic_32.result | 38 ++++++++++++------- mysql-test/t/fulltext.test | 9 +++++ sql/mysqld.cc | 2 +- storage/myisam/mi_check.c | 9 ++--- storage/myisam/sort.c | 26 ++++++------- 8 files changed, 70 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 9c69f7fd88e..806675edc5a 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -631,4 +631,17 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); 1 DROP TABLE t1; +# +# BUG#51866 - crash with repair by sort and fulltext keys +# +CREATE TABLE t1(a CHAR(4), FULLTEXT(a)); +INSERT INTO t1 VALUES('aaaa'); +SET myisam_sort_buffer_size=4; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index ba417d54998..508523fda21 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2313,6 +2313,8 @@ INSERT INTO t1 SELECT a+1280,b FROM t1; INSERT INTO t1 SELECT a+2560,b FROM t1; INSERT INTO t1 SELECT a+5120,b FROM t1; SET myisam_sort_buffer_size=4; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' REPAIR TABLE t1; Table Op Msg_type Msg_text test.t1 repair error myisam_sort_buffer_size is too small @@ -2363,6 +2365,8 @@ CREATE TABLE t1(a CHAR(255), KEY(a)); SELECT * FROM t1, t1 AS a1; a a SET myisam_sort_buffer_size=4; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' INSERT INTO t1 VALUES ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), ('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'),('0'), diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 7f45046fab5..ff6d4cf85d9 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -523,6 +523,8 @@ select @@max_user_connections; 100 set global max_write_lock_count=100; set myisam_sort_buffer_size=100; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100' set global net_buffer_length=100; Warnings: Warning 1292 Truncated incorrect net_buffer_length value: '100' diff --git a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_32.result b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_32.result index 2657d599df7..cdc73b99316 100644 --- a/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_32.result +++ b/mysql-test/suite/sys_vars/r/myisam_sort_buffer_size_basic_32.result @@ -8,11 +8,15 @@ SELECT @start_session_value; 8388608 '#--------------------FN_DYNVARS_005_01-------------------------#' SET @@global.myisam_sort_buffer_size = 100; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100' SET @@global.myisam_sort_buffer_size = DEFAULT; SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size 8388608 SET @@session.myisam_sort_buffer_size = 200; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '200' SET @@session.myisam_sort_buffer_size = DEFAULT; SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size @@ -28,9 +32,11 @@ SELECT @@session.myisam_sort_buffer_size = 8388608; 1 '#--------------------FN_DYNVARS_005_03-------------------------#' SET @@global.myisam_sort_buffer_size = 4; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -4 +4096 SET @@global.myisam_sort_buffer_size = 4294967295; SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size @@ -41,9 +47,11 @@ SELECT @@global.myisam_sort_buffer_size ; 655354 '#--------------------FN_DYNVARS_005_04-------------------------#' SET @@session.myisam_sort_buffer_size = 4; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '4' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 SET @@session.myisam_sort_buffer_size = 4294967295; SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size @@ -58,13 +66,13 @@ Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -4 +4096 SET @@global.myisam_sort_buffer_size = -1024; Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-1024' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -4 +4096 SET @@global.myisam_sort_buffer_size = 429496729533; Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '429496729533' @@ -101,28 +109,28 @@ Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 SET @@session.myisam_sort_buffer_size = -2; Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '-2' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 SET @@session.myisam_sort_buffer_size = 65530.34.; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.' at line 1 SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 SET @@session.myisam_sort_buffer_size = test; ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 SET @@session.myisam_sort_buffer_size = "test"; ERROR 42000: Incorrect argument type to variable 'myisam_sort_buffer_size' SELECT @@session.myisam_sort_buffer_size ; @@session.myisam_sort_buffer_size -4 +4096 '#------------------FN_DYNVARS_005_06-----------------------#' SELECT @@global.myisam_sort_buffer_size = VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES @@ -141,20 +149,24 @@ Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -4 +4096 SET @@global.myisam_sort_buffer_size = FALSE; Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '0' SELECT @@global.myisam_sort_buffer_size ; @@global.myisam_sort_buffer_size -4 +4096 '#---------------------FN_DYNVARS_001_09----------------------#' SET @@global.myisam_sort_buffer_size = 10; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '10' SELECT @@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size ; @@myisam_sort_buffer_size = @@global.myisam_sort_buffer_size -0 +1 '#---------------------FN_DYNVARS_001_10----------------------#' SET @@myisam_sort_buffer_size = 100; +Warnings: +Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '100' SELECT @@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size ; @@myisam_sort_buffer_size = @@local.myisam_sort_buffer_size 1 @@ -167,7 +179,7 @@ Warnings: Warning 1292 Truncated incorrect myisam_sort_buffer_size value: '1' SELECT @@myisam_sort_buffer_size ; @@myisam_sort_buffer_size -4 +4096 SELECT local.myisam_sort_buffer_size ; ERROR 42S02: Unknown table 'local' in field list SELECT session.myisam_sort_buffer_size ; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index afaabb781b8..ec64728a8c9 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -575,5 +575,14 @@ CREATE TABLE t1(a CHAR(1),FULLTEXT(a)); SELECT 1 FROM t1 WHERE MATCH(a) AGAINST ('') AND ROW(a,a) > ROW(1,1); DROP TABLE t1; +--echo # +--echo # BUG#51866 - crash with repair by sort and fulltext keys +--echo # +CREATE TABLE t1(a CHAR(4), FULLTEXT(a)); +INSERT INTO t1 VALUES('aaaa'); +SET myisam_sort_buffer_size=4; +REPAIR TABLE t1; +SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; +DROP TABLE t1; --echo End of 5.1 tests diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f658a7c8c3c..bb685ba42e3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6858,7 +6858,7 @@ The minimum value for this variable is 4096.", "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", (uchar**) &global_system_variables.myisam_sort_buff_size, (uchar**) &max_system_variables.myisam_sort_buff_size, 0, - GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, + GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, ~0L, 0, 1, 0}, {"myisam_use_mmap", OPT_MYISAM_USE_MMAP, "Use memory mapping for reading and writing MyISAM tables.", (uchar**) &opt_myisam_use_mmap, diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index c10cfdd0c9b..8e3864d1c44 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2396,10 +2396,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, /* fulltext indexes may have much more entries than the number of rows in the table. We estimate the number here. - - Note, built-in parser is always nr. 0 - see ftparser_call_initializer() */ - if (sort_param.keyinfo->ftkey_nr == 0) + if (sort_param.keyinfo->parser == &ft_default_parser) { /* for built-in parser the number of generated index entries @@ -2416,8 +2414,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, so, we'll use all the sort memory and start from ~10 buffpeks. (see _create_index_by_sort) */ - sort_info.max_records= - 10*param->sort_buffer_length/sort_param.key_length; + sort_info.max_records= 10 * + max(param->sort_buffer_length, MIN_SORT_BUFFER) / + sort_param.key_length; } sort_param.key_read=sort_ft_key_read; diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c index b450d27de66..0333898092f 100644 --- a/storage/myisam/sort.c +++ b/storage/myisam/sort.c @@ -28,13 +28,11 @@ /* static variables */ -#undef MIN_SORT_MEMORY #undef MYF_RW #undef DISK_BUFFER_SIZE #define MERGEBUFF 15 #define MERGEBUFF2 31 -#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD) #define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL) #define DISK_BUFFER_SIZE (IO_SIZE*16) @@ -131,12 +129,12 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, sort_keys= (uchar **) NULL; error= 1; maxbuffer=1; - memavl=max(sortbuff_size,MIN_SORT_MEMORY); + memavl= max(sortbuff_size, MIN_SORT_BUFFER); records= info->sort_info->max_records; sort_length= info->key_length; LINT_INIT(keys); - while (memavl >= MIN_SORT_MEMORY) + while (memavl >= MIN_SORT_BUFFER) { if ((records < UINT_MAX32) && ((my_off_t) (records + 1) * @@ -171,10 +169,10 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, break; } old_memavl=memavl; - if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY) - memavl=MIN_SORT_MEMORY; + if ((memavl= memavl/4*3) < MIN_SORT_BUFFER && old_memavl > MIN_SORT_BUFFER) + memavl= MIN_SORT_BUFFER; } - if (memavl < MIN_SORT_MEMORY) + if (memavl < MIN_SORT_BUFFER) { mi_check_print_error(info->sort_info->param,"MyISAM sort buffer too small"); /* purecov: tested */ goto err; /* purecov: tested */ @@ -348,12 +346,12 @@ pthread_handler_t thr_find_all_keys(void *arg) bzero((char*) &sort_param->unique, sizeof(sort_param->unique)); sort_keys= (uchar **) NULL; - memavl= max(sort_param->sortbuff_size, MIN_SORT_MEMORY); + memavl= max(sort_param->sortbuff_size, MIN_SORT_BUFFER); idx= (uint)sort_param->sort_info->max_records; sort_length= sort_param->key_length; maxbuffer= 1; - while (memavl >= MIN_SORT_MEMORY) + while (memavl >= MIN_SORT_BUFFER) { if ((my_off_t) (idx+1)*(sort_length+sizeof(char*)) <= (my_off_t) memavl) @@ -391,11 +389,11 @@ pthread_handler_t thr_find_all_keys(void *arg) break; } old_memavl= memavl; - if ((memavl= memavl/4*3) < MIN_SORT_MEMORY && - old_memavl > MIN_SORT_MEMORY) - memavl= MIN_SORT_MEMORY; + if ((memavl= memavl / 4 * 3) < MIN_SORT_BUFFER && + old_memavl > MIN_SORT_BUFFER) + memavl= MIN_SORT_BUFFER; } - if (memavl < MIN_SORT_MEMORY) + if (memavl < MIN_SORT_BUFFER) { mi_check_print_error(sort_param->sort_info->param, "MyISAM sort buffer too small"); @@ -569,7 +567,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) if (!mergebuf) { length=param->sort_buffer_length; - while (length >= MIN_SORT_MEMORY) + while (length >= MIN_SORT_BUFFER) { if ((mergebuf= my_malloc(length, MYF(0)))) break;