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