diff options
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 18 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.c | 10 | ||||
-rw-r--r-- | storage/innobase/include/buf0buf.h | 3 |
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 */ /* @{ */ |