Commit b7b9a4e8 authored by Vasil Dimov's avatar Vasil Dimov

Partial fix for Bug#11764622 57480: MEMORY LEAK WHEN HAVING 256+ TABLES

Port vasil.dimov@oracle.com-20111205082756-wtlg8isyn4yohyny from mysql-trunk
parent 841e8ddb
...@@ -3816,9 +3816,8 @@ retry: ...@@ -3816,9 +3816,8 @@ retry:
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
} }
prebuilt = row_create_prebuilt(ib_table); prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
prebuilt->mysql_row_len = table->s->reclength;
prebuilt->default_rec = table->s->default_values; prebuilt->default_rec = table->s->default_values;
ut_ad(prebuilt->default_rec); ut_ad(prebuilt->default_rec);
......
...@@ -1008,7 +1008,12 @@ ha_innobase::final_add_index( ...@@ -1008,7 +1008,12 @@ ha_innobase::final_add_index(
row_prebuilt_free(prebuilt, TRUE); row_prebuilt_free(prebuilt, TRUE);
error = row_merge_drop_table(trx, old_table); error = row_merge_drop_table(trx, old_table);
add->indexed_table->n_mysql_handles_opened++; add->indexed_table->n_mysql_handles_opened++;
prebuilt = row_create_prebuilt(add->indexed_table); prebuilt = row_create_prebuilt(add->indexed_table,
0 /* XXX Do we know the mysql_row_len here?
Before the addition of this parameter to
row_create_prebuilt() the mysql_row_len
member was left 0 (from zalloc) in the
prebuilt object. */);
} }
err = convert_error_code_to_mysql( err = convert_error_code_to_mysql(
......
...@@ -231,6 +231,12 @@ dtuple_set_n_fields_cmp( ...@@ -231,6 +231,12 @@ dtuple_set_n_fields_cmp(
dtuple_t* tuple, /*!< in: tuple */ dtuple_t* tuple, /*!< in: tuple */
ulint n_fields_cmp); /*!< in: number of fields used in ulint n_fields_cmp); /*!< in: number of fields used in
comparisons in rem0cmp.* */ comparisons in rem0cmp.* */
/* Estimate the number of bytes that are going to be allocated when
creating a new dtuple_t object */
#define DTUPLE_EST_ALLOC(n_fields) \
(sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t))
/**********************************************************//** /**********************************************************//**
Creates a data tuple to a memory heap. The default value for number Creates a data tuple to a memory heap. The default value for number
of fields used in record comparisons for this tuple is n_fields. of fields used in record comparisons for this tuple is n_fields.
...@@ -240,7 +246,8 @@ dtuple_t* ...@@ -240,7 +246,8 @@ dtuple_t*
dtuple_create( dtuple_create(
/*==========*/ /*==========*/
mem_heap_t* heap, /*!< in: memory heap where the tuple mem_heap_t* heap, /*!< in: memory heap where the tuple
is created */ is created, DTUPLE_EST_ALLOC(n_fields)
bytes will be allocated from this heap */
ulint n_fields); /*!< in: number of fields */ ulint n_fields); /*!< in: number of fields */
/**********************************************************//** /**********************************************************//**
......
...@@ -356,15 +356,15 @@ dtuple_t* ...@@ -356,15 +356,15 @@ dtuple_t*
dtuple_create( dtuple_create(
/*==========*/ /*==========*/
mem_heap_t* heap, /*!< in: memory heap where the tuple mem_heap_t* heap, /*!< in: memory heap where the tuple
is created */ is created, DTUPLE_EST_ALLOC(n_fields)
bytes will be allocated from this heap */
ulint n_fields) /*!< in: number of fields */ ulint n_fields) /*!< in: number of fields */
{ {
dtuple_t* tuple; dtuple_t* tuple;
ut_ad(heap); ut_ad(heap);
tuple = (dtuple_t*) mem_heap_alloc(heap, sizeof(dtuple_t) tuple = (dtuple_t*) mem_heap_alloc(heap, DTUPLE_EST_ALLOC(n_fields));
+ n_fields * sizeof(dfield_t));
tuple->info_bits = 0; tuple->info_bits = 0;
tuple->n_fields = n_fields; tuple->n_fields = n_fields;
tuple->n_fields_cmp = n_fields; tuple->n_fields_cmp = n_fields;
......
...@@ -168,7 +168,9 @@ UNIV_INTERN ...@@ -168,7 +168,9 @@ UNIV_INTERN
row_prebuilt_t* row_prebuilt_t*
row_create_prebuilt( row_create_prebuilt(
/*================*/ /*================*/
dict_table_t* table); /*!< in: Innobase table handle */ dict_table_t* table, /*!< in: Innobase table handle */
ulint mysql_row_len); /*!< in: length in bytes of a row in
the MySQL format */
/********************************************************************//** /********************************************************************//**
Free a prebuilt struct for a MySQL table handle. */ Free a prebuilt struct for a MySQL table handle. */
UNIV_INTERN UNIV_INTERN
......
...@@ -667,17 +667,60 @@ UNIV_INTERN ...@@ -667,17 +667,60 @@ UNIV_INTERN
row_prebuilt_t* row_prebuilt_t*
row_create_prebuilt( row_create_prebuilt(
/*================*/ /*================*/
dict_table_t* table) /*!< in: Innobase table handle */ dict_table_t* table, /*!< in: Innobase table handle */
ulint mysql_row_len) /*!< in: length in bytes of a row in
the MySQL format */
{ {
row_prebuilt_t* prebuilt; row_prebuilt_t* prebuilt;
mem_heap_t* heap; mem_heap_t* heap;
dict_index_t* clust_index; dict_index_t* clust_index;
dtuple_t* ref; dtuple_t* ref;
ulint ref_len; ulint ref_len;
ulint search_tuple_n_fields;
search_tuple_n_fields = 2 * dict_table_get_n_cols(table);
clust_index = dict_table_get_first_index(table);
heap = mem_heap_create(sizeof *prebuilt + 128); /* Make sure that search_tuple is long enough for clustered index */
ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
ref_len = dict_index_get_n_unique(clust_index);
prebuilt = mem_heap_zalloc(heap, sizeof *prebuilt); #define PREBUILT_HEAP_INITIAL_SIZE \
( \
sizeof(*prebuilt) \
/* allocd in this function */ \
+ DTUPLE_EST_ALLOC(search_tuple_n_fields) \
+ DTUPLE_EST_ALLOC(ref_len) \
/* allocd in row_prebuild_sel_graph() */ \
+ sizeof(sel_node_t) \
+ sizeof(que_fork_t) \
+ sizeof(que_thr_t) \
/* allocd in row_get_prebuilt_update_vector() */ \
+ sizeof(upd_node_t) \
+ sizeof(upd_t) \
+ sizeof(upd_field_t) \
* dict_table_get_n_cols(table) \
+ sizeof(que_fork_t) \
+ sizeof(que_thr_t) \
/* allocd in row_get_prebuilt_insert_row() */ \
+ sizeof(ins_node_t) \
/* mysql_row_len could be huge and we are not \
sure if this prebuilt instance is going to be \
used in inserts */ \
+ (mysql_row_len < 256 ? mysql_row_len : 0) \
+ DTUPLE_EST_ALLOC(dict_table_get_n_cols(table)) \
+ sizeof(que_fork_t) \
+ sizeof(que_thr_t) \
)
/* 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);
prebuilt = mem_heap_zalloc(heap, sizeof(*prebuilt));
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED; prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED; prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
...@@ -695,15 +738,7 @@ row_create_prebuilt( ...@@ -695,15 +738,7 @@ row_create_prebuilt(
UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type, UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
sizeof prebuilt->stored_select_lock_type); sizeof prebuilt->stored_select_lock_type);
prebuilt->search_tuple = dtuple_create( prebuilt->search_tuple = dtuple_create(heap, search_tuple_n_fields);
heap, 2 * dict_table_get_n_cols(table));
clust_index = dict_table_get_first_index(table);
/* Make sure that search_tuple is long enough for clustered index */
ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
ref_len = dict_index_get_n_unique(clust_index);
ref = dtuple_create(heap, ref_len); ref = dtuple_create(heap, ref_len);
...@@ -720,6 +755,8 @@ row_create_prebuilt( ...@@ -720,6 +755,8 @@ row_create_prebuilt(
prebuilt->autoinc_last_value = 0; prebuilt->autoinc_last_value = 0;
prebuilt->mysql_row_len = mysql_row_len;
return(prebuilt); return(prebuilt);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment