Commit d84c9557 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug #13413535 61104: INNODB: FAILING ASSERTION: PAGE_GET_N_RECS(PAGE) > 1

This fix does not remove the underlying cause of the assertion
failure. It just works around the problem, allowing a corrupted
secondary index to be fixed by DROP INDEX and CREATE INDEX (or in the
worst case, by re-creating the table).

ibuf_delete(): If the record to be purged is the last one in the page
or it is not delete-marked, refuse to purge it. Instead, write an
error message to the error log and let a debug assertion fail.

ibuf_set_del_mark(): If the record to be delete-marked is not found,
display some more information in the error log and let a debug
assertion fail.

row_undo_mod_del_unmark_sec_and_undo_update(),
row_upd_sec_index_entry(): Let a debug assertion fail when the record
to be delete-marked is not found.

buf_page_print(): Add ut_ad(0) so that corruption will be more
prominent in stress testing with debug binaries. Add ut_ad(0) here and
there where corruption is noticed.

btr_corruption_report(): Display some data on page_is_comp() mismatch.

btr_assert_not_corrupted(): A wrapper around btr_corruption_report().
Assert that page_is_comp() agrees with the table flags.

rb:911 approved by Inaam Rana
parent 95646db7
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -42,6 +42,27 @@ Created 6/2/1994 Heikki Tuuri
#include "ibuf0ibuf.h"
#include "trx0trx.h"
/**************************************************************//**
Report that an index page is corrupted. */
UNIV_INTERN
void
btr_corruption_report(
/*==================*/
const buf_block_t* block, /*!< in: corrupted block */
const dict_index_t* index) /*!< in: index tree */
{
fprintf(stderr, "InnoDB: flag mismatch in space %u page %u"
" index %s of table %s\n",
(unsigned) buf_block_get_space(block),
(unsigned) buf_block_get_page_no(block),
index->name, index->table_name);
buf_page_print(buf_block_get_frame(block), 0);
if (block->page.zip.data) {
buf_page_print(block->page.zip.data,
buf_block_get_zip_size(block));
}
}
#ifdef UNIV_BLOB_DEBUG
# include "srv0srv.h"
# include "ut0rbt.h"
......@@ -692,8 +713,7 @@ btr_root_block_get(
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
index, mtr);
ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
== dict_table_is_comp(index->table));
btr_assert_not_corrupted(block, index);
#ifdef UNIV_BTR_DEBUG
if (!dict_index_is_ibuf(index)) {
const page_t* root = buf_block_get_frame(block);
......@@ -1532,7 +1552,7 @@ btr_page_reorganize_low(
ibool success = FALSE;
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
btr_assert_not_corrupted(block, index);
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
......@@ -3164,7 +3184,8 @@ btr_compress(
block = btr_cur_get_block(cursor);
page = btr_cur_get_page(cursor);
index = btr_cur_get_index(cursor);
ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
btr_assert_not_corrupted(block, index);
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
MTR_MEMO_X_LOCK));
......
/*****************************************************************************
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -762,11 +762,11 @@ retry_page_get:
if (level != 0) {
/* x-latch the page */
page = btr_page_get(
buf_block_t* child_block = btr_block_get(
space, zip_size, page_no, RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));
page = buf_block_get_frame(child_block);
btr_assert_not_corrupted(child_block, index);
} else {
cursor->low_match = low_match;
cursor->low_bytes = low_bytes;
......
/*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -615,6 +615,8 @@ buf_page_print(
ulint old_checksum;
ulint size = zip_size;
ut_ad(0);
if (!size) {
size = UNIV_PAGE_SIZE;
}
......
......@@ -3880,6 +3880,7 @@ ibuf_insert_to_index_page_low(
fputs("InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
ut_ad(0);
}
/************************************************************************
......@@ -4073,6 +4074,11 @@ ibuf_set_del_mark(
TRUE, mtr);
}
} else {
const page_t* page
= page_cur_get_page(&page_cur);
const buf_block_t* block
= page_cur_get_block(&page_cur);
ut_print_timestamp(stderr);
fputs(" InnoDB: unable to find a record to delete-mark\n",
stderr);
......@@ -4081,10 +4087,14 @@ ibuf_set_del_mark(
fputs("\n"
"InnoDB: record ", stderr);
rec_print(stderr, page_cur_get_rec(&page_cur), index);
putc('\n', stderr);
fputs("\n"
fprintf(stderr, "\nspace %u offset %u"
" (%u records, index id %llu)\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
" to http://bugs.mysql.com\n",
(unsigned) buf_block_get_space(block),
(unsigned) buf_block_get_page_no(block),
(unsigned) page_get_n_recs(page),
btr_page_get_index_id(page));
ut_ad(0);
}
}
......@@ -4128,12 +4138,31 @@ ibuf_delete(
offsets = rec_get_offsets(
rec, index, offsets, ULINT_UNDEFINED, &heap);
/* Refuse to delete the last record. */
ut_a(page_get_n_recs(page) > 1);
if (page_get_n_recs(page) <= 1
|| !(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)))) {
/* Refuse to purge the last record or a
record that has not been marked for deletion. */
ut_print_timestamp(stderr);
fputs(" InnoDB: unable to purge a record\n",
stderr);
fputs("InnoDB: tuple ", stderr);
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
rec_print_new(stderr, rec, offsets);
fprintf(stderr, "\nspace %u offset %u"
" (%u records, index id %llu)\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n",
(unsigned) buf_block_get_space(block),
(unsigned) buf_block_get_page_no(block),
(unsigned) page_get_n_recs(page),
btr_page_get_index_id(page));
/* The record should have been marked for deletion. */
ut_ad(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)));
ut_ad(0);
return;
}
lock_update_delete(block, rec);
......@@ -4219,6 +4248,7 @@ ibuf_restore_pos(
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
ut_ad(0);
}
return(FALSE);
......
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -92,6 +92,26 @@ insert/delete buffer when the record is not in the buffer pool. */
buffer when the record is not in the buffer pool. */
#define BTR_DELETE 8192
/**************************************************************//**
Report that an index page is corrupted. */
UNIV_INTERN
void
btr_corruption_report(
/*==================*/
const buf_block_t* block, /*!< in: corrupted block */
const dict_index_t* index) /*!< in: index tree */
UNIV_COLD __attribute__((nonnull));
/** Assert that a B-tree page is not corrupted.
@param block buffer block containing a B-tree page
@param index the B-tree index */
#define btr_assert_not_corrupted(block, index) \
if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \
!= dict_table_is_comp((index)->table)) { \
btr_corruption_report(block, index); \
ut_error; \
}
#ifdef UNIV_BLOB_DEBUG
# include "ut0rbt.h"
/** An index->blobs entry for keeping track of off-page column references */
......
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -216,6 +216,7 @@ mlog_write_initial_log_record_fast(
"Please post a bug report to "
"bugs.mysql.com.\n",
type, offset, space);
ut_ad(0);
}
}
......
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -1690,7 +1690,7 @@ lock_rec_create(
page_no = buf_block_get_page_no(block);
page = block->frame;
ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
btr_assert_not_corrupted(block, index);
/* If rec is the supremum record, then we reset the gap and
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
......@@ -1795,6 +1795,7 @@ lock_rec_enqueue_waiting(
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n",
stderr);
ut_ad(0);
}
/* Enqueue the lock request that will wait to be granted */
......@@ -3795,6 +3796,7 @@ lock_table_enqueue_waiting(
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n",
stderr);
ut_ad(0);
}
/* Enqueue the lock request that will wait to be granted */
......
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -549,8 +549,7 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1);
}
ut_a((ibool)!!page_is_comp(new_page)
== dict_table_is_comp(index->table));
btr_assert_not_corrupted(new_block, index);
ut_a(page_is_comp(new_page) == page_rec_is_comp(rec));
ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint)
(page_is_comp(new_page) ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
......
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -950,7 +950,7 @@ row_ins_foreign_check_on_constraint(
fputs("\n"
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com\n", stderr);
ut_ad(0);
err = DB_SUCCESS;
goto nonstandard_exit_func;
......
/*****************************************************************************
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -2963,6 +2963,7 @@ row_sel_get_clust_rec_for_mysql(
fputs("\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
ut_ad(0);
}
clust_rec = NULL;
......
/*****************************************************************************
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -509,6 +509,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
fputs("\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
ut_ad(0);
break;
case ROW_FOUND:
btr_cur = btr_pcur_get_btr_cur(&pcur);
......
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -1617,6 +1617,7 @@ row_upd_sec_index_entry(
fputs("\n"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
ut_ad(0);
break;
case ROW_FOUND:
/* Delete mark the old index record; it can already be
......
/*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
......@@ -2415,6 +2415,7 @@ loop:
"InnoDB: Please submit a bug report"
" to http://bugs.mysql.com\n",
old_lsn, new_lsn);
ut_ad(0);
}
old_lsn = new_lsn;
......
/*****************************************************************************
Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -730,6 +730,7 @@ trx_purge_rseg_get_next_history_log(
"InnoDB: report, and submit it"
" to http://bugs.mysql.com\n",
(ulong) trx_sys->rseg_history_len);
ut_ad(0);
}
mutex_exit(&kernel_mutex);
......
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -1003,6 +1003,7 @@ trx_undo_update_rec_get_update(
fprintf(stderr, "\n"
"InnoDB: n_fields = %lu, i = %lu, ptr %p\n",
(ulong) n_fields, (ulong) i, ptr);
ut_ad(0);
*upd = NULL;
return(NULL);
}
......@@ -1513,6 +1514,7 @@ trx_undo_prev_version_build(
"InnoDB: record version ", stderr);
rec_print_new(stderr, rec, offsets);
putc('\n', stderr);
ut_ad(0);
return(DB_ERROR);
}
......@@ -1618,6 +1620,7 @@ trx_undo_prev_version_build(
(ullint) old_roll_ptr, (ullint) roll_ptr);
trx_purge_sys_print();
ut_ad(0);
return(DB_ERROR);
}
......
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