Skip to content

Commit

Permalink
Bug #13413535 61104: INNODB: FAILING ASSERTION: PAGE_GET_N_RECS(PAGE)…
Browse files Browse the repository at this point in the history
… > 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
--BZR--
revision-id: marko.makela@oracle.com-20120126112400-lmni2h5frvv5v54z
property-branch-nick: mysql-5.5
testament3-sha1: b8e923031f7ecc314ac2901f843a844406571949
  • Loading branch information
Marko Mäkelä committed Jan 26, 2012
1 parent 46765cd commit a7c7dd9
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 35 deletions.
31 changes: 26 additions & 5 deletions storage/innobase/btr/btr0btr.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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));
Expand Down
8 changes: 4 additions & 4 deletions storage/innobase/btr/btr0cur.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -762,11 +762,11 @@ btr_cur_search_to_nth_level(

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;
Expand Down
4 changes: 3 additions & 1 deletion storage/innobase/buf/buf0buf.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -615,6 +615,8 @@ buf_page_print(
ulint old_checksum;
ulint size = zip_size;

ut_ad(0);

if (!size) {
size = UNIV_PAGE_SIZE;
}
Expand Down
50 changes: 40 additions & 10 deletions storage/innobase/ibuf/ibuf0ibuf.c
Expand Up @@ -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);
}

/************************************************************************
Expand Down Expand Up @@ -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);
Expand All @@ -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"
"InnoDB: Submit a detailed bug report"
" to http://bugs.mysql.com\n", stderr);
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));
ut_ad(0);
}
}
Expand Down Expand Up @@ -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);

/* The record should have been marked for deletion. */
ut_ad(REC_INFO_DELETED_FLAG
& rec_get_info_bits(rec, page_is_comp(page)));
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));

ut_ad(0);
return;
}

lock_update_delete(block, rec);

Expand Down Expand Up @@ -4219,6 +4248,7 @@ ibuf_restore_pos(

fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
ut_ad(0);
}

return(FALSE);
Expand Down
22 changes: 21 additions & 1 deletion storage/innobase/include/btr0btr.h
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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 */
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/include/mtr0log.ic
@@ -1,6 +1,6 @@
/*****************************************************************************

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
Expand Down Expand Up @@ -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);
}
}

Expand Down
6 changes: 4 additions & 2 deletions storage/innobase/lock/lock0lock.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
5 changes: 2 additions & 3 deletions storage/innobase/page/page0page.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions storage/innobase/row/row0ins.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/row/row0sel.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/row/row0umod.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/row/row0upd.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/srv/srv0srv.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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.
Expand Down Expand Up @@ -2415,6 +2415,7 @@ srv_error_monitor_thread(
"InnoDB: Please submit a bug report"
" to http://bugs.mysql.com\n",
old_lsn, new_lsn);
ut_ad(0);
}

old_lsn = new_lsn;
Expand Down
3 changes: 2 additions & 1 deletion storage/innobase/trx/trx0purge.c
@@ -1,6 +1,6 @@
/*****************************************************************************
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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit a7c7dd9

Please sign in to comment.