diff options
Diffstat (limited to 'storage/innobase/row')
-rw-r--r-- | storage/innobase/row/row0ins.c | 11 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.c | 5 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.c | 70 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.c | 33 | ||||
-rw-r--r-- | storage/innobase/row/row0row.c | 55 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 116 | ||||
-rw-r--r-- | storage/innobase/row/row0uins.c | 4 | ||||
-rw-r--r-- | storage/innobase/row/row0umod.c | 25 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.c | 7 |
9 files changed, 234 insertions, 92 deletions
diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index e0414cde80d..2925feb2904 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -118,6 +118,9 @@ ins_node_create_entry_list( node->entry_sys_heap); UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry); + /* We will include all indexes (include those corrupted + secondary indexes) in the entry list. Filteration of + these corrupted index will be done in row_ins() */ index = dict_table_get_next_index(index); } } @@ -2045,7 +2048,6 @@ row_ins_index_entry_low( mtr_start(&mtr); if (err != DB_SUCCESS) { - goto function_exit; } @@ -2395,6 +2397,13 @@ row_ins( node->index = dict_table_get_next_index(node->index); node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); + + /* Skip corrupted secondar index and its entry */ + while (node->index && dict_index_is_corrupted(node->index)) { + + node->index = dict_table_get_next_index(node->index); + node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); + } } ut_ad(node->entry == NULL); diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index 5be437add5a..d42f21241ca 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -2554,8 +2554,9 @@ row_merge_is_index_usable( const trx_t* trx, /*!< in: transaction */ const dict_index_t* index) /*!< in: index to check */ { - return(!trx->read_view - || read_view_sees_trx_id(trx->read_view, index->trx_id)); + return(!dict_index_is_corrupted(index) + && (!trx->read_view + || read_view_sees_trx_id(trx->read_view, index->trx_id))); } /*********************************************************************//** diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index e1ada387729..d0bedd69842 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -576,6 +576,7 @@ handle_new_error: case DB_DUPLICATE_KEY: case DB_FOREIGN_DUPLICATE_KEY: case DB_TOO_BIG_RECORD: + case DB_UNDO_RECORD_TOO_BIG: case DB_ROW_IS_REFERENCED: case DB_NO_REFERENCED_ROW: case DB_CANNOT_ADD_CONSTRAINT: @@ -2015,41 +2016,13 @@ row_create_index_for_mysql( trx_start_if_not_started(trx); - /* Check that the same column does not appear twice in the index. - Starting from 4.0.14, InnoDB should be able to cope with that, but - safer not to allow them. */ - - for (i = 0; i < dict_index_get_n_fields(index); i++) { - ulint j; - - for (j = 0; j < i; j++) { - if (0 == ut_strcmp( - dict_index_get_nth_field(index, j)->name, - dict_index_get_nth_field(index, i)->name)) { - ut_print_timestamp(stderr); - - fputs(" InnoDB: Error: column ", stderr); - ut_print_name(stderr, trx, FALSE, - dict_index_get_nth_field( - index, i)->name); - fputs(" appears twice in ", stderr); - dict_index_name_print(stderr, trx, index); - fputs("\n" - "InnoDB: This is not allowed" - " in InnoDB.\n", stderr); - - err = DB_COL_APPEARS_TWICE_IN_INDEX; - - goto error_handling; - } - } - - /* Check also that prefix_len and actual length - is less than that from DICT_MAX_FIELD_LEN_BY_FORMAT() */ + for (i = 0; i < index->n_def; i++) { + /* Check that prefix_len and actual length + < DICT_MAX_INDEX_COL_LEN */ len = dict_index_get_nth_field(index, i)->prefix_len; - if (field_lengths) { + if (field_lengths && field_lengths[i]) { len = ut_max(len, field_lengths[i]); } @@ -2057,6 +2030,7 @@ row_create_index_for_mysql( if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) { err = DB_TOO_BIG_INDEX_COL; + dict_mem_index_free(index); goto error_handling; } } @@ -3125,7 +3099,8 @@ row_drop_table_for_mysql( ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT); + table = dict_table_get_low_ignore_err( + name, DICT_ERR_IGNORE_INDEX_ROOT | DICT_ERR_IGNORE_CORRUPT); if (!table) { err = DB_TABLE_NOT_FOUND; @@ -3272,6 +3247,19 @@ check_next_foreign: "index_id CHAR;\n" "foreign_id CHAR;\n" "found INT;\n" + + "DECLARE CURSOR cur_fk IS\n" + "SELECT ID FROM SYS_FOREIGN\n" + "WHERE FOR_NAME = :table_name\n" + "AND TO_BINARY(FOR_NAME)\n" + " = TO_BINARY(:table_name)\n" + "LOCK IN SHARE MODE;\n" + + "DECLARE CURSOR cur_idx IS\n" + "SELECT ID FROM SYS_INDEXES\n" + "WHERE TABLE_ID = table_id\n" + "LOCK IN SHARE MODE;\n" + "BEGIN\n" "SELECT ID INTO table_id\n" "FROM SYS_TABLES\n" @@ -3294,13 +3282,9 @@ check_next_foreign: "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n" " found := 0;\n" "END IF;\n" + "OPEN cur_fk;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO foreign_id\n" - " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = :table_name\n" - " AND TO_BINARY(FOR_NAME)\n" - " = TO_BINARY(:table_name)\n" - " LOCK IN SHARE MODE;\n" + " FETCH cur_fk INTO foreign_id;\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -3310,12 +3294,11 @@ check_next_foreign: " WHERE ID = foreign_id;\n" " END IF;\n" "END LOOP;\n" + "CLOSE cur_fk;\n" "found := 1;\n" + "OPEN cur_idx;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO index_id\n" - " FROM SYS_INDEXES\n" - " WHERE TABLE_ID = table_id\n" - " LOCK IN SHARE MODE;\n" + " FETCH cur_idx INTO index_id;\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -3326,6 +3309,7 @@ check_next_foreign: " AND TABLE_ID = table_id;\n" " END IF;\n" "END LOOP;\n" + "CLOSE cur_idx;\n" "DELETE FROM SYS_COLUMNS\n" "WHERE TABLE_ID = table_id;\n" "DELETE FROM SYS_TABLES\n" diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index 83e7c9e4857..efcfdc3bac5 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -469,6 +469,13 @@ row_purge_del_mark( heap = mem_heap_create(1024); while (node->index != NULL) { + /* skip corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; /* Build the index entry */ @@ -508,7 +515,8 @@ row_purge_upd_exist_or_extern_func( ut_ad(node); - if (node->rec_type == TRX_UNDO_UPD_DEL_REC) { + if (node->rec_type == TRX_UNDO_UPD_DEL_REC + || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { goto skip_secondaries; } @@ -516,6 +524,12 @@ row_purge_upd_exist_or_extern_func( heap = mem_heap_create(1024); while (node->index != NULL) { + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; if (row_upd_changes_ord_field_binary(node->index, node->update, @@ -632,14 +646,14 @@ row_purge_parse_undo_rec( roll_ptr_t roll_ptr; ulint info_bits; ulint type; - ulint cmpl_info; ut_ad(node && thr); trx = thr_get_trx(thr); - ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, - updated_extern, &undo_no, &table_id); + ptr = trx_undo_rec_get_pars( + node->undo_rec, &type, &node->cmpl_info, + updated_extern, &undo_no, &table_id); node->rec_type = type; if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) { @@ -652,7 +666,8 @@ row_purge_parse_undo_rec( node->table = NULL; if (type == TRX_UNDO_UPD_EXIST_REC - && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { + && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE + && !(*updated_extern)) { /* Purge requires no changes to indexes: we may return */ @@ -702,7 +717,7 @@ err_exit: /* Read to the partial row the fields that occur in indexes */ - if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { + if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ptr = trx_undo_rec_get_partial_row( ptr, clust_index, &node->row, type == TRX_UNDO_UPD_DEL_REC, diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index 3bd0323ddbe..20fd475343e 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -101,12 +101,27 @@ row_build_index_entry( dfield_copy(dfield, dfield2); - if (dfield_is_null(dfield) || ind_field->prefix_len == 0) { + if (dfield_is_null(dfield)) { continue; } - /* If a column prefix index, take only the prefix. - Prefix-indexed columns may be externally stored. */ + if (ind_field->prefix_len == 0 + && (!dfield_is_ext(dfield) + || dict_index_is_clust(index))) { + /* The dfield_copy() above suffices for + columns that are stored in-page, or for + clustered index record columns that are not + part of a column prefix in the PRIMARY KEY. */ + continue; + } + + /* If the column is stored externally (off-page) in + the clustered index, it must be an ordering field in + the secondary index. In the Antelope format, only + prefix-indexed columns may be stored off-page in the + clustered index record. In the Barracuda format, also + fully indexed long CHAR or VARCHAR columns may be + stored off-page. */ ut_ad(col->ord_part); if (UNIV_LIKELY_NULL(ext)) { @@ -119,15 +134,41 @@ row_build_index_entry( } dfield_set_data(dfield, buf, len); } + + if (ind_field->prefix_len == 0) { + /* In the Barracuda format + (ROW_FORMAT=DYNAMIC or + ROW_FORMAT=COMPRESSED), we can have a + secondary index on an entire column + that is stored off-page in the + clustered index. As this is not a + prefix index (prefix_len == 0), + include the entire off-page column in + the secondary index record. */ + continue; + } } else if (dfield_is_ext(dfield)) { + /* This table is either in Antelope format + (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT) + or a purge record where the ordered part of + the field is not external. + In Antelope, the maximum column prefix + index length is 767 bytes, and the clustered + index record contains a 768-byte prefix of + each off-page column. */ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); len -= BTR_EXTERN_FIELD_REF_SIZE; + dfield_set_len(dfield, len); } - len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, - ind_field->prefix_len, len, dfield_get_data(dfield)); - dfield_set_len(dfield, len); + /* If a column prefix index, take only the prefix. */ + if (ind_field->prefix_len) { + len = dtype_get_at_most_n_mbchars( + col->prtype, col->mbminmaxlen, + ind_field->prefix_len, len, + dfield_get_data(dfield)); + dfield_set_len(dfield, len); + } } ut_ad(dtuple_check_typed(entry)); diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 53d0c2ec232..5d8f53f68da 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -99,14 +99,22 @@ row_sel_sec_rec_is_for_blob( ulint clust_len, /*!< in: length of clust_field */ const byte* sec_field, /*!< in: column in secondary index */ ulint sec_len, /*!< in: length of sec_field */ + ulint prefix_len, /*!< in: index column prefix length + in bytes */ dict_table_t* table) /*!< in: table */ { ulint len; byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN]; ulint zip_size = dict_table_flags_to_zip_size(table->flags); - ulint max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table); + /* This function should never be invoked on an Antelope format + table, because they should always contain enough prefix in the + clustered index record. */ + ut_ad(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP); ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE); + ut_ad(prefix_len >= sec_len); + ut_ad(prefix_len > 0); + ut_a(prefix_len <= sizeof buf); if (UNIV_UNLIKELY (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE, @@ -118,7 +126,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len, + len = btr_copy_externally_stored_field_prefix(buf, prefix_len, zip_size, clust_field, clust_len); @@ -132,7 +140,7 @@ row_sel_sec_rec_is_for_blob( } len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, - sec_len, len, (const char*) buf); + prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); } @@ -224,6 +232,7 @@ row_sel_sec_rec_is_for_clust_rec( col->mbminmaxlen, clust_field, clust_len, sec_field, sec_len, + ifield->prefix_len, clust_index->table)) { goto inequal; } @@ -493,7 +502,7 @@ sel_col_prefetch_buf_alloc( sel_buf = column->prefetch_buf + i; sel_buf->data = NULL; - + sel_buf->len = 0; sel_buf->val_buf_size = 0; } } @@ -518,6 +527,8 @@ sel_col_prefetch_buf_free( mem_free(sel_buf->data); } } + + mem_free(prefetch_buf); } /*********************************************************************//** @@ -2541,6 +2552,8 @@ row_sel_field_store_in_mysql_format( ut_ad(len != UNIV_SQL_NULL); UNIV_MEM_ASSERT_RW(data, len); + UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len); + UNIV_MEM_INVALID(dest, templ->mysql_col_len); switch (templ->type) { const byte* field_end; @@ -2579,14 +2592,16 @@ row_sel_field_store_in_mysql_format( dest = row_mysql_store_true_var_len( dest, len, templ->mysql_length_bytes); + /* Copy the actual data. Leave the rest of the + buffer uninitialized. */ + memcpy(dest, data, len); + break; } /* Copy the actual data */ ut_memcpy(dest, data, len); - /* Pad with trailing spaces. We pad with spaces also the - unused end of a >= 5.0.3 true VARCHAR column, just in case - MySQL expects its contents to be deterministic. */ + /* Pad with trailing spaces. */ pad = dest + len; @@ -3113,6 +3128,39 @@ sel_restore_position_for_mysql( } /********************************************************************//** +Copies a cached field for MySQL from the fetch cache. */ +static +void +row_sel_copy_cached_field_for_mysql( +/*================================*/ + byte* buf, /*!< in/out: row buffer */ + const byte* cache, /*!< in: cached row */ + const mysql_row_templ_t*templ) /*!< in: column template */ +{ + ulint len; + + buf += templ->mysql_col_offset; + cache += templ->mysql_col_offset; + + UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len); + + if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR + && templ->type != DATA_INT) { + /* Check for != DATA_INT to make sure we do + not treat MySQL ENUM or SET as a true VARCHAR! + Find the actual length of the true VARCHAR field. */ + row_mysql_read_true_varchar( + &len, cache, templ->mysql_length_bytes); + len += templ->mysql_length_bytes; + UNIV_MEM_INVALID(buf, templ->mysql_col_len); + } else { + len = templ->mysql_col_len; + } + + ut_memcpy(buf, cache, len); +} + +/********************************************************************//** Pops a cached row for MySQL from the fetch cache. */ UNIV_INLINE void @@ -3124,26 +3172,22 @@ row_sel_pop_cached_row_for_mysql( { ulint i; const mysql_row_templ_t*templ; - byte* cached_rec; + const byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); + UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len); + + cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first]; + if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { /* Copy cache record field by field, don't touch fields that are not covered by current key */ - cached_rec = prebuilt->fetch_cache[ - prebuilt->fetch_cache_first]; for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; -#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ - UNIV_MEM_ASSERT_RW(cached_rec - + templ->mysql_col_offset, - templ->mysql_col_len); -#endif - ut_memcpy(buf + templ->mysql_col_offset, - cached_rec + templ->mysql_col_offset, - templ->mysql_col_len); + row_sel_copy_cached_field_for_mysql( + buf, cached_rec, templ); /* Copy NULL bit of the current field from cached_rec to buf */ if (templ->mysql_null_bit_mask) { @@ -3153,17 +3197,24 @@ row_sel_pop_cached_row_for_mysql( & (byte)templ->mysql_null_bit_mask; } } + } else if (prebuilt->mysql_prefix_len > 63) { + /* The record is long. Copy it field by field, in case + there are some long VARCHAR column of which only a + small length is being used. */ + UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len); + + /* First copy the NULL bits. */ + ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len); + /* Then copy the requested fields. */ + + for (i = 0; i < prebuilt->n_template; i++) { + row_sel_copy_cached_field_for_mysql( + buf, cached_rec, prebuilt->mysql_template + i); + } + } else { + ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len); } - else { -#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ - UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache - [prebuilt->fetch_cache_first], - prebuilt->mysql_prefix_len); -#endif - ut_memcpy(buf, - prebuilt->fetch_cache[prebuilt->fetch_cache_first], - prebuilt->mysql_prefix_len); - } + prebuilt->n_fetch_cached--; prebuilt->fetch_cache_first++; @@ -3401,6 +3452,13 @@ row_search_for_mysql( return(DB_MISSING_HISTORY); } + if (dict_index_is_corrupted(index)) { +#ifdef UNIV_SYNC_DEBUG + ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); +#endif /* UNIV_SYNC_DEBUG */ + return(DB_CORRUPTION); + } + if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" diff --git a/storage/innobase/row/row0uins.c b/storage/innobase/row/row0uins.c index d25afed3840..4fa97c9355d 100644 --- a/storage/innobase/row/row0uins.c +++ b/storage/innobase/row/row0uins.c @@ -328,6 +328,8 @@ row_undo_ins( node->index = dict_table_get_next_index( dict_table_get_first_index(node->table)); + dict_table_skip_corrupt_index(node->index); + while (node->index != NULL) { dtuple_t* entry; ulint err; @@ -355,7 +357,7 @@ row_undo_ins( } } - node->index = dict_table_get_next_index(node->index); + dict_table_next_uncorrupted_index(node->index); } log_free_check(); diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index 2188fdeff49..b86ce9eeabd 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -573,6 +573,14 @@ row_undo_mod_upd_del_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; entry = row_build_index_entry(node->row, node->ext, @@ -626,6 +634,13 @@ row_undo_mod_del_mark_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; entry = row_build_index_entry(node->row, node->ext, @@ -677,6 +692,13 @@ row_undo_mod_upd_exist_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; if (row_upd_changes_ord_field_binary(node->index, node->update, @@ -859,6 +881,9 @@ row_undo_mod( node->index = dict_table_get_next_index( dict_table_get_first_index(node->table)); + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { err = row_undo_mod_upd_exist_sec(node, thr); diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 053b3513f1d..0c6036fe218 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -2305,6 +2305,13 @@ row_upd( while (node->index != NULL) { + /* Skip corrupted index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + log_free_check(); err = row_upd_sec_step(node, thr); |