Commit 3fa4aaac authored by Jimmy Yang's avatar Jimmy Yang

Fix bug #11796673 address backward compatibility on index with

large prefix (>=768). Table with such large prefix index will not
be loaded into memory (for its metadata), unless innodb_force_recovery
is on.

rb://604 Approved by Marko
parent a14a9dc3
...@@ -454,9 +454,11 @@ dict_load_report_deleted_index( ...@@ -454,9 +454,11 @@ dict_load_report_deleted_index(
/************************************************************************ /************************************************************************
Loads definitions for index fields. */ Loads definitions for index fields. */
static static
void ulint
dict_load_fields( dict_load_fields(
/*=============*/ /*=============*/
/* out: DB_SUCCESS if ok, DB_CORRUPTION
if failed */
dict_table_t* table, /* in: table */ dict_table_t* table, /* in: table */
dict_index_t* index, /* in: index whose fields to load */ dict_index_t* index, /* in: index whose fields to load */
mem_heap_t* heap) /* in: memory heap for temporary storage */ mem_heap_t* heap) /* in: memory heap for temporary storage */
...@@ -474,6 +476,7 @@ dict_load_fields( ...@@ -474,6 +476,7 @@ dict_load_fields(
byte* buf; byte* buf;
ulint i; ulint i;
mtr_t mtr; mtr_t mtr;
ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
...@@ -535,6 +538,26 @@ dict_load_fields( ...@@ -535,6 +538,26 @@ dict_load_fields(
field = rec_get_nth_field_old(rec, 4, &len); field = rec_get_nth_field_old(rec, 4, &len);
if (prefix_len >= DICT_MAX_INDEX_COL_LEN) {
fprintf(stderr, "InnoDB: Error: load index"
" '%s' failed.\n"
"InnoDB: index field '%s' has a prefix"
" length of %lu bytes,\n"
"InnoDB: which exceeds the"
" maximum limit of %lu bytes.\n"
"InnoDB: Please use server that"
" supports long index prefix\n"
"InnoDB: or turn on"
" innodb_force_recovery to load"
" the table\n",
index->name, mem_heap_strdupl(
heap, (char*) field, len),
(ulong) prefix_len,
(ulong) (DICT_MAX_INDEX_COL_LEN - 1));
error = DB_CORRUPTION;
goto func_exit;
}
dict_mem_index_add_field(index, dict_mem_index_add_field(index,
mem_heap_strdupl(heap, mem_heap_strdupl(heap,
(char*) field, len), (char*) field, len),
...@@ -543,8 +566,10 @@ dict_load_fields( ...@@ -543,8 +566,10 @@ dict_load_fields(
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
func_exit:
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
return(error);
} }
/************************************************************************ /************************************************************************
...@@ -701,10 +726,28 @@ dict_load_indexes( ...@@ -701,10 +726,28 @@ dict_load_indexes(
space, type, n_fields); space, type, n_fields);
index->id = id; index->id = id;
dict_load_fields(table, index, heap); error = dict_load_fields(table, index, heap);
if (error != DB_SUCCESS) {
fprintf(stderr, "InnoDB: Error: load index '%s'"
" for table '%s' failed\n",
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
&& !(index->type & DICT_CLUSTERED)) {
error = DB_SUCCESS;
goto next_rec;
} else {
goto func_exit;
}
}
dict_index_add_to_cache(table, index, page_no); dict_index_add_to_cache(table, index, page_no);
} }
next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
...@@ -881,9 +924,18 @@ err_exit: ...@@ -881,9 +924,18 @@ err_exit:
} else { } else {
table->fk_max_recusive_level = 0; table->fk_max_recusive_level = 0;
} }
} else if (!srv_force_recovery) { } else {
dict_table_remove_from_cache(table); dict_index_t* index;
table = NULL;
/* Make sure that at least the clustered index was loaded.
Otherwise refuse to load the table */
index = dict_table_get_first_index(table);
if (!srv_force_recovery || !index
|| !(index->type & DICT_CLUSTERED)) {
dict_table_remove_from_cache(table);
table = NULL;
}
} }
#if 0 #if 0
if (err != DB_SUCCESS && table != NULL) { if (err != DB_SUCCESS && table != NULL) {
......
...@@ -553,9 +553,10 @@ dict_load_columns( ...@@ -553,9 +553,10 @@ dict_load_columns(
} }
/********************************************************************//** /********************************************************************//**
Loads definitions for index fields. */ Loads definitions for index fields.
@return DB_SUCCESS if ok, DB_CORRUPTION if failed */
static static
void ulint
dict_load_fields( dict_load_fields(
/*=============*/ /*=============*/
dict_index_t* index, /*!< in: index whose fields to load */ dict_index_t* index, /*!< in: index whose fields to load */
...@@ -574,6 +575,7 @@ dict_load_fields( ...@@ -574,6 +575,7 @@ dict_load_fields(
byte* buf; byte* buf;
ulint i; ulint i;
mtr_t mtr; mtr_t mtr;
ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex))); ut_ad(mutex_own(&(dict_sys->mutex)));
...@@ -640,6 +642,26 @@ dict_load_fields( ...@@ -640,6 +642,26 @@ dict_load_fields(
field = rec_get_nth_field_old(rec, 4, &len); field = rec_get_nth_field_old(rec, 4, &len);
if (prefix_len >= DICT_MAX_INDEX_COL_LEN) {
fprintf(stderr, "InnoDB: Error: load index"
" '%s' failed.\n"
"InnoDB: index field '%s' has a prefix"
" length of %lu bytes,\n"
"InnoDB: which exceeds the"
" maximum limit of %lu bytes.\n"
"InnoDB: Please use server that"
" supports long index prefix\n"
"InnoDB: or turn on"
" innodb_force_recovery to load"
" the table\n",
index->name, mem_heap_strdupl(
heap, (char*) field, len),
(ulong) prefix_len,
(ulong) (DICT_MAX_INDEX_COL_LEN - 1));
error = DB_CORRUPTION;
goto func_exit;
}
dict_mem_index_add_field(index, dict_mem_index_add_field(index,
mem_heap_strdupl(heap, mem_heap_strdupl(heap,
(char*) field, len), (char*) field, len),
...@@ -649,8 +671,10 @@ next_rec: ...@@ -649,8 +671,10 @@ next_rec:
btr_pcur_move_to_next_user_rec(&pcur, &mtr); btr_pcur_move_to_next_user_rec(&pcur, &mtr);
} }
func_exit:
btr_pcur_close(&pcur); btr_pcur_close(&pcur);
mtr_commit(&mtr); mtr_commit(&mtr);
return(error);
} }
/********************************************************************//** /********************************************************************//**
...@@ -801,7 +825,25 @@ dict_load_indexes( ...@@ -801,7 +825,25 @@ dict_load_indexes(
space, type, n_fields); space, type, n_fields);
index->id = id; index->id = id;
dict_load_fields(index, heap); error = dict_load_fields(index, heap);
if (error != DB_SUCCESS) {
fprintf(stderr, "InnoDB: Error: load index '%s'"
" for table '%s' failed\n",
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
&& !(index->type & DICT_CLUSTERED)) {
error = DB_SUCCESS;
goto next_rec;
} else {
goto func_exit;
}
}
error = dict_index_add_to_cache(table, index, page_no, error = dict_index_add_to_cache(table, index, page_no,
FALSE); FALSE);
/* The data dictionary tables should never contain /* The data dictionary tables should never contain
...@@ -1027,9 +1069,18 @@ err_exit: ...@@ -1027,9 +1069,18 @@ err_exit:
} else { } else {
table->fk_max_recusive_level = 0; table->fk_max_recusive_level = 0;
} }
} else if (!srv_force_recovery) { } else {
dict_table_remove_from_cache(table); dict_index_t* index;
table = NULL;
/* Make sure that at least the clustered index was loaded.
Otherwise refuse to load the table */
index = dict_table_get_first_index(table);
if (!srv_force_recovery || !index
|| !(index->type & DICT_CLUSTERED)) {
dict_table_remove_from_cache(table);
table = NULL;
}
} }
#if 0 #if 0
if (err != DB_SUCCESS && table != NULL) { if (err != DB_SUCCESS && table != NULL) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment