summaryrefslogtreecommitdiff
path: root/dict/dict0load.c
diff options
context:
space:
mode:
Diffstat (limited to 'dict/dict0load.c')
-rw-r--r--dict/dict0load.c94
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);