=== modified file 'internal/mysql-test/suite/i_innodb/r/innodb_bug14500557.result' --- internal/mysql-test/suite/i_innodb/r/innodb_bug14500557.result +++ internal/mysql-test/suite/i_innodb/r/innodb_bug14500557.result @@ -99,13 +99,6 @@ char_length(f15), char_length(f16) from char_length(f1) char_length(f2) char_length(f3) char_length(f4) char_length(f5) char_length(f6) char_length(f7) char_length(f8) char_length(f9) char_length(f10) char_length(f11) char_length(f12) char_length(f13) char_length(f14) char_length(f15) char_length(f16) 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 -# When the DBUG_EXECUTE_IF is enabled, it will assert that -# the search key buffer in innodb table handler is fully -# used. -set debug="+d,innodb_srch_key_buffer_full"; -# Expecting that the search key buffer in innodb table handler -# is fully used. If not the assert labelled -# innodb_srch_key_buffer_full will fail. select f0 = 2, f1 = @b255, f2 = @b255, @@ -134,9 +127,6 @@ f14 like @b192 and f15 like @b192 and f16 like @b192 order by f0 desc; f0 = 2 f1 = @b255 f2 = @b255 f3 = @b255 f4 = @b255 f5 = @b255 f6 = @b255 f7 = @b255 f8 = @b255 f9 = @b255 f10 = @b255 f11 = @b255 f12 = @b255 f13 = @b255 f14 = @b255 f15 = @b255 f16 = @b255 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -# Expecting that the search key buffer in innodb table handler -# is fully used. If not the assert labelled -# innodb_srch_key_buffer_full will fail. select f0 = 1, f1 = @c255, f2 = @c255, @@ -165,7 +155,6 @@ f14 like @c192 and f15 like @c192 and f16 like @c192 order by f0 desc; f0 = 1 f1 = @c255 f2 = @c255 f3 = @c255 f4 = @c255 f5 = @c255 f6 = @c255 f7 = @c255 f8 = @c255 f9 = @c255 f10 = @c255 f11 = @c255 f12 = @c255 f13 = @c255 f14 = @c255 f15 = @c255 f16 = @c255 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -set debug="-d,innodb_srch_key_buffer_full"; drop table t1, t2; # End of test case. # @@ -187,3 +176,26 @@ k1 k2 k3 k4 k5 A B C D 1 drop table t1; # End of test case. +# +# Bug #17780517 5.6 PARTITIONS USE MUCH MORE +# MEMORY THAN 5.1 +# +create table t1 ( +f1 BIGINT,f2 BIGINT,f3 BIGINT,f4 BIGINT,f5 BIGINT, +f6 BIGINT,f7 BIGINT,f8 BIGINT,f9 BIGINT,f10 BIGINT, +f11 BIGINT,f12 BIGINT,f13 BIGINT,f14 BIGINT,f15 BIGINT, +f16 BIGINT,f17 BIGINT,f18 BIGINT,f19 BIGINT,f20 BIGINT, +f21 BIGINT,f22 BIGINT,f23 BIGINT,f24 BIGINT,f25 BIGINT, +f26 BIGINT,f27 BIGINT,f28 BIGINT,f29 BIGINT,f30 BIGINT, +f31 BIGINT,f32 BIGINT, +primary key ( +f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16), +key( +f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30, +f31,f32)) engine=innodb; +set debug="+d,innodb_srch_key_buffer_max_value"; +select count(*) from t1; +count(*) +0 +set debug="-d,innodb_srch_key_buffer_max_value"; +drop table t1; === modified file 'internal/mysql-test/suite/i_innodb/t/innodb_bug14500557.test' --- internal/mysql-test/suite/i_innodb/t/innodb_bug14500557.test +++ internal/mysql-test/suite/i_innodb/t/innodb_bug14500557.test @@ -101,14 +101,6 @@ select char_length(f1), char_length(f2) char_length(f13), char_length(f14), char_length(f15), char_length(f16) from t2; ---echo # When the DBUG_EXECUTE_IF is enabled, it will assert that ---echo # the search key buffer in innodb table handler is fully ---echo # used. -set debug="+d,innodb_srch_key_buffer_full"; - ---echo # Expecting that the search key buffer in innodb table handler ---echo # is fully used. If not the assert labelled ---echo # innodb_srch_key_buffer_full will fail. select f0 = 2, f1 = @b255, f2 = @b255, @@ -136,9 +128,6 @@ select f0 = 2, f14 like @b192 and f15 like @b192 and f16 like @b192 order by f0 desc; ---echo # Expecting that the search key buffer in innodb table handler ---echo # is fully used. If not the assert labelled ---echo # innodb_srch_key_buffer_full will fail. select f0 = 1, f1 = @c255, f2 = @c255, @@ -166,8 +155,6 @@ select f0 = 1, f14 like @c192 and f15 like @c192 and f16 like @c192 order by f0 desc; -set debug="-d,innodb_srch_key_buffer_full"; - drop table t1, t2; --echo # End of test case. @@ -191,3 +178,42 @@ insert into t1 (k1,k2,k3,k4,k5) values select * from t1 order by k2; drop table t1; --echo # End of test case. + + +--echo # +--echo # Bug #17780517 5.6 PARTITIONS USE MUCH MORE +--echo # MEMORY THAN 5.1 +--echo # + +create table t1 ( +f1 BIGINT,f2 BIGINT,f3 BIGINT,f4 BIGINT,f5 BIGINT, +f6 BIGINT,f7 BIGINT,f8 BIGINT,f9 BIGINT,f10 BIGINT, +f11 BIGINT,f12 BIGINT,f13 BIGINT,f14 BIGINT,f15 BIGINT, +f16 BIGINT,f17 BIGINT,f18 BIGINT,f19 BIGINT,f20 BIGINT, +f21 BIGINT,f22 BIGINT,f23 BIGINT,f24 BIGINT,f25 BIGINT, +f26 BIGINT,f27 BIGINT,f28 BIGINT,f29 BIGINT,f30 BIGINT, +f31 BIGINT,f32 BIGINT, +primary key ( +f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16), +key( +f17,f18,f19,f20,f21,f22,f23,f24,f25,f26,f27,f28,f29,f30, +f31,f32)) engine=innodb; + +# Search key buffers are only needed when converting +# INT's from little endian format to big endian +# format. The maximum fields which can be present in +# index is 16.Therefore maximum possible size of the +# search key buffer considering all fields as BIGINT is +# Max for PK: 16 * 8 (size of BIGINT) = 128 bytes +# Max for Secondary key: 16 * 8 bytes + PK = 256 bytes +# If the maximum number of fields allowed in the index +# is changed in future,this test case has to be changed +# accordingly. +set debug="+d,innodb_srch_key_buffer_max_value"; +select count(*) from t1; +set debug="-d,innodb_srch_key_buffer_max_value"; + +drop table t1; + + + === modified file 'storage/innobase/handler/ha_innodb.cc' --- storage/innobase/handler/ha_innodb.cc +++ storage/innobase/handler/ha_innodb.cc @@ -7470,7 +7470,8 @@ ha_innobase::index_read( row_sel_convert_mysql_key_to_innobase( prebuilt->search_tuple, - srch_key_val1, sizeof(srch_key_val1), + prebuilt->srch_key_val1, + prebuilt->srch_key_val_len, index, (byte*) key_ptr, (ulint) key_len, @@ -10410,7 +10411,8 @@ ha_innobase::records_in_range( row_sel_convert_mysql_key_to_innobase( range_start, - srch_key_val1, sizeof(srch_key_val1), + prebuilt->srch_key_val1, + prebuilt->srch_key_val_len, index, (byte*) (min_key ? min_key->key : (const uchar*) 0), @@ -10422,7 +10424,8 @@ ha_innobase::records_in_range( row_sel_convert_mysql_key_to_innobase( range_end, - srch_key_val2, sizeof(srch_key_val2), + prebuilt->srch_key_val2, + prebuilt->srch_key_val_len, index, (byte*) (max_key ? max_key->key : (const uchar*) 0), === modified file 'storage/innobase/handler/ha_innodb.h' --- storage/innobase/handler/ha_innodb.h +++ storage/innobase/handler/ha_innodb.h @@ -71,13 +71,6 @@ class ha_innobase: public handler uchar* upd_buf; /*!< buffer used in updates */ ulint upd_buf_size; /*!< the size of upd_buf in bytes */ - uchar srch_key_val1[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; - uchar srch_key_val2[MAX_KEY_LENGTH + MAX_REF_PARTS*2]; - /*!< buffers used in converting - search key values from MySQL format - to InnoDB format. For each column - 2 bytes are used to store length, - hence MAX_REF_PARTS*2. */ Table_flags int_table_flags; uint primary_key; ulong start_of_scan; /*!< this is set to 1 when we are === modified file 'storage/innobase/include/row0mysql.h' --- storage/innobase/include/row0mysql.h +++ storage/innobase/include/row0mysql.h @@ -871,6 +871,14 @@ struct row_prebuilt_t { unsigned innodb_api:1; /*!< whether this is a InnoDB API query */ const rec_t* innodb_api_rec; /*!< InnoDB API search result */ + byte* srch_key_val1; /*!< buffer used in converting + search key values from MySQL format + to InnoDB format.*/ + byte* srch_key_val2; /*!< buffer used in converting + search key values from MySQL format + to InnoDB format.*/ + uint srch_key_val_len; /*!< Size of search key */ + }; /** Callback for row_mysql_sys_index_iterate() */ === modified file 'storage/innobase/row/row0mysql.cc' --- storage/innobase/row/row0mysql.cc +++ storage/innobase/row/row0mysql.cc @@ -33,6 +33,7 @@ Created 9/17/2000 Heikki Tuuri #include #include +#include #include "row0ins.h" #include "row0merge.h" #include "row0sel.h" @@ -710,8 +711,10 @@ row_create_prebuilt( row_prebuilt_t* prebuilt; mem_heap_t* heap; dict_index_t* clust_index; + dict_index_t* temp_index; dtuple_t* ref; ulint ref_len; + uint srch_key_len = 0; ulint search_tuple_n_fields; search_tuple_n_fields = 2 * dict_table_get_n_cols(table); @@ -723,6 +726,14 @@ row_create_prebuilt( ref_len = dict_index_get_n_unique(clust_index); + + /* Maximum size of the buffer needed for conversion of INTs from + little endian format to big endian format in an index. An index + can have maximum 16 columns (MAX_REF_PARTS) in it. Therfore + Max size for PK: 16 * 8 bytes (BIGINT's size) = 128 bytes + Max size Secondary index: 16 * 8 bytes + PK = 256 bytes. */ +#define MAX_SRCH_KEY_VAL_BUFFER 2* (8 * MAX_REF_PARTS) + #define PREBUILT_HEAP_INITIAL_SIZE \ ( \ sizeof(*prebuilt) \ @@ -751,10 +762,38 @@ row_create_prebuilt( + sizeof(que_thr_t) \ ) + /* Calculate size of key buffer used to store search key in + InnoDB format. MySQL stores INTs in little endian format and + InnoDB stores INTs in big endian format with the sign bit + flipped. All other field types are stored/compared the same + in MySQL and InnoDB, so we must create a buffer containing + the INT key parts in InnoDB format.We need two such buffers + since both start and end keys are used in records_in_range(). */ + + for (temp_index = dict_table_get_first_index(table); temp_index; + temp_index = dict_table_get_next_index(temp_index)) { + DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value", + ut_a(temp_index->n_user_defined_cols + == MAX_REF_PARTS);); + uint temp_len = 0; + for (uint i = 0; i < temp_index->n_uniq; i++) { + if (temp_index->fields[i].col->mtype == DATA_INT) { + temp_len += + temp_index->fields[i].fixed_len; + } + } + srch_key_len = ut_max(srch_key_len,temp_len); + } + + ut_a(srch_key_len <= MAX_SRCH_KEY_VAL_BUFFER); + + DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value", + ut_a(srch_key_len == MAX_SRCH_KEY_VAL_BUFFER);); + /* We allocate enough space for the objects that are likely to be created later in order to minimize the number of malloc() calls */ - heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE); + heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE + 2 * srch_key_len); prebuilt = static_cast( mem_heap_zalloc(heap, sizeof(*prebuilt))); @@ -767,6 +806,18 @@ row_create_prebuilt( prebuilt->sql_stat_start = TRUE; prebuilt->heap = heap; + prebuilt->srch_key_val_len = srch_key_len; + if (prebuilt->srch_key_val_len) { + prebuilt->srch_key_val1 = static_cast( + mem_heap_alloc(prebuilt->heap, + 2 * prebuilt->srch_key_val_len)); + prebuilt->srch_key_val2 = prebuilt->srch_key_val1 + + prebuilt->srch_key_val_len; + } else { + prebuilt->srch_key_val1 = NULL; + prebuilt->srch_key_val2 = NULL; + } + btr_pcur_reset(&prebuilt->pcur); btr_pcur_reset(&prebuilt->clust_pcur); === modified file 'storage/innobase/row/row0sel.cc' --- storage/innobase/row/row0sel.cc +++ storage/innobase/row/row0sel.cc @@ -2455,13 +2455,12 @@ row_sel_convert_mysql_key_to_innobase( /* Storing may use at most data_len bytes of buf */ if (UNIV_LIKELY(!is_null)) { - ut_a(buf + data_len <= original_buf + buf_len); - row_mysql_store_col_in_innobase_format( - dfield, buf, - FALSE, /* MySQL key value format col */ - key_ptr + data_offset, data_len, - dict_table_is_comp(index->table)); - buf += data_len; + buf = row_mysql_store_col_in_innobase_format( + dfield, buf, + FALSE, /* MySQL key value format col */ + key_ptr + data_offset, data_len, + dict_table_is_comp(index->table)); + ut_a(buf <= original_buf + buf_len); } key_ptr += data_field_len; @@ -2505,9 +2504,6 @@ row_sel_convert_mysql_key_to_innobase( dfield++; } - DBUG_EXECUTE_IF("innodb_srch_key_buffer_full", - ut_a(buf == (original_buf + buf_len));); - ut_a(buf <= original_buf + buf_len); /* We set the length of tuple to n_fields: we assume that the memory