diff options
author | Jimmy Yang <jimmy.yang@oracle.com> | 2011-08-16 18:07:59 -0700 |
---|---|---|
committer | Jimmy Yang <jimmy.yang@oracle.com> | 2011-08-16 18:07:59 -0700 |
commit | 95fa7fab3b70e5117d757d9df42ac9d7040fea03 (patch) | |
tree | f35296e1cd9a625708ab194372e0944f1309f78c /storage/innobase/include | |
parent | 887ac6774f9d33b64d7c316e9310038592ec6a83 (diff) | |
download | mariadb-git-95fa7fab3b70e5117d757d9df42ac9d7040fea03.tar.gz |
Fix bug #11830883, SUPPORT "CORRUPTED" BIT FOR INNODB TABLES AND INDEXES.
Also addressed issues in bug #11745133, where we could mark a table
corrupted instead of crashing the server when found a corrupted buffer/page
if the table created with innodb_file_per_table on.
Diffstat (limited to 'storage/innobase/include')
-rw-r--r-- | storage/innobase/include/buf0lru.h | 11 | ||||
-rw-r--r-- | storage/innobase/include/db0err.h | 1 | ||||
-rw-r--r-- | storage/innobase/include/dict0boot.h | 6 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 81 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.ic | 46 | ||||
-rw-r--r-- | storage/innobase/include/dict0mem.h | 14 | ||||
-rw-r--r-- | storage/innobase/include/dict0types.h | 3 | ||||
-rw-r--r-- | storage/innobase/include/srv0srv.h | 4 |
8 files changed, 150 insertions, 16 deletions
diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 74ef2d2dab7..eb40621abbe 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -203,6 +203,17 @@ void buf_LRU_stat_update(void); /*=====================*/ +/******************************************************************//** +Remove one page from LRU list and put it to free list */ +UNIV_INTERN +void +buf_LRU_free_one_page( +/*==================*/ + buf_page_t* bpage) /*!< in/out: block, must contain a file page and + be in a state where it can be freed; there + may or may not be a hash index to the page */ + __attribute__((nonnull)); + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /**********************************************************************//** Validates the LRU list. diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 28ef64500cc..415470b61b4 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -110,6 +110,7 @@ enum db_err { foreign keys as its prefix columns */ DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum limit */ + DB_INDEX_CORRUPT, /* we have corrupted index */ /* The following are partial failure codes */ DB_FAIL = 1000, diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h index 22df826da65..5d136862bc6 100644 --- a/storage/innobase/include/dict0boot.h +++ b/storage/innobase/include/dict0boot.h @@ -137,8 +137,10 @@ dict_create(void); header is created */ /*-------------------------------------------------------------*/ -/* The field number of the page number field in the sys_indexes table -clustered index */ +/* The field numbers in the SYS_TABLES clustered index */ +#define DICT_SYS_TABLES_TYPE_FIELD 5 + +/* The field numbers in the SYS_INDEXES clustered index */ #define DICT_SYS_INDEXES_PAGE_NO_FIELD 8 #define DICT_SYS_INDEXES_SPACE_NO_FIELD 7 #define DICT_SYS_INDEXES_TYPE_FIELD 6 diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index f979d0fcc96..93e9162dc87 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -585,6 +585,20 @@ dict_table_get_next_index( # define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index) #endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ + +/* Skip corrupted index */ +#define dict_table_skip_corrupt_index(index) \ + while (index && dict_index_is_corrupted(index)) { \ + index = dict_table_get_next_index(index); \ + } + +/* Get the next non-corrupt index */ +#define dict_table_next_uncorrupted_index(index) \ +do { \ + index = dict_table_get_next_index(index); \ + dict_table_skip_corrupt_index(index); \ +} while (0) + /********************************************************************//** Check whether the index is the clustered index. @return nonzero for clustered index, zero for other indexes */ @@ -593,7 +607,7 @@ ulint dict_index_is_clust( /*================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is unique. @return nonzero for unique index, zero for other indexes */ @@ -602,7 +616,7 @@ ulint dict_index_is_unique( /*=================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is the insert buffer tree. @return nonzero for insert buffer, zero for other indexes */ @@ -611,7 +625,7 @@ ulint dict_index_is_ibuf( /*===============*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is a secondary index or the insert buffer tree. @return nonzero for insert buffer, zero for other indexes */ @@ -620,7 +634,7 @@ ulint dict_index_is_sec_or_ibuf( /*======================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of user-defined columns in a table in the dictionary @@ -630,7 +644,8 @@ UNIV_INLINE ulint dict_table_get_n_user_cols( /*=======================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of system columns in a table in the dictionary cache. @return number of system (e.g., ROW_ID) columns of a table */ @@ -638,7 +653,8 @@ UNIV_INLINE ulint dict_table_get_n_sys_cols( /*======================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of all columns (also system) in a table in the dictionary cache. @@ -647,7 +663,8 @@ UNIV_INLINE ulint dict_table_get_n_cols( /*==================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); #ifdef UNIV_DEBUG /********************************************************************//** Gets the nth column of a table. @@ -1243,6 +1260,56 @@ void dict_close(void); /*============*/ +/**********************************************************************//** +Check whether the table is corrupted. +@return nonzero for corrupted table, zero for valid tables */ +UNIV_INLINE +ulint +dict_table_is_corrupted( +/*====================*/ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); + +/**********************************************************************//** +Check whether the index is corrupted. +@return nonzero for corrupted index, zero for valid indexes */ +UNIV_INLINE +ulint +dict_index_is_corrupted( +/*====================*/ + const dict_index_t* index) /*!< in: index */ + __attribute__((nonnull, pure, warn_unused_result)); + +/**********************************************************************//** +Flags an index and table corrupted both in the data dictionary cache +and in the system table SYS_INDEXES. */ +UNIV_INTERN +void +dict_set_corrupted( +/*===============*/ + dict_index_t* index) /*!< in/out: index */ + UNIV_COLD __attribute__((nonnull)); + +/**********************************************************************//** +Flags an index corrupted in the data dictionary cache only. This +is used mostly to mark a corrupted index when index's own dictionary +is corrupted, and we force to load such index for repair purpose */ +UNIV_INTERN +void +dict_set_corrupted_index_cache_only( +/*================================*/ + dict_index_t* index); /*!< in/out: index */ + +/**********************************************************************//** +Flags a table with specified space_id corrupted in the table dictionary +cache. +@return TRUE if successful */ +UNIV_INTERN +ibool +dict_set_corrupted_by_space( +/*========================*/ + ulint space_id); /*!< in: space ID */ + #ifndef UNIV_NONINL #include "dict0dict.ic" #endif diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 59811568556..ade9e627e29 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri #ifndef UNIV_HOTBACKUP #include "dict0load.h" #include "rem0types.h" +#include "srv0srv.h" /*********************************************************************//** Gets the minimum number of bytes per character. @@ -828,7 +829,7 @@ dict_table_check_if_in_cache_low( } /**********************************************************************//** -load a table into dictionary cache, ignore any error specified during load; +load a table into dictionary cache, ignore any error specified during load; @return table, NULL if not found */ UNIV_INLINE dict_table_t* @@ -872,6 +873,18 @@ dict_table_get_low( table = dict_table_check_if_in_cache_low(table_name); + if (table && table->corrupted) { + fprintf(stderr, "InnoDB: table"); + ut_print_name(stderr, NULL, TRUE, table->name); + if (srv_load_corrupted) { + fputs(" is corrupted, but" + " innodb_force_load_corrupted is set\n", stderr); + } else { + fputs(" is corrupted\n", stderr); + return(NULL); + } + } + if (table == NULL) { table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE); } @@ -937,4 +950,35 @@ dict_max_field_len_store_undo( return(prefix_len); } +/********************************************************************//** +Check whether the table is corrupted. +@return nonzero for corrupted table, zero for valid tables */ +UNIV_INLINE +ulint +dict_table_is_corrupted( +/*====================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return(UNIV_UNLIKELY(table->corrupted)); +} + +/********************************************************************//** +Check whether the index is corrupted. +@return nonzero for corrupted index, zero for valid indexes */ +UNIV_INLINE +ulint +dict_index_is_corrupted( +/*====================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return(UNIV_UNLIKELY((index->type & DICT_CORRUPT) + || (index->table && index->table->corrupted))); +} + #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 3a475fa85fc..9ded0dba39b 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -51,7 +51,12 @@ combination of types */ #define DICT_UNIQUE 2 /*!< unique index */ #define DICT_UNIVERSAL 4 /*!< index which can contain records from any other index */ -#define DICT_IBUF 8 /*!< insert buffer tree */ +#define DICT_IBUF 8 /*!< insert buffer tree */ +#define DICT_CORRUPT 16 /*!< bit to store the corrupted flag + in SYS_INDEXES.TYPE */ + +#define DICT_IT_BITS 5 /*!< number of bits used for + SYS_INDEXES.TYPE */ /* @} */ /** Types for a table object */ @@ -369,8 +374,9 @@ struct dict_index_struct{ /*!< space where the index tree is placed */ unsigned page:32;/*!< index tree root page number */ #endif /* !UNIV_HOTBACKUP */ - unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE, - DICT_UNIVERSAL, DICT_IBUF) */ + unsigned type:DICT_IT_BITS; + /*!< index type (DICT_CLUSTERED, DICT_UNIQUE, + DICT_UNIVERSAL, DICT_IBUF, DICT_CORRUPT) */ unsigned trx_id_offset:10;/*!< position of the trx id column in a clustered index record, if the fields before it are known to be of a fixed size, @@ -391,8 +397,6 @@ struct dict_index_struct{ /*!< TRUE if this index is marked to be dropped in ha_innobase::prepare_drop_index(), otherwise FALSE */ - unsigned corrupted:1; - /*!< TRUE if the index object is corrupted */ dict_field_t* fields; /*!< array of field descriptions */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index 8cbd7cd5783..f0a05a38070 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -51,7 +51,8 @@ be or-ed together */ enum dict_err_ignore { DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */ DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root - page is FIL_NUL or incorrect value */ + page is FIL_NULL or incorrect value */ + DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */ DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */ }; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 7a93548cb03..dfe7397d189 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -141,6 +141,10 @@ extern ulint srv_log_buffer_size; extern ulong srv_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +/* If this flag is TRUE, then we will load the indexes' (and tables') metadata +even if they are marked as "corrupted". Mostly it is for DBA to process +corrupted index and table */ +extern my_bool srv_load_corrupted; /* The sort order table of the MySQL latin1_swedish_ci character set collation */ |