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:
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;
ut_ad(prebuilt->default_rec);
......
......@@ -1008,7 +1008,12 @@ ha_innobase::final_add_index(
row_prebuilt_free(prebuilt, TRUE);
error = row_merge_drop_table(trx, old_table);
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(
......
......@@ -231,6 +231,12 @@ dtuple_set_n_fields_cmp(
dtuple_t* tuple, /*!< in: tuple */
ulint n_fields_cmp); /*!< in: number of fields used in
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
of fields used in record comparisons for this tuple is n_fields.
......@@ -240,7 +246,8 @@ dtuple_t*
dtuple_create(
/*==========*/
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 */
/**********************************************************//**
......
......@@ -356,15 +356,15 @@ dtuple_t*
dtuple_create(
/*==========*/
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 */
{
dtuple_t* tuple;
ut_ad(heap);
tuple = (dtuple_t*) mem_heap_alloc(heap, sizeof(dtuple_t)
+ n_fields * sizeof(dfield_t));
tuple = (dtuple_t*) mem_heap_alloc(heap, DTUPLE_EST_ALLOC(n_fields));
tuple->info_bits = 0;
tuple->n_fields = n_fields;
tuple->n_fields_cmp = n_fields;
......
......@@ -168,7 +168,9 @@ UNIV_INTERN
row_prebuilt_t*
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. */
UNIV_INTERN
......
......@@ -667,17 +667,60 @@ UNIV_INTERN
row_prebuilt_t*
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;
mem_heap_t* heap;
dict_index_t* clust_index;
dtuple_t* ref;
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_n2 = ROW_PREBUILT_ALLOCATED;
......@@ -695,15 +738,7 @@ row_create_prebuilt(
UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type,
sizeof prebuilt->stored_select_lock_type);
prebuilt->search_tuple = dtuple_create(
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);
prebuilt->search_tuple = dtuple_create(heap, search_tuple_n_fields);
ref = dtuple_create(heap, ref_len);
......@@ -720,6 +755,8 @@ row_create_prebuilt(
prebuilt->autoinc_last_value = 0;
prebuilt->mysql_row_len = mysql_row_len;
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