diff options
Diffstat (limited to 'dict/dict0load.c')
-rw-r--r-- | dict/dict0load.c | 94 |
1 files changed, 85 insertions, 9 deletions
diff --git a/dict/dict0load.c b/dict/dict0load.c index c5bd84f84ad..20b9caf7322 100644 --- a/dict/dict0load.c +++ b/dict/dict0load.c @@ -54,6 +54,11 @@ static const char* SYSTEM_TABLE_NAME[] = { "SYS_FOREIGN_COLS", "SYS_STATS" }; + +/* If this flag is TRUE, then we will load the cluster index's (and tables') +metadata even if it is marked as "corrupted". */ +UNIV_INTERN my_bool srv_load_corrupted = FALSE; + /****************************************************************//** Compare the name of an index column. @return TRUE if the i'th column of index is 'name'. */ @@ -1396,6 +1401,9 @@ err_len: goto err_len; } type = mach_read_from_4(field); + if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) { + return("unknown SYS_INDEXES.TYPE bits"); + } field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len); if (UNIV_UNLIKELY(len != 4)) { @@ -1495,16 +1503,47 @@ dict_load_indexes( goto next_rec; } else if (err_msg) { fprintf(stderr, "InnoDB: %s\n", err_msg); + if (ignore_err & DICT_ERR_IGNORE_CORRUPT) { + goto next_rec; + } error = DB_CORRUPTION; goto func_exit; } ut_ad(index); + /* Check whether the index is corrupted */ + if (dict_index_is_corrupted(index)) { + ut_print_timestamp(stderr); + fputs(" InnoDB: ", stderr); + dict_index_name_print(stderr, NULL, index); + fputs(" is corrupted\n", stderr); + + if (!srv_load_corrupted + && !(ignore_err & DICT_ERR_IGNORE_CORRUPT) + && dict_index_is_clust(index)) { + dict_mem_index_free(index); + + error = DB_INDEX_CORRUPT; + goto func_exit; + } else { + /* We will load the index if + 1) srv_load_corrupted is TRUE + 2) ignore_err is set with + DICT_ERR_IGNORE_CORRUPT + 3) if the index corrupted is a secondary + index */ + ut_print_timestamp(stderr); + fputs(" InnoDB: load corrupted index ", stderr); + dict_index_name_print(stderr, NULL, index); + putc('\n', stderr); + } + } + /* We check for unsupported types first, so that the subsequent checks are relevant for the supported types. */ - if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) { - + if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE + | DICT_CORRUPT)) { fprintf(stderr, "InnoDB: Error: unknown type %lu" " of index %s of table %s\n", @@ -1525,9 +1564,14 @@ dict_load_indexes( /* If caller can tolerate this error, we will continue to load the index and let caller deal with this error. However - mark the index and table corrupted */ - index->corrupted = TRUE; - table->corrupted = TRUE; + mark the index and table corrupted. We + only need to mark such in the index + dictionary cache for such metadata corruption, + since we would always be able to set it + when loading the dictionary cache */ + dict_set_corrupted_index_cache_only( + index, table); + fprintf(stderr, "InnoDB: Index is corrupt but forcing" " load into data dictionary\n"); @@ -1567,9 +1611,10 @@ corrupted: index->name, table->name); /* If the force recovery flag is set, and - if the failed index is not the primary index, we - will continue and open other indexes */ - if (srv_force_recovery + if the failed index is not the clustered index, + we will continue and open other indexes */ + if ((srv_force_recovery + || srv_load_corrupted) && !dict_index_is_clust(index)) { error = DB_SUCCESS; goto next_rec; @@ -1884,6 +1929,30 @@ err_exit: err = dict_load_indexes(table, heap, ignore_err); + if (err == DB_INDEX_CORRUPT) { + /* Refuse to load the table if the table has a corrupted + cluster index */ + if (!srv_load_corrupted) { + fprintf(stderr, "InnoDB: Error: Load table "); + ut_print_name(stderr, NULL, TRUE, table->name); + fprintf(stderr, " failed, the table has corrupted" + " clustered indexes. Turn on" + " 'innodb_force_load_corrupted'" + " to drop it\n"); + + dict_table_remove_from_cache(table); + table = NULL; + goto func_exit; + } else { + dict_index_t* clust_index; + clust_index = dict_table_get_first_index(table); + + if (dict_index_is_corrupted(clust_index)) { + table->corrupted = TRUE; + } + } + } + /* Initialize table foreign_child value. Its value could be changed when dict_load_foreigns() is called below */ table->fk_max_recusive_level = 0; @@ -1910,9 +1979,15 @@ err_exit: index = dict_table_get_first_index(table); if (!srv_force_recovery || !index - || !dict_index_is_clust(index)) { + || !dict_index_is_clust(index)) { dict_table_remove_from_cache(table); table = NULL; + } else if (dict_index_is_corrupted(index)) { + + /* It is possible we force to load a corrupted + clustered index if srv_load_corrupted is set. + Mark the table as corrupted in this case */ + table->corrupted = TRUE; } } #if 0 @@ -1939,6 +2014,7 @@ err_exit: mutex_exit(&dict_foreign_err_mutex); } #endif /* 0 */ +func_exit: mem_heap_free(heap); return(table); |