diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2012-01-26 13:24:00 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2012-01-26 13:24:00 +0200 |
commit | d84c95579ba1eca2f9bf5b0be9f14040e4441227 (patch) | |
tree | 23b204cd9c0ed1020382a1acbc2b185390d338aa /storage | |
parent | 95646db77b7e1324c3febcccba02d727c7b9b1da (diff) | |
download | mariadb-git-d84c95579ba1eca2f9bf5b0be9f14040e4441227.tar.gz |
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
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/btr/btr0btr.c | 31 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 8 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.c | 4 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.c | 50 | ||||
-rw-r--r-- | storage/innobase/include/btr0btr.h | 22 | ||||
-rw-r--r-- | storage/innobase/include/mtr0log.ic | 3 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.c | 6 | ||||
-rw-r--r-- | storage/innobase/page/page0page.c | 5 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.c | 4 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.c | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0umod.c | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.c | 3 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.c | 3 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.c | 3 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rec.c | 5 |
15 files changed, 118 insertions, 35 deletions
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index b476167af29..88371208230 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/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 @@ -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)); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index e0aed5d7d21..1551aee5426 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/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 @@ -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; diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 68faafacb83..0721929abd3 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/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 @@ -615,6 +615,8 @@ buf_page_print( ulint old_checksum; ulint size = zip_size; + ut_ad(0); + if (!size) { size = UNIV_PAGE_SIZE; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index e68544bdfe8..cb8842dddfd 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -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" - "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); } } @@ -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); @@ -4219,6 +4248,7 @@ ibuf_restore_pos( fprintf(stderr, "InnoDB: ibuf tree ok\n"); fflush(stderr); + ut_ad(0); } return(FALSE); diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 71e772388a0..93b59fdfafb 100644 --- a/storage/innobase/include/btr0btr.h +++ b/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 @@ -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 */ diff --git a/storage/innobase/include/mtr0log.ic b/storage/innobase/include/mtr0log.ic index c670a0a8c82..6f871170099 100644 --- a/storage/innobase/include/mtr0log.ic +++ b/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 @@ -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); } } diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 714107304f7..d842817e6eb 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/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 @@ -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 */ diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c index 4858929082a..e250bb359fe 100644 --- a/storage/innobase/page/page0page.c +++ b/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 @@ -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)); diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 6e311ce2e80..67846ab6f69 100644 --- a/storage/innobase/row/row0ins.c +++ b/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 @@ -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; diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 20d45c1884d..0d1d3aad1c6 100644 --- a/storage/innobase/row/row0sel.c +++ b/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 @@ -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; diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index b86ce9eeabd..9597c476125 100644 --- a/storage/innobase/row/row0umod.c +++ b/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 @@ -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); diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 765233c8dab..cfa69b8c572 100644 --- a/storage/innobase/row/row0upd.c +++ b/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 @@ -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 diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index c7427abdddd..bda086f4778 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/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. @@ -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; diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index 02ec9f1c072..2370d3deab0 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/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 @@ -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); diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index 0bf41780fcc..786c7be36a4 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -1,6 +1,6 @@ /***************************************************************************** -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); } |