Many files:

  Try to skip over corrupt records in SELECT if innodb_force_recovery > 0; print more page hex dumps in CHECK TABLE
parent d0ee72c8
...@@ -2295,21 +2295,27 @@ btr_check_node_ptr( ...@@ -2295,21 +2295,27 @@ btr_check_node_ptr(
/**************************************************************** /****************************************************************
Checks the size and number of fields in a record based on the definition of Checks the size and number of fields in a record based on the definition of
the index. */ the index. */
static
ibool ibool
btr_index_rec_validate( btr_index_rec_validate(
/*====================*/ /*====================*/
/* out: TRUE if ok */ /* out: TRUE if ok */
rec_t* rec, /* in: index record */ rec_t* rec, /* in: index record */
dict_index_t* index) /* in: index */ dict_index_t* index, /* in: index */
ibool dump_on_error) /* in: TRUE if the function
should print hex dump of record
and page on error */
{ {
dtype_t* type; dtype_t* type;
byte* data; byte* data;
ulint len; ulint len;
ulint n; ulint n;
ulint i; ulint i;
page_t* page;
char err_buf[1000]; char err_buf[1000];
page = buf_frame_align(rec);
if (index->type & DICT_UNIVERSAL) { if (index->type & DICT_UNIVERSAL) {
/* The insert buffer index tree can contain records from any /* The insert buffer index tree can contain records from any
other index: we cannot check the number of fields or other index: we cannot check the number of fields or
...@@ -2321,11 +2327,22 @@ btr_index_rec_validate( ...@@ -2321,11 +2327,22 @@ btr_index_rec_validate(
n = dict_index_get_n_fields(index); n = dict_index_get_n_fields(index);
if (rec_get_n_fields(rec) != n) { if (rec_get_n_fields(rec) != n) {
fprintf(stderr, "Record has %lu fields, should have %lu\n", fprintf(stderr,
"InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
"InnoDB: has %lu fields, should have %lu\n",
index->name, index->table_name,
buf_frame_get_page_no(page), (ulint)(rec - page),
rec_get_n_fields(rec), n); rec_get_n_fields(rec), n);
if (!dump_on_error) {
return(FALSE);
}
buf_page_print(page);
rec_sprintf(err_buf, 900, rec); rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr, "InnoDB: corrupt record %s\n", err_buf);
return(FALSE); return(FALSE);
} }
...@@ -2338,11 +2355,23 @@ btr_index_rec_validate( ...@@ -2338,11 +2355,23 @@ btr_index_rec_validate(
if (len != UNIV_SQL_NULL && dtype_is_fixed_size(type) if (len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
&& len != dtype_get_fixed_size(type)) { && len != dtype_get_fixed_size(type)) {
fprintf(stderr, fprintf(stderr,
"Record field %lu len is %lu, should be %lu\n", "InnoDB: Record in index %s in table %s, page %lu, at offset %lu\n"
"InnoDB: field %lu len is %lu, should be %lu\n",
index->name, index->table_name,
buf_frame_get_page_no(page),
(ulint)(rec - page),
i, len, dtype_get_fixed_size(type)); i, len, dtype_get_fixed_size(type));
if (!dump_on_error) {
return(FALSE);
}
buf_page_print(page);
rec_sprintf(err_buf, 900, rec); rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr,
"InnoDB: corrupt record %s\n", err_buf);
return(FALSE); return(FALSE);
} }
...@@ -2373,12 +2402,13 @@ btr_index_page_validate( ...@@ -2373,12 +2402,13 @@ btr_index_page_validate(
rec = (&cur)->rec; rec = (&cur)->rec;
if (page_cur_is_after_last(&cur)) { if (page_cur_is_after_last(&cur)) {
break; break;
} }
if (!btr_index_rec_validate(rec, index)) { if (!btr_index_rec_validate(rec, index, TRUE)) {
ret = FALSE; return(FALSE);
} }
page_cur_move_to_next(&cur); page_cur_move_to_next(&cur);
...@@ -2435,25 +2465,26 @@ btr_validate_level( ...@@ -2435,25 +2465,26 @@ btr_validate_level(
index = UT_LIST_GET_FIRST(tree->tree_indexes); index = UT_LIST_GET_FIRST(tree->tree_indexes);
/* Now we are on the desired level */ /* Now we are on the desired level. Loop through the pages on that
level. */
loop: loop:
mtr_x_lock(dict_tree_get_lock(tree), &mtr); mtr_x_lock(dict_tree_get_lock(tree), &mtr);
/* Check ordering etc. of records */ /* Check ordering etc. of records */
if (!page_validate(page, index)) { if (!page_validate(page, index)) {
fprintf(stderr, "Error in page %lu in index %s\n", fprintf(stderr,
buf_frame_get_page_no(page), index->name); "InnoDB: Error in page %lu in index %s table %s, index tree level %lu\n",
buf_frame_get_page_no(page), index->name,
index->table_name, level);
ret = FALSE; ret = FALSE;
} } else if (level == 0) {
/* We are on level 0. Check that the records have the right
number of fields, and field lengths are right. */
if (level == 0) {
if (!btr_index_page_validate(page, index)) { if (!btr_index_page_validate(page, index)) {
fprintf(stderr,
"Error in page %lu in index %s, level %lu\n",
buf_frame_get_page_no(page), index->name,
level);
ret = FALSE; ret = FALSE;
} }
} }
...@@ -2476,14 +2507,17 @@ btr_validate_level( ...@@ -2476,14 +2507,17 @@ btr_validate_level(
UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) { UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on pages %lu and %lu in index %s\n", "InnoDB: Error on pages %lu and %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
right_page_no, right_page_no,
index->name); index->name, index->table_name);
fprintf(stderr, fprintf(stderr,
"InnoDB: records in wrong order on adjacent pages\n"); "InnoDB: records in wrong order on adjacent pages\n");
buf_page_print(page);
buf_page_print(right_page);
rec_sprintf(err_buf, 900, rec_sprintf(err_buf, 900,
page_rec_get_prev(page_get_supremum_rec(page))); page_rec_get_prev(page_get_supremum_rec(page)));
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr, "InnoDB: record %s\n", err_buf);
...@@ -2506,6 +2540,7 @@ btr_validate_level( ...@@ -2506,6 +2540,7 @@ btr_validate_level(
/* Check father node pointers */ /* Check father node pointers */
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr); node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
father_page = buf_frame_align(node_ptr);
if (btr_node_ptr_get_child_page_no(node_ptr) != if (btr_node_ptr_get_child_page_no(node_ptr) !=
buf_frame_get_page_no(page) buf_frame_get_page_no(page)
...@@ -2513,13 +2548,16 @@ btr_validate_level( ...@@ -2513,13 +2548,16 @@ btr_validate_level(
page_rec_get_prev(page_get_supremum_rec(page)), page_rec_get_prev(page_get_supremum_rec(page)),
&mtr)) { &mtr)) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on page %lu in index %s\n", "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
index->name); index->name, index->table_name);
fprintf(stderr, fprintf(stderr,
"InnoDB: node pointer to the page is wrong\n"); "InnoDB: node pointer to the page is wrong\n");
buf_page_print(father_page);
buf_page_print(page);
rec_sprintf(err_buf, 900, node_ptr); rec_sprintf(err_buf, 900, node_ptr);
fprintf(stderr, "InnoDB: node ptr %s\n", err_buf); fprintf(stderr, "InnoDB: node ptr %s\n", err_buf);
...@@ -2540,8 +2578,6 @@ btr_validate_level( ...@@ -2540,8 +2578,6 @@ btr_validate_level(
goto node_ptr_fails; goto node_ptr_fails;
} }
father_page = buf_frame_align(node_ptr);
if (btr_page_get_level(page, &mtr) > 0) { if (btr_page_get_level(page, &mtr) > 0) {
heap = mem_heap_create(256); heap = mem_heap_create(256);
...@@ -2555,9 +2591,12 @@ btr_validate_level( ...@@ -2555,9 +2591,12 @@ btr_validate_level(
if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) { if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on page %lu in index %s\n", "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
index->name); index->name, index->table_name);
buf_page_print(father_page);
buf_page_print(page);
fprintf(stderr, fprintf(stderr,
"InnoDB: Error: node ptrs differ on levels > 0\n"); "InnoDB: Error: node ptrs differ on levels > 0\n");
...@@ -2607,9 +2646,13 @@ btr_validate_level( ...@@ -2607,9 +2646,13 @@ btr_validate_level(
"InnoDB: node pointer to the right page is wrong\n"); "InnoDB: node pointer to the right page is wrong\n");
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on page %lu in index %s\n", "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
index->name); index->name, index->table_name);
buf_page_print(father_page);
buf_page_print(page);
buf_page_print(right_page);
} }
} else { } else {
right_father_page = buf_frame_align( right_father_page = buf_frame_align(
...@@ -2623,9 +2666,14 @@ btr_validate_level( ...@@ -2623,9 +2666,14 @@ btr_validate_level(
"InnoDB: node pointer 2 to the right page is wrong\n"); "InnoDB: node pointer 2 to the right page is wrong\n");
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on page %lu in index %s\n", "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
index->name); index->name, index->table_name);
buf_page_print(father_page);
buf_page_print(right_father_page);
buf_page_print(page);
buf_page_print(right_page);
} }
if (buf_frame_get_page_no(right_father_page) if (buf_frame_get_page_no(right_father_page)
...@@ -2636,9 +2684,14 @@ btr_validate_level( ...@@ -2636,9 +2684,14 @@ btr_validate_level(
"InnoDB: node pointer 3 to the right page is wrong\n"); "InnoDB: node pointer 3 to the right page is wrong\n");
fprintf(stderr, fprintf(stderr,
"InnoDB: Error on page %lu in index %s\n", "InnoDB: Error on page %lu in index %s table %s\n",
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
index->name); index->name, index->table_name);
buf_page_print(father_page);
buf_page_print(right_father_page);
buf_page_print(page);
buf_page_print(right_page);
} }
} }
} }
......
...@@ -399,6 +399,19 @@ btr_print_tree( ...@@ -399,6 +399,19 @@ btr_print_tree(
dict_tree_t* tree, /* in: tree */ dict_tree_t* tree, /* in: tree */
ulint width); /* in: print this many entries from start ulint width); /* in: print this many entries from start
and end */ and end */
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
ibool
btr_index_rec_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: index record */
dict_index_t* index, /* in: index */
ibool dump_on_error); /* in: TRUE if the function
should print hex dump of record
and page on error */
/****************************************************************** /******************************************************************
Checks the consistency of an index tree. */ Checks the consistency of an index tree. */
......
...@@ -298,6 +298,14 @@ btr_pcur_move_to_prev( ...@@ -298,6 +298,14 @@ btr_pcur_move_to_prev(
function may release the page latch */ function may release the page latch */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
/************************************************************* /*************************************************************
Moves the persistent cursor to the last record on the same page. */
UNIV_INLINE
void
btr_pcur_move_to_last_on_page(
/*==========================*/
btr_pcur_t* cursor, /* in: persistent cursor */
mtr_t* mtr); /* in: mtr */
/*************************************************************
Moves the persistent cursor to the next user record in the tree. If no user Moves the persistent cursor to the next user record in the tree. If no user
records are left, the cursor ends up 'after last in tree'. */ records are left, the cursor ends up 'after last in tree'. */
UNIV_INLINE UNIV_INLINE
......
...@@ -284,6 +284,24 @@ btr_pcur_move_to_prev_on_page( ...@@ -284,6 +284,24 @@ btr_pcur_move_to_prev_on_page(
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED; cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
} }
/*************************************************************
Moves the persistent cursor to the last record on the same page. */
UNIV_INLINE
void
btr_pcur_move_to_last_on_page(
/*==========================*/
btr_pcur_t* cursor, /* in: persistent cursor */
mtr_t* mtr) /* in: mtr */
{
UT_NOT_USED(mtr);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
page_cur_set_after_last(buf_frame_align(btr_pcur_get_rec(cursor)),
btr_pcur_get_page_cur(cursor));
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
}
/************************************************************* /*************************************************************
Moves the persistent cursor to the next user record in the tree. If no user Moves the persistent cursor to the next user record in the tree. If no user
records are left, the cursor ends up 'after last in tree'. */ records are left, the cursor ends up 'after last in tree'. */
......
...@@ -41,6 +41,7 @@ Created 5/24/1996 Heikki Tuuri ...@@ -41,6 +41,7 @@ Created 5/24/1996 Heikki Tuuri
which is referenced */ which is referenced */
#define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint #define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint
to a table failed */ to a table failed */
#define DB_CORRUPTION 39 /* data structure corruption noticed */
/* The following are partial failure codes */ /* The following are partial failure codes */
#define DB_FAIL 1000 #define DB_FAIL 1000
......
...@@ -1299,12 +1299,16 @@ page_rec_validate( ...@@ -1299,12 +1299,16 @@ page_rec_validate(
heap_no = rec_get_heap_no(rec); heap_no = rec_get_heap_no(rec);
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) { if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
fprintf(stderr, "Dir slot n owned too big %lu\n", n_owned); fprintf(stderr,
"InnoDB: Dir slot of rec %lu, n owned too big %lu\n",
(ulint)(rec - page), n_owned);
return(FALSE); return(FALSE);
} }
if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) { if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
fprintf(stderr, "Heap no too big %lu %lu\n", heap_no, fprintf(stderr,
"InnoDB: Heap no of rec %lu too big %lu %lu\n",
(ulint)(rec - page), heap_no,
page_header_get_field(page, PAGE_N_HEAP)); page_header_get_field(page, PAGE_N_HEAP));
return(FALSE); return(FALSE);
} }
...@@ -1340,7 +1344,7 @@ page_simple_validate( ...@@ -1340,7 +1344,7 @@ page_simple_validate(
if (n_slots > UNIV_PAGE_SIZE / 4) { if (n_slots > UNIV_PAGE_SIZE / 4) {
fprintf(stderr, fprintf(stderr,
"Nonsensical number %lu of page dir slots\n", n_slots); "InnoDB: Nonsensical number %lu of page dir slots\n", n_slots);
goto func_exit; goto func_exit;
} }
...@@ -1350,7 +1354,7 @@ page_simple_validate( ...@@ -1350,7 +1354,7 @@ page_simple_validate(
if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) { if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) {
fprintf(stderr, fprintf(stderr,
"Record heap and dir overlap on a page, heap top %lu, dir %lu\n", "InnoDB: Record heap and dir overlap on a page, heap top %lu, dir %lu\n",
(ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), (ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page),
(ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page)); (ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page));
...@@ -1372,7 +1376,7 @@ page_simple_validate( ...@@ -1372,7 +1376,7 @@ page_simple_validate(
if (rec > rec_heap_top) { if (rec > rec_heap_top) {
fprintf(stderr, fprintf(stderr,
"Record %lu is above rec heap top %lu\n", "InnoDB: Record %lu is above rec heap top %lu\n",
(ulint)(rec - page), (ulint)(rec_heap_top - page)); (ulint)(rec - page), (ulint)(rec_heap_top - page));
goto func_exit; goto func_exit;
...@@ -1383,7 +1387,7 @@ page_simple_validate( ...@@ -1383,7 +1387,7 @@ page_simple_validate(
if (rec_get_n_owned(rec) != own_count) { if (rec_get_n_owned(rec) != own_count) {
fprintf(stderr, fprintf(stderr,
"Wrong owned count %lu, %lu, rec %lu\n", "InnoDB: Wrong owned count %lu, %lu, rec %lu\n",
rec_get_n_owned(rec), own_count, rec_get_n_owned(rec), own_count,
(ulint)(rec - page)); (ulint)(rec - page));
...@@ -1392,7 +1396,7 @@ page_simple_validate( ...@@ -1392,7 +1396,7 @@ page_simple_validate(
if (page_dir_slot_get_rec(slot) != rec) { if (page_dir_slot_get_rec(slot) != rec) {
fprintf(stderr, fprintf(stderr,
"Dir slot does not point to right rec %lu\n", "InnoDB: Dir slot does not point to right rec %lu\n",
(ulint)(rec - page)); (ulint)(rec - page));
goto func_exit; goto func_exit;
...@@ -1414,7 +1418,7 @@ page_simple_validate( ...@@ -1414,7 +1418,7 @@ page_simple_validate(
if (rec_get_next_offs(rec) < FIL_PAGE_DATA if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) { || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"Next record offset nonsensical %lu for rec %lu\n", "InnoDB: Next record offset nonsensical %lu for rec %lu\n",
rec_get_next_offs(rec), rec_get_next_offs(rec),
(ulint)(rec - page)); (ulint)(rec - page));
...@@ -1425,7 +1429,7 @@ page_simple_validate( ...@@ -1425,7 +1429,7 @@ page_simple_validate(
if (count > UNIV_PAGE_SIZE) { if (count > UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"Page record list appears to be circular %lu\n", "InnoDB: Page record list appears to be circular %lu\n",
count); count);
goto func_exit; goto func_exit;
} }
...@@ -1435,19 +1439,19 @@ page_simple_validate( ...@@ -1435,19 +1439,19 @@ page_simple_validate(
} }
if (rec_get_n_owned(rec) == 0) { if (rec_get_n_owned(rec) == 0) {
fprintf(stderr, "n owned is zero in a supremum rec\n"); fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
goto func_exit; goto func_exit;
} }
if (slot_no != n_slots - 1) { if (slot_no != n_slots - 1) {
fprintf(stderr, "n slots wrong %lu, %lu\n", fprintf(stderr, "InnoDB: n slots wrong %lu, %lu\n",
slot_no, n_slots - 1); slot_no, n_slots - 1);
goto func_exit; goto func_exit;
} }
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
fprintf(stderr, "n recs wrong %lu %lu\n", fprintf(stderr, "InnoDB: n recs wrong %lu %lu\n",
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1); page_header_get_field(page, PAGE_N_RECS) + 2, count + 1);
goto func_exit; goto func_exit;
...@@ -1460,7 +1464,7 @@ page_simple_validate( ...@@ -1460,7 +1464,7 @@ page_simple_validate(
if (rec < page + FIL_PAGE_DATA if (rec < page + FIL_PAGE_DATA
|| rec >= page + UNIV_PAGE_SIZE) { || rec >= page + UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"Free list record has a nonsensical offset %lu\n", "InnoDB: Free list record has a nonsensical offset %lu\n",
(ulint)(rec - page)); (ulint)(rec - page));
goto func_exit; goto func_exit;
...@@ -1468,7 +1472,7 @@ page_simple_validate( ...@@ -1468,7 +1472,7 @@ page_simple_validate(
if (rec > rec_heap_top) { if (rec > rec_heap_top) {
fprintf(stderr, fprintf(stderr,
"Free list record %lu is above rec heap top %lu\n", "InnoDB: Free list record %lu is above rec heap top %lu\n",
(ulint)(rec - page), (ulint)(rec_heap_top - page)); (ulint)(rec - page), (ulint)(rec_heap_top - page));
goto func_exit; goto func_exit;
...@@ -1478,7 +1482,7 @@ page_simple_validate( ...@@ -1478,7 +1482,7 @@ page_simple_validate(
if (count > UNIV_PAGE_SIZE) { if (count > UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"Page free list appears to be circular %lu\n", "InnoDB: Page free list appears to be circular %lu\n",
count); count);
goto func_exit; goto func_exit;
} }
...@@ -1488,7 +1492,7 @@ page_simple_validate( ...@@ -1488,7 +1492,7 @@ page_simple_validate(
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) { if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
fprintf(stderr, "N heap is wrong %lu, %lu\n", fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
page_header_get_field(page, PAGE_N_HEAP), count + 1); page_header_get_field(page, PAGE_N_HEAP), count + 1);
goto func_exit; goto func_exit;
...@@ -1528,10 +1532,13 @@ page_validate( ...@@ -1528,10 +1532,13 @@ page_validate(
char err_buf[1000]; char err_buf[1000];
if (!page_simple_validate(page)) { if (!page_simple_validate(page)) {
fprintf(stderr,
"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
buf_frame_get_page_no(page), index->name,
index->table_name);
buf_page_print(page); buf_page_print(page);
fprintf(stderr, "Apparent corruption in a page in index %s\n",
index->name);
return(FALSE); return(FALSE);
} }
...@@ -1553,7 +1560,7 @@ page_validate( ...@@ -1553,7 +1560,7 @@ page_validate(
if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <= if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <=
page_dir_get_nth_slot(page, n_slots - 1))) { page_dir_get_nth_slot(page, n_slots - 1))) {
fprintf(stderr, fprintf(stderr,
"Record heap and dir overlap on a page in index %s, %lu, %lu\n", "InnoDB: Record heap and dir overlap on a page in index %s, %lu, %lu\n",
index->name, (ulint)page_header_get_ptr(page, PAGE_HEAP_TOP), index->name, (ulint)page_header_get_ptr(page, PAGE_HEAP_TOP),
(ulint)page_dir_get_nth_slot(page, n_slots - 1)); (ulint)page_dir_get_nth_slot(page, n_slots - 1));
...@@ -1581,10 +1588,14 @@ page_validate( ...@@ -1581,10 +1588,14 @@ page_validate(
if ((count >= 2) && (!page_cur_is_after_last(&cur))) { if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
if (!(1 == cmp_rec_rec(rec, old_rec, index))) { if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
fprintf(stderr, fprintf(stderr,
"Records in wrong order in index %s\n", "InnoDB: Records in wrong order on page %lu index %s table %s\n",
index->name); buf_frame_get_page_no(page),
index->name,
index->table_name);
rec_sprintf(err_buf, 900, old_rec); rec_sprintf(err_buf, 900, old_rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr,
"InnoDB: previous record %s\n", err_buf);
rec_sprintf(err_buf, 900, rec); rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr, "InnoDB: record %s\n", err_buf);
...@@ -1606,7 +1617,7 @@ page_validate( ...@@ -1606,7 +1617,7 @@ page_validate(
/* No other record may overlap this */ /* No other record may overlap this */
fprintf(stderr, fprintf(stderr,
"Record overlaps another in index %s \n", "InnoDB: Record overlaps another in index %s \n",
index->name); index->name);
goto func_exit; goto func_exit;
...@@ -1619,7 +1630,7 @@ page_validate( ...@@ -1619,7 +1630,7 @@ page_validate(
/* This is a record pointed to by a dir slot */ /* This is a record pointed to by a dir slot */
if (rec_get_n_owned(rec) != own_count) { if (rec_get_n_owned(rec) != own_count) {
fprintf(stderr, fprintf(stderr,
"Wrong owned count %lu, %lu, in index %s\n", "InnoDB: Wrong owned count %lu, %lu, in index %s\n",
rec_get_n_owned(rec), own_count, rec_get_n_owned(rec), own_count,
index->name); index->name);
...@@ -1628,7 +1639,7 @@ page_validate( ...@@ -1628,7 +1639,7 @@ page_validate(
if (page_dir_slot_get_rec(slot) != rec) { if (page_dir_slot_get_rec(slot) != rec) {
fprintf(stderr, fprintf(stderr,
"Dir slot does not point to right rec in %s\n", "InnoDB: Dir slot does not point to right rec in %s\n",
index->name); index->name);
goto func_exit; goto func_exit;
...@@ -1650,7 +1661,7 @@ page_validate( ...@@ -1650,7 +1661,7 @@ page_validate(
if (rec_get_next_offs(rec) < FIL_PAGE_DATA if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) { || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
fprintf(stderr, fprintf(stderr,
"Next record offset wrong %lu in index %s\n", "InnoDB: Next record offset wrong %lu in index %s\n",
rec_get_next_offs(rec), index->name); rec_get_next_offs(rec), index->name);
goto func_exit; goto func_exit;
...@@ -1663,19 +1674,20 @@ page_validate( ...@@ -1663,19 +1674,20 @@ page_validate(
} }
if (rec_get_n_owned(rec) == 0) { if (rec_get_n_owned(rec) == 0) {
fprintf(stderr, "n owned is zero in index %s\n", index->name); fprintf(stderr,
"InnoDB: n owned is zero in index %s\n", index->name);
goto func_exit; goto func_exit;
} }
if (slot_no != n_slots - 1) { if (slot_no != n_slots - 1) {
fprintf(stderr, "n slots wrong %lu %lu in index %s\n", fprintf(stderr, "InnoDB: n slots wrong %lu %lu in index %s\n",
slot_no, n_slots - 1, index->name); slot_no, n_slots - 1, index->name);
goto func_exit; goto func_exit;
} }
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
fprintf(stderr, "n recs wrong %lu %lu in index %s\n", fprintf(stderr, "InnoDB: n recs wrong %lu %lu in index %s\n",
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1, page_header_get_field(page, PAGE_N_RECS) + 2, count + 1,
index->name); index->name);
...@@ -1683,7 +1695,8 @@ page_validate( ...@@ -1683,7 +1695,8 @@ page_validate(
} }
if (data_size != page_get_data_size(page)) { if (data_size != page_get_data_size(page)) {
fprintf(stderr, "Summed data size %lu, returned by func %lu\n", fprintf(stderr,
"InnoDB: Summed data size %lu, returned by func %lu\n",
data_size, page_get_data_size(page)); data_size, page_get_data_size(page));
goto func_exit; goto func_exit;
} }
...@@ -1704,7 +1717,7 @@ page_validate( ...@@ -1704,7 +1717,7 @@ page_validate(
if (buf[offs + i] != 0) { if (buf[offs + i] != 0) {
fprintf(stderr, fprintf(stderr,
"Record overlaps another in free list, index %s \n", "InnoDB: Record overlaps another in free list, index %s \n",
index->name); index->name);
goto func_exit; goto func_exit;
...@@ -1718,9 +1731,11 @@ page_validate( ...@@ -1718,9 +1731,11 @@ page_validate(
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) { if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
fprintf(stderr, "N heap is wrong %lu %lu in index %s\n", fprintf(stderr,
"InnoDB: N heap is wrong %lu %lu in index %s\n",
page_header_get_field(page, PAGE_N_HEAP), count + 1, page_header_get_field(page, PAGE_N_HEAP), count + 1,
index->name); index->name);
goto func_exit;
} }
ret = TRUE; ret = TRUE;
...@@ -1728,6 +1743,15 @@ page_validate( ...@@ -1728,6 +1743,15 @@ page_validate(
func_exit: func_exit:
mem_heap_free(heap); mem_heap_free(heap);
if (ret == FALSE) {
fprintf(stderr,
"InnoDB: Apparent corruption in page %lu in index %s in table %s\n",
buf_frame_get_page_no(page), index->name,
index->table_name);
buf_page_print(page);
}
return(ret); return(ret);
} }
......
...@@ -2560,6 +2560,7 @@ row_search_for_mysql( ...@@ -2560,6 +2560,7 @@ row_search_for_mysql(
then this is set to FALSE */ then this is set to FALSE */
ibool success; ibool success;
ulint cnt = 0; ulint cnt = 0;
ulint next_offs;
mtr_t mtr; mtr_t mtr;
ut_ad(index && pcur && search_tuple); ut_ad(index && pcur && search_tuple);
...@@ -2916,7 +2917,59 @@ row_search_for_mysql( ...@@ -2916,7 +2917,59 @@ row_search_for_mysql(
goto next_rec; goto next_rec;
} }
ut_ad(page_rec_is_user_rec(rec)); /*-------------------------------------------------------------*/
/* Do sanity checks in case our cursor has bumped into page
corruption */
next_offs = rec_get_next_offs(rec);
if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: index %s, table %s. Run CHECK TABLE to table. You may need to\n"
"InnoDB: restore from a backup, or dump + drop + reimport the table.\n",
(ulint)(rec - buf_frame_align(rec)), next_offs,
buf_frame_get_page_no(rec), index->name,
index->table_name);
err = DB_CORRUPTION;
goto lock_wait_or_error;
} else {
/* The user may be dumping a corrupt table. Jump
over the corruption to recover as much as possible. */
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: index %s, table %s. We try to skip the rest of the page.\n",
(ulint)(rec - buf_frame_align(rec)), next_offs,
buf_frame_get_page_no(rec), index->name,
index->table_name);
btr_pcur_move_to_last_on_page(pcur, &mtr);
goto next_rec;
}
}
if (srv_force_recovery > 0) {
if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
FALSE)) {
fprintf(stderr,
"InnoDB: Index record corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: index %s, table %s. We try to skip the record.\n",
(ulint)(rec - buf_frame_align(rec)), next_offs,
buf_frame_get_page_no(rec), index->name,
index->table_name);
goto next_rec;
}
}
/*-------------------------------------------------------------*/
if (unique_search_from_clust_index && btr_pcur_get_up_match(pcur) if (unique_search_from_clust_index && btr_pcur_get_up_match(pcur)
== dtuple_get_n_fields(search_tuple)) { == dtuple_get_n_fields(search_tuple)) {
......
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