summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2011-05-24 11:41:31 +0300
committerMarko Mäkelä <marko.makela@oracle.com>2011-05-24 11:41:31 +0300
commit34e5d4740e9eddb13ea735c294152dffe34e9e06 (patch)
treeaddb9ec42342b916aba7fadeab3e2f5426405e1e
parent79f8d024b8fc73f310b255862d2797004b99871d (diff)
downloadmariadb-git-34e5d4740e9eddb13ea735c294152dffe34e9e06.tar.gz
Backport an InnoDB Bug #58815 (Bug #11765812) work-around from mysql-trunk:
------------------------------------------------------------ revno 2876.244.305 revision id marko.makela@oracle.com-20110413082211-e6ouhjz5rmqxcqap parent marko.makela@oracle.com-20110413075948-kvytmc37ye1nt7d9 committer Marko Mäkelä <marko.makela@oracle.com> branch nick 5.6-innodb timestamp Wed 2011-04-13 11:22:11 +0300 message: Suppress the Bug #58815 (Bug #11765812) assertion failure. buf_page_get_gen(): Introduce BUF_GET_POSSIBLY_FREED for suppressing the check that the file page must not have been freed. btr_estimate_n_rows_in_range_on_level(): Pass BUF_GET_POSSIBLY_FREED and explain in the comments why this is needed and why it should be mostly harmless to ignore the problem. If InnoDB had always initialized all unused fields in data files, no problem would exist. This change does not fix the bug, it just "shoots the messenger". rb:647 approved by Jimmy Yang
-rw-r--r--storage/innobase/btr/btr0cur.c18
-rw-r--r--storage/innobase/buf/buf0buf.c10
-rw-r--r--storage/innobase/include/buf0buf.h3
3 files changed, 23 insertions, 8 deletions
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index 9fa8fc663c9..2aff65e0bf6 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -3264,9 +3264,14 @@ btr_estimate_n_rows_in_range_on_level(
mtr_start(&mtr);
- /* fetch the page */
- block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
- &mtr);
+ /* Fetch the page. Because we are not holding the
+ index->lock, the tree may have changed and we may be
+ attempting to read a page that is no longer part of
+ the B-tree. We pass BUF_GET_POSSIBLY_FREED in order to
+ silence a debug assertion about this. */
+ block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
+ NULL, BUF_GET_POSSIBLY_FREED,
+ __FILE__, __LINE__, &mtr);
page = buf_block_get_frame(block);
@@ -3285,6 +3290,13 @@ btr_estimate_n_rows_in_range_on_level(
goto inexact;
}
+ /* It is possible but highly unlikely that the page was
+ originally written by an old version of InnoDB that did
+ not initialize FIL_PAGE_TYPE on other than B-tree pages.
+ For example, this could be an almost-empty BLOB page
+ that happens to contain the magic values in the fields
+ that we checked above. */
+
n_pages_read++;
if (page_no != slot1->page_no) {
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index cf5b90a2539..52358c52853 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -2747,6 +2747,7 @@ buf_page_get_gen(
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
+ case BUF_GET_POSSIBLY_FREED:
break;
default:
ut_error;
@@ -3062,7 +3063,10 @@ wait_until_unfixed:
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
buf_block_buf_fix_inc(block, file, line);
-
+#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
+ ut_a(mode == BUF_GET_POSSIBLY_FREED
+ || !block->page.file_page_was_freed);
+#endif
mutex_exit(&block->mutex);
/* Check if this is the first access to the page */
@@ -3075,10 +3079,6 @@ wait_until_unfixed:
buf_page_set_accessed_make_young(&block->page, access_time);
}
-#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
- ut_a(!block->page.file_page_was_freed);
-#endif
-
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 5771 || buf_validate());
ut_a(block->page.buf_fix_count > 0);
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 8fb008997ab..d83d484bace 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -53,6 +53,9 @@ Created 11/5/1995 Heikki Tuuri
/*!< Get the page only if it's in the
buffer pool, if not then set a watch
on the page. */
+#define BUF_GET_POSSIBLY_FREED 16
+ /*!< Like BUF_GET, but do not mind
+ if the file page has been freed. */
/* @} */
/** @name Modes for buf_page_get_known_nowait */
/* @{ */