3917 Mikael Ronstrom 2012-05-31
BUG#13903821, fix a memory leak at inserts
modified:
storage/innobase/btr/btr0cur.cc
storage/innobase/include/dict0dict.h
storage/innobase/include/dict0dict.ic
storage/innobase/include/row0mysql.h
storage/innobase/row/row0ins.cc
storage/innobase/row/row0mysql.cc
3916 Sunanda Menon 2012-05-31
changed VERSION string for this branch
modified:
VERSION
=== modified file 'storage/innobase/btr/btr0cur.cc'
--- a/storage/innobase/btr/btr0cur.cc revid:sunanda.menon@stripped
+++ b/storage/innobase/btr/btr0cur.cc revid:mikael.ronstrom@stripped
@@ -482,7 +482,7 @@ btr_cur_search_to_nth_level(
#else
switch (latch_mode) {
default:
- if (level == 0) {
+ if (level == 0 || !dict_index_is_online_ddl(index)) {
break;
}
/* fall through */
=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h revid:sunanda.menon@stripped
+++ b/storage/innobase/include/dict0dict.h revid:mikael.ronstrom@stripped
@@ -666,6 +666,15 @@ dict_table_get_first_index(
const dict_table_t* table) /*!< in: table */
__attribute__((nonnull, warn_unused_result));
/********************************************************************//**
+Gets the last index on the table.
+@return index, NULL if none exists */
+UNIV_INLINE
+dict_index_t*
+dict_table_get_last_index(
+/*=======================*/
+ const dict_table_t* table) /*!< in: table */
+ __attribute__((nonnull, warn_unused_result));
+/********************************************************************//**
Gets the next index on the table.
@return index, NULL if none left */
UNIV_INLINE
@@ -676,6 +685,7 @@ dict_table_get_next_index(
__attribute__((nonnull, warn_unused_result));
#else /* UNIV_DEBUG */
# define dict_table_get_first_index(table) UT_LIST_GET_FIRST((table)->indexes)
+# define dict_table_get_last_index(table) UT_LIST_GET_LAST((table)->indexes)
# define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
#endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
=== modified file 'storage/innobase/include/dict0dict.ic'
--- a/storage/innobase/include/dict0dict.ic revid:sunanda.menon@stripped
+++ b/storage/innobase/include/dict0dict.ic revid:mikael.ronstrom@stripped
@@ -224,6 +224,22 @@ dict_table_get_first_index(
}
/********************************************************************//**
+Gets the last index on the table.
+@return index, NULL if none exists */
+UNIV_INLINE
+dict_index_t*
+dict_table_get_last_index(
+/*=======================*/
+ const dict_table_t* table) /*!< in: table */
+{
+ ut_ad(table);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ return(UT_LIST_GET_LAST((const_cast<const dict_table_t*>(table))
+ ->indexes));
+}
+
+/********************************************************************//**
Gets the next index on the table.
@return index, NULL if none left */
UNIV_INLINE
=== modified file 'storage/innobase/include/row0mysql.h'
--- a/storage/innobase/include/row0mysql.h revid:sunanda.menon@stripped
+++ b/storage/innobase/include/row0mysql.h revid:mikael.ronstrom@stripped
@@ -724,6 +724,11 @@ struct row_prebuilt_struct {
columns in the table */
upd_node_t* upd_node; /*!< Innobase SQL update node used
to perform updates and deletes */
+ trx_id_t trx_id; /*!< The transaction id of the last
+ index of the table, when the insert
+ query graph was built. We use it for
+ checking whether the insert query
+ graphs needs to be rebuilt */
que_fork_t* ins_graph; /*!< Innobase SQL query graph used
in inserts */
que_fork_t* upd_graph; /*!< Innobase SQL query graph used
=== modified file 'storage/innobase/row/row0ins.cc'
--- a/storage/innobase/row/row0ins.cc revid:sunanda.menon@stripped
+++ b/storage/innobase/row/row0ins.cc revid:mikael.ronstrom@stripped
@@ -111,7 +111,6 @@ ins_node_create_entry_list(
dict_index_t* index;
dtuple_t* entry;
- ut_ad(node->ins_type != INS_DIRECT);
ut_ad(node->entry_sys_heap);
UT_LIST_INIT(node->entry_list);
@@ -207,9 +206,7 @@ ins_node_set_new_row(
/* Create templates for index entries */
- if (node->ins_type != INS_DIRECT) {
- ins_node_create_entry_list(node);
- }
+ ins_node_create_entry_list(node);
/* Allocate from entry_sys_heap buffers for sys fields */
@@ -2460,7 +2457,7 @@ row_ins_index_entry(
/***********************************************************//**
Sets the values of the dtuple fields in entry from the values of appropriate
columns in row. */
-static
+static __attribute__((nonnull))
void
row_ins_index_entry_set_vals(
/*=========================*/
@@ -2471,9 +2468,6 @@ row_ins_index_entry_set_vals(
ulint n_fields;
ulint i;
- ut_ad(row);
- ut_ad(entry);
-
n_fields = dtuple_get_n_fields(entry);
for (i = 0; i < n_fields; i++) {
@@ -2637,24 +2631,22 @@ row_ins(
ins_node_t* node, /*!< in: row insert node */
que_thr_t* thr) /*!< in: query thread */
{
+ dberr_t err;
+
if (node->state == INS_NODE_ALLOC_ROW_ID) {
row_ins_alloc_row_id_step(node);
node->index = dict_table_get_first_index(node->table);
+ node->entry = UT_LIST_GET_FIRST(node->entry_list);
+
+ if (node->ins_type == INS_SEARCHED) {
- switch (node->ins_type) {
- case INS_DIRECT:
- node->entry = NULL;
- break;
- case INS_SEARCHED:
- node->entry = UT_LIST_GET_FIRST(node->entry_list);
row_ins_get_row_from_select(node);
- break;
- case INS_VALUES:
- node->entry = UT_LIST_GET_FIRST(node->entry_list);
+
+ } else if (node->ins_type == INS_VALUES) {
+
row_ins_get_row_from_values(node);
- break;
}
node->state = INS_NODE_INSERT_ENTRIES;
@@ -2663,42 +2655,23 @@ row_ins(
ut_ad(node->state == INS_NODE_INSERT_ENTRIES);
while (node->index != NULL) {
- dberr_t err;
-
- if (node->index->type & DICT_FTS) {
- goto next_index;
- }
-
- if (node->ins_type == INS_DIRECT) {
- /* node->entry == NULL here, except when
- row_ins_index_entry_step() returned
- DB_LOCK_WAIT on the previous call and
- row_insert_for_mysql() retried the insert. */
- node->entry = row_build_index_entry(
- node->row, NULL, node->index,
- node->entry_sys_heap);
- }
-
- err = row_ins_index_entry_step(node, thr);
+ if (node->index->type != DICT_FTS) {
+ err = row_ins_index_entry_step(node, thr);
- if (err != DB_SUCCESS) {
+ if (err != DB_SUCCESS) {
- return(err);
+ return(err);
+ }
}
-next_index:
node->index = dict_table_get_next_index(node->index);
- node->entry = (node->ins_type != INS_DIRECT)
- ? UT_LIST_GET_NEXT(tuple_list, node->entry)
- : NULL;
+ node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
/* Skip corrupted secondary index and its entry */
while (node->index && dict_index_is_corrupted(node->index)) {
node->index = dict_table_get_next_index(node->index);
- node->entry = (node->ins_type != INS_DIRECT)
- ? UT_LIST_GET_NEXT(tuple_list, node->entry)
- : NULL;
+ node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
}
}
=== modified file 'storage/innobase/row/row0mysql.cc'
--- a/storage/innobase/row/row0mysql.cc revid:sunanda.menon@stripped
+++ b/storage/innobase/row/row0mysql.cc revid:mikael.ronstrom@stripped
@@ -957,44 +957,60 @@ row_get_prebuilt_insert_row(
row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
handle */
{
- ins_node_t* node;
- dtuple_t* row;
- dict_table_t* table = prebuilt->table;
+ dict_table_t* table = prebuilt->table;
+ const dict_index_t* last_index = dict_table_get_last_index(table);
ut_ad(prebuilt && table && prebuilt->trx);
- if (prebuilt->ins_node == NULL) {
+ /* Check if a new index has been added that prebuilt doesn't know
+ about. We need to rebuild the query graph. */
- /* Not called before for this handle: create an insert node
- and query graph to the prebuilt struct */
+ if (prebuilt->ins_node != 0) {
- node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
+ if (prebuilt->trx_id >= last_index->trx_id) {
+ return(prebuilt->ins_node->row);
+ }
- prebuilt->ins_node = node;
+ que_graph_free_recursive(prebuilt->ins_graph);
- if (prebuilt->ins_upd_rec_buff == NULL) {
- prebuilt->ins_upd_rec_buff = static_cast<byte*>(
- mem_heap_alloc(
- prebuilt->heap,
- prebuilt->mysql_row_len));
- }
+ prebuilt->ins_graph = 0;
+ }
- row = dtuple_create(prebuilt->heap,
- dict_table_get_n_cols(table));
+ /* Create an insert node and query graph to the prebuilt struct */
- dict_table_copy_types(row, table);
+ ins_node_t* node;
- ins_node_set_new_row(node, row);
+ node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
- prebuilt->ins_graph = static_cast<que_fork_t*>(
- que_node_get_parent(
- pars_complete_graph_for_exec(
- node,
- prebuilt->trx, prebuilt->heap)));
+ prebuilt->ins_node = node;
- prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
+ if (prebuilt->ins_upd_rec_buff == 0) {
+ prebuilt->ins_upd_rec_buff = static_cast<byte*>(
+ mem_heap_alloc(
+ prebuilt->heap,
+ prebuilt->mysql_row_len));
}
+ dtuple_t* row;
+
+ row = dtuple_create(prebuilt->heap, dict_table_get_n_cols(table));
+
+ dict_table_copy_types(row, table);
+
+ ins_node_set_new_row(node, row);
+
+ prebuilt->ins_graph = static_cast<que_fork_t*>(
+ que_node_get_parent(
+ pars_complete_graph_for_exec(
+ node,
+ prebuilt->trx, prebuilt->heap)));
+
+ prebuilt->ins_graph->state = QUE_FORK_ACTIVE;
+
+ ut_ad(prebuilt->trx_id == 0 || prebuilt->trx_id <= last_index->trx_id);
+
+ prebuilt->trx_id = last_index->trx_id;
+
return(prebuilt->ins_node->row);
}
@@ -1073,10 +1089,8 @@ row_lock_table_autoinc_for_mysql(
trx->op_info = "setting auto-inc lock";
- if (node == NULL) {
- row_get_prebuilt_insert_row(prebuilt);
- node = prebuilt->ins_node;
- }
+ row_get_prebuilt_insert_row(prebuilt);
+ node = prebuilt->ins_node;
/* We use the insert query graph as the dummy graph needed
in the lock module call */
@@ -1266,10 +1280,8 @@ row_insert_for_mysql(
trx_start_if_not_started_xa(trx);
- if (node == NULL) {
- row_get_prebuilt_insert_row(prebuilt);
- node = prebuilt->ins_node;
- }
+ row_get_prebuilt_insert_row(prebuilt);
+ node = prebuilt->ins_node;
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (mikael.ronstrom:3916 to 3917) Bug#13903821 | Mikael Ronstrom | 31 May |