summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0buf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0buf.cc')
-rw-r--r--storage/innobase/buf/buf0buf.cc411
1 files changed, 187 insertions, 224 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 60ede653bee..736aa32a4c2 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -67,6 +67,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0dump.h"
#include <map>
#include <sstream>
+#include "log.h"
using st_::span;
@@ -583,9 +584,6 @@ bool buf_is_zeroes(span<const byte> buf)
bool buf_page_is_corrupted(bool check_lsn, const byte *read_buf,
uint32_t fsp_flags)
{
-#ifndef UNIV_INNOCHECKSUM
- DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", return(true); );
-#endif
if (fil_space_t::full_crc32(fsp_flags)) {
bool compressed = false, corrupted = false;
const uint size = buf_page_full_crc32_size(
@@ -2197,6 +2195,7 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr)
++buf_pool.stat.n_page_gets;
const page_id_t page_id(space->id, page);
buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(page_id.fold());
+ uint32_t fix;
buf_block_t *block;
{
transactional_shared_lock_guard<page_hash_latch> g
@@ -2209,7 +2208,13 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr)
/* To avoid a deadlock with buf_LRU_free_page() of some other page
and buf_page_write_complete() of this page, we must not wait for a
page latch while holding a page_hash latch. */
- block->page.fix();
+ fix= block->page.fix();
+ }
+
+ if (UNIV_UNLIKELY(fix < buf_page_t::UNFIXED))
+ {
+ block->page.unfix();
+ return;
}
block->page.lock.x_lock();
@@ -2402,6 +2407,7 @@ buf_zip_decompress(
case FIL_PAGE_RTREE:
if (page_zip_decompress(&block->page.zip,
block->page.frame, TRUE)) {
+func_exit:
if (space) {
space->release();
}
@@ -2421,11 +2427,7 @@ buf_zip_decompress(
case FIL_PAGE_TYPE_ZBLOB2:
/* Copy to uncompressed storage. */
memcpy(block->page.frame, frame, block->zip_size());
- if (space) {
- space->release();
- }
-
- return(TRUE);
+ goto func_exit;
}
ib::error() << "Unknown compressed page type "
@@ -2440,12 +2442,6 @@ err_exit:
}
if (space) {
- if (encrypted) {
- dict_set_encrypted_by_space(space);
- } else {
- dict_set_corrupted_by_space(space);
- }
-
space->release();
}
@@ -2458,7 +2454,7 @@ err_exit:
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
-BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
+BUF_PEEK_IF_IN_POOL, or BUF_GET_IF_IN_POOL_OR_WATCH
@param[in] mtr mini-transaction
@param[out] err DB_SUCCESS or error code
@param[in] allow_ibuf_merge Allow change buffer merge to happen
@@ -2481,8 +2477,8 @@ buf_page_get_low(
unsigned access_time;
ulint retries = 0;
- ut_ad((mtr == NULL) == (mode == BUF_EVICT_IF_IN_POOL));
ut_ad(!mtr || mtr->is_active());
+ ut_ad(mtr || mode == BUF_PEEK_IF_IN_POOL);
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_SX_LATCH)
@@ -2499,24 +2495,15 @@ buf_page_get_low(
#ifdef UNIV_DEBUG
switch (mode) {
- case BUF_EVICT_IF_IN_POOL:
- /* After DISCARD TABLESPACE, the tablespace would not exist,
- but in IMPORT TABLESPACE, PageConverter::operator() must
- replace any old pages, which were not evicted during DISCARD.
- Skip the assertion on space_page_size. */
- break;
case BUF_PEEK_IF_IN_POOL:
case BUF_GET_IF_IN_POOL:
/* The caller may pass a dummy page size,
because it does not really matter. */
break;
default:
- ut_error;
+ MY_ASSERT_UNREACHABLE();
case BUF_GET_POSSIBLY_FREED:
break;
- case BUF_GET_NO_LATCH:
- ut_ad(rw_latch == RW_NO_LATCH);
- /* fall through */
case BUF_GET:
case BUF_GET_IF_IN_POOL_OR_WATCH:
ut_ad(!mtr->is_freeing_tree());
@@ -2573,7 +2560,6 @@ loop:
switch (mode) {
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
- case BUF_EVICT_IF_IN_POOL:
return nullptr;
case BUF_GET_IF_IN_POOL_OR_WATCH:
/* We cannot easily use a memory transaction here. */
@@ -2603,62 +2589,15 @@ loop:
checksum cannot be decypted. */
if (dberr_t local_err = buf_read_page(page_id, zip_size)) {
- if (mode == BUF_GET_POSSIBLY_FREED) {
- if (err) {
- *err = local_err;
- }
- return nullptr;
- } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
- ++retries;
- DBUG_EXECUTE_IF("innodb_page_corruption_retries",
+ if (mode != BUF_GET_POSSIBLY_FREED
+ && retries++ < BUF_PAGE_READ_MAX_RETRIES) {
+ DBUG_EXECUTE_IF("intermittent_read_failure",
retries = BUF_PAGE_READ_MAX_RETRIES;);
} else {
if (err) {
*err = local_err;
}
- /* Pages whose encryption key is unavailable or the
- configured key, encryption algorithm or encryption
- method are incorrect are marked as encrypted in
- buf_page_check_corrupt(). Unencrypted page could be
- corrupted in a way where the key_id field is
- nonzero. There is no checksum on field
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION. */
- switch (local_err) {
- case DB_PAGE_CORRUPTED:
- if (!srv_force_recovery) {
- break;
- }
- /* fall through */
- case DB_DECRYPTION_FAILED:
- return nullptr;
- default:
- break;
- }
-
- /* Try to set table as corrupted instead of
- asserting. */
- if (page_id.space() == TRX_SYS_SPACE) {
- } else if (page_id.space() == SRV_TMP_SPACE_ID) {
- } else if (fil_space_t* space
- = fil_space_t::get(page_id.space())) {
- bool set = dict_set_corrupted_by_space(space);
- space->release();
- if (set) {
- return nullptr;
- }
- }
-
- if (local_err == DB_IO_ERROR) {
- return nullptr;
- }
-
- ib::fatal() << "Unable to read page " << page_id
- << " into the buffer pool after "
- << BUF_PAGE_READ_MAX_RETRIES
- << ". The most probable cause"
- " of this error may be that the"
- " table has been corrupted."
- " See https://mariadb.com/kb/en/library/innodb-recovery-modes/";
+ return nullptr;
}
} else {
buf_read_ahead_random(page_id, zip_size, ibuf_inside(mtr));
@@ -2673,10 +2612,14 @@ got_block:
ut_ad(state > buf_page_t::FREED);
if (state > buf_page_t::READ_FIX && state < buf_page_t::WRITE_FIX) {
- if (mode == BUF_PEEK_IF_IN_POOL
- || mode == BUF_EVICT_IF_IN_POOL) {
+ if (mode == BUF_PEEK_IF_IN_POOL) {
ignore_block:
+ ut_ad(mode == BUF_GET_POSSIBLY_FREED
+ || mode == BUF_PEEK_IF_IN_POOL);
block->unfix();
+ if (err) {
+ *err = DB_CORRUPTION;
+ }
return nullptr;
}
@@ -2702,46 +2645,29 @@ ignore_block:
*err = DB_PAGE_CORRUPTED;
}
- if (page_id.space() == TRX_SYS_SPACE) {
- } else if (page_id.space() == SRV_TMP_SPACE_ID) {
- } else if (fil_space_t* space =
- fil_space_t::get(page_id.space())) {
- bool set = dict_set_corrupted_by_space(space);
- space->release();
- if (set) {
- return nullptr;
- }
- }
-
- ib::fatal() << "Unable to read page " << page_id
- << " into the buffer pool after "
- << BUF_PAGE_READ_MAX_RETRIES
- << ". The most probable cause"
- " of this error may be that the"
- " table has been corrupted."
- " See https://mariadb.com/kb/en/library/innodb-recovery-modes/";
- }
- } else if (mode == BUF_PEEK_IF_IN_POOL) {
- if (UNIV_UNLIKELY(!block->page.frame)) {
- /* This mode is only used for dropping an
- adaptive hash index. There cannot be an
- adaptive hash index for a compressed-only page. */
- goto ignore_block;
+ return nullptr;
}
- } else if (mode == BUF_EVICT_IF_IN_POOL) {
+ } else if (mode != BUF_PEEK_IF_IN_POOL) {
+ } else if (!mtr) {
ut_ad(!block->page.oldest_modification());
mysql_mutex_lock(&buf_pool.mutex);
block->unfix();
- if (!buf_LRU_free_page(&block->page, true)) {
+ if (!buf_LRU_free_page(&block->page, true)) {
ut_ad(0);
}
mysql_mutex_unlock(&buf_pool.mutex);
return nullptr;
+ } else if (UNIV_UNLIKELY(!block->page.frame)) {
+ /* The BUF_PEEK_IF_IN_POOL mode is mainly used for dropping an
+ adaptive hash index. There cannot be an
+ adaptive hash index for a compressed-only page. */
+ goto ignore_block;
}
- ut_ad(mode == BUF_GET_IF_IN_POOL || block->zip_size() == zip_size);
+ ut_ad(mode == BUF_GET_IF_IN_POOL || mode == BUF_PEEK_IF_IN_POOL
+ || block->zip_size() == zip_size);
if (UNIV_UNLIKELY(!block->page.frame)) {
if (!block->page.lock.x_lock_try()) {
@@ -2786,14 +2712,11 @@ wait_for_unfix:
if (state < buf_page_t::UNFIXED + 1) {
ut_ad(state > buf_page_t::FREED);
- ut_ad(mode == BUF_GET_POSSIBLY_FREED
- || mode == BUF_PEEK_IF_IN_POOL);
- block->page.unfix();
block->page.lock.x_unlock();
hash_lock.unlock();
buf_LRU_block_free_non_file_page(new_block);
mysql_mutex_unlock(&buf_pool.mutex);
- return nullptr;
+ goto ignore_block;
}
mysql_mutex_unlock(&buf_pool.mutex);
@@ -2911,60 +2834,135 @@ re_evict:
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
ut_ad(state > buf_page_t::FREED);
- ut_ad(state < buf_page_t::UNFIXED || (~buf_page_t::LRU_MASK) & state);
- ut_ad(state > buf_page_t::WRITE_FIX || state < buf_page_t::READ_FIX);
-
- /* While tablespace is reinited the indexes are already freed but the
- blocks related to it still resides in buffer pool. Trying to remove
- such blocks from buffer pool would invoke removal of AHI entries
- associated with these blocks. Logic to remove AHI entry will try to
- load the block but block is already in free state. Handle the said case
- with mode = BUF_PEEK_IF_IN_POOL that is invoked from
- "btr_search_drop_page_hash_when_freed". */
- ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL
- || state > buf_page_t::UNFIXED);
-
- const bool not_first_access = block->page.set_accessed();
-
- if (mode != BUF_PEEK_IF_IN_POOL) {
- buf_page_make_young_if_needed(&block->page);
- if (!not_first_access) {
- buf_read_ahead_linear(page_id, block->zip_size(),
- ibuf_inside(mtr));
- }
+ if (UNIV_UNLIKELY(state < buf_page_t::UNFIXED)) {
+ goto ignore_block;
}
+ ut_ad((~buf_page_t::LRU_MASK) & state);
+ ut_ad(state > buf_page_t::WRITE_FIX || state < buf_page_t::READ_FIX);
#ifdef UNIV_DEBUG
if (!(++buf_dbg_counter % 5771)) buf_pool.validate();
#endif /* UNIV_DEBUG */
ut_ad(block->page.frame);
- ut_ad(block->page.id() == page_id);
-
if (state >= buf_page_t::UNFIXED
&& allow_ibuf_merge
&& fil_page_get_type(block->page.frame) == FIL_PAGE_INDEX
&& page_is_leaf(block->page.frame)) {
block->page.lock.x_lock();
+ ut_ad(block->page.id() == page_id
+ || (state >= buf_page_t::READ_FIX
+ && state < buf_page_t::WRITE_FIX));
+
+#ifdef BTR_CUR_HASH_ADAPT
+ if (dict_index_t* index = block->index) {
+ if (index->freed()) {
+ btr_search_drop_page_hash_index(block);
+ }
+ }
+#endif /* BTR_CUR_HASH_ADAPT */
+
+ dberr_t e;
+
+ if (UNIV_UNLIKELY(block->page.id() != page_id)) {
+page_id_mismatch:
+ state = block->page.state();
+ e = DB_CORRUPTION;
+ibuf_merge_corrupted:
+ if (err) {
+ *err = e;
+ }
+
+ buf_pool.corrupted_evict(&block->page, state);
+ return nullptr;
+ }
+
state = block->page.state();
ut_ad(state < buf_page_t::READ_FIX);
if (state >= buf_page_t::IBUF_EXIST
&& state < buf_page_t::REINIT) {
block->page.clear_ibuf_exist();
- ibuf_merge_or_delete_for_page(block, page_id,
- block->zip_size());
+ e = ibuf_merge_or_delete_for_page(block, page_id,
+ block->zip_size());
+ if (UNIV_UNLIKELY(e != DB_SUCCESS)) {
+ goto ibuf_merge_corrupted;
+ }
}
if (rw_latch == RW_X_LATCH) {
mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
+ goto got_latch;
} else {
block->page.lock.x_unlock();
goto get_latch;
}
} else {
get_latch:
- mtr->page_lock(block, rw_latch);
+ switch (rw_latch) {
+ mtr_memo_type_t fix_type;
+ case RW_NO_LATCH:
+ mtr->memo_push(block, MTR_MEMO_BUF_FIX);
+ return block;
+ case RW_S_LATCH:
+ fix_type = MTR_MEMO_PAGE_S_FIX;
+ block->page.lock.s_lock();
+ ut_ad(!block->page.is_read_fixed());
+ if (UNIV_UNLIKELY(block->page.id() != page_id)) {
+ block->page.lock.s_unlock();
+ block->page.lock.x_lock();
+ goto page_id_mismatch;
+ }
+get_latch_valid:
+#ifdef BTR_CUR_HASH_ADAPT
+ if (dict_index_t* index = block->index) {
+ if (index->freed()) {
+ mtr_t::defer_drop_ahi(block, fix_type);
+ }
+ }
+#endif /* BTR_CUR_HASH_ADAPT */
+ mtr->memo_push(block, fix_type);
+ break;
+ case RW_SX_LATCH:
+ fix_type = MTR_MEMO_PAGE_SX_FIX;
+ block->page.lock.u_lock();
+ ut_ad(!block->page.is_io_fixed());
+ if (UNIV_UNLIKELY(block->page.id() != page_id)) {
+ block->page.lock.u_x_upgrade();
+ goto page_id_mismatch;
+ }
+ goto get_latch_valid;
+ default:
+ ut_ad(rw_latch == RW_X_LATCH);
+ fix_type = MTR_MEMO_PAGE_X_FIX;
+ if (block->page.lock.x_lock_upgraded()) {
+ ut_ad(block->page.id() == page_id);
+ block->unfix();
+ mtr->page_lock_upgrade(*block);
+ return block;
+ }
+ if (UNIV_UNLIKELY(block->page.id() != page_id)) {
+ goto page_id_mismatch;
+ }
+ goto get_latch_valid;
+ }
+
+got_latch:
+ ut_ad(page_id_t(page_get_space_id(block->page.frame),
+ page_get_page_no(block->page.frame))
+ == page_id);
+
+ if (mode == BUF_GET_POSSIBLY_FREED
+ || mode == BUF_PEEK_IF_IN_POOL) {
+ return block;
+ }
+
+ const bool not_first_access{block->page.set_accessed()};
+ buf_page_make_young_if_needed(&block->page);
+ if (!not_first_access) {
+ buf_read_ahead_linear(page_id, block->zip_size(),
+ ibuf_inside(mtr));
+ }
}
return block;
@@ -2976,8 +2974,8 @@ get_latch:
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
-BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
-@param[in] mtr mini-transaction
+BUF_PEEK_IF_IN_POOL, or BUF_GET_IF_IN_POOL_OR_WATCH
+@param[in,out] mtr mini-transaction, or NULL
@param[out] err DB_SUCCESS or error code
@param[in] allow_ibuf_merge Allow change buffer merge while
reading the pages from file.
@@ -2995,6 +2993,13 @@ buf_page_get_gen(
{
if (buf_block_t *block= recv_sys.recover(page_id))
{
+ if (UNIV_UNLIKELY(block == reinterpret_cast<buf_block_t*>(-1)))
+ {
+ corrupted:
+ if (err)
+ *err= DB_CORRUPTION;
+ return nullptr;
+ }
/* Recovery is a special case; we fix() before acquiring lock. */
auto s= block->page.fix();
ut_ad(s >= buf_page_t::FREED);
@@ -3006,7 +3011,12 @@ buf_page_get_gen(
const bool must_merge= allow_ibuf_merge &&
ibuf_page_exists(page_id, block->zip_size());
if (s < buf_page_t::UNFIXED)
+ {
+ got_freed_page:
ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL);
+ block->page.unfix();
+ goto corrupted;
+ }
else if (must_merge &&
fil_page_get_type(block->page.frame) == FIL_PAGE_INDEX &&
page_is_leaf(block->page.frame))
@@ -3016,12 +3026,22 @@ buf_page_get_gen(
ut_ad(s > buf_page_t::FREED);
ut_ad(s < buf_page_t::READ_FIX);
if (s < buf_page_t::UNFIXED)
- ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL);
+ {
+ block->page.lock.x_unlock();
+ goto got_freed_page;
+ }
else
{
if (block->page.is_ibuf_exist())
block->page.clear_ibuf_exist();
- ibuf_merge_or_delete_for_page(block, page_id, block->zip_size());
+ if (dberr_t e=
+ ibuf_merge_or_delete_for_page(block, page_id, block->zip_size()))
+ {
+ if (err)
+ *err= e;
+ buf_pool.corrupted_evict(&block->page, s);
+ return nullptr;
+ }
}
if (rw_latch == RW_X_LATCH)
@@ -3156,7 +3176,7 @@ buf_block_t *buf_page_try_get(const page_id_t page_id, mtr_t *mtr)
block->page.fix();
ut_ad(!block->page.is_read_fixed());
- mtr_memo_push(mtr, block, MTR_MEMO_PAGE_S_FIX);
+ mtr->memo_push(block, MTR_MEMO_PAGE_S_FIX);
#ifdef UNIV_DEBUG
if (!(++buf_dbg_counter % 5771)) buf_pool.validate();
@@ -3228,7 +3248,7 @@ static buf_block_t *buf_page_create_low(page_id_t page_id, ulint zip_size,
{
mysql_mutex_unlock(&buf_pool.mutex);
buf_block_t *block= reinterpret_cast<buf_block_t*>(bpage);
- mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
+ mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX);
#ifdef BTR_CUR_HASH_ADAPT
drop_hash_entry= block->index;
#endif
@@ -3268,7 +3288,7 @@ static buf_block_t *buf_page_create_low(page_id_t page_id, ulint zip_size,
bpage->lock.free();
#endif
ut_free(bpage);
- mtr_memo_push(mtr, free_block, MTR_MEMO_PAGE_X_FIX);
+ mtr->memo_push(free_block, MTR_MEMO_PAGE_X_FIX);
bpage= &free_block->page;
}
}
@@ -3483,37 +3503,6 @@ ATTRIBUTE_COLD void buf_page_monitor(const buf_page_t &bpage, bool read)
MONITOR_INC_NOCHECK(counter);
}
-/** Mark a table corrupted.
-@param[in] bpage corrupted page
-@param[in] space tablespace of the corrupted page */
-ATTRIBUTE_COLD
-static void buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t& space)
-{
- /* If block is not encrypted find the table with specified
- space id, and mark it corrupted. Encrypted tables
- are marked unusable later e.g. in ::open(). */
- if (!space.crypt_data
- || space.crypt_data->type == CRYPT_SCHEME_UNENCRYPTED) {
- dict_set_corrupted_by_space(&space);
- } else {
- dict_set_encrypted_by_space(&space);
- }
-}
-
-/** Mark a table corrupted.
-@param[in] bpage Corrupted page
-@param[in] node data file
-Also remove the bpage from LRU list. */
-ATTRIBUTE_COLD
-static void buf_corrupt_page_release(buf_page_t *bpage, const fil_node_t &node)
-{
- ut_ad(bpage->id().space() == node.space->id);
- buf_pool.corrupted_evict(bpage);
-
- if (!srv_force_recovery)
- buf_mark_space_corrupt(bpage, *node.space);
-}
-
/** Check if the encrypted page is corrupted for the full crc32 format.
@param[in] space_id page belongs to space id
@param[in] d page
@@ -3589,21 +3578,8 @@ static dberr_t buf_page_check_corrupt(buf_page_t *bpage,
ib::error()
<< "The page " << bpage->id()
<< " in file '" << node.name
- << "' cannot be decrypted.";
-
- ib::info()
- << "However key management plugin or used key_version "
- << key_version
- << " is not found or"
- " used encryption algorithm or method does not match.";
-
- if (bpage->id().space() != TRX_SYS_SPACE) {
- ib::info()
- << "Marking tablespace as missing."
- " You may drop this table or"
- " install correct key management plugin"
- " and key file.";
- }
+ << "' cannot be decrypted; key_version="
+ << key_version;
}
return (err);
@@ -3623,6 +3599,10 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
ut_ad(zip_size() == node.space->zip_size());
ut_ad(!!zip.ssize == !!zip.data);
+ ut_d(auto n=) buf_pool.n_pend_reads--;
+ ut_ad(n > 0);
+ buf_pool.stat.n_pages_read++;
+
const byte *read_frame= zip.data ? zip.data : frame;
ut_ad(read_frame);
@@ -3653,7 +3633,11 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
if (read_id == expected_id);
else if (read_id == page_id_t(0, 0))
- /* This is likely an uninitialized page. */;
+ {
+ /* This is likely an uninitialized (all-zero) page. */
+ err= DB_FAIL;
+ goto release_page;
+ }
else if (!node.space->full_crc32() &&
page_id_t(0, read_id.page_no()) == expected_id)
/* FIL_PAGE_SPACE_ID was written as garbage in the system tablespace
@@ -3669,25 +3653,18 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
goto release_page;
}
else
+ {
ib::error() << "Space id and page no stored in the page, read in are "
<< read_id << ", should be " << expected_id;
+ err= DB_PAGE_CORRUPTED;
+ goto release_page;
+ }
}
err= buf_page_check_corrupt(this, node);
if (UNIV_UNLIKELY(err != DB_SUCCESS))
{
database_corrupted:
- /* Not a real corruption if it was triggered by error injection */
- DBUG_EXECUTE_IF("buf_page_import_corrupt_failure",
- if (!is_predefined_tablespace(id().space()))
- {
- buf_corrupt_page_release(this, node);
- ib::info() << "Simulated IMPORT corruption";
- return err;
- }
- err= DB_SUCCESS;
- goto page_not_corrupt;);
-
if (belongs_to_unzip_LRU())
memset_aligned<UNIV_PAGE_SIZE_MIN>(frame, 0, srv_page_size);
@@ -3700,38 +3677,28 @@ database_corrupted:
buf_page_print(read_frame, zip_size());
+ node.space->set_corrupted();
+
ib::info() << " You can use CHECK TABLE to scan"
" your table for corruption. "
<< FORCE_RECOVERY_MSG;
}
if (!srv_force_recovery)
- {
- /* If the corruption is in the system tablespace, we will
- intentionally crash the server. */
- if (expected_id.space() == TRX_SYS_SPACE)
- ib::fatal() << "Aborting because of a corrupt database page.";
- buf_corrupt_page_release(this, node);
- return err;
- }
+ goto release_page;
}
- DBUG_EXECUTE_IF("buf_page_import_corrupt_failure",
- page_not_corrupt: err= err; );
-
if (err == DB_PAGE_CORRUPTED || err == DB_DECRYPTION_FAILED)
{
release_page:
- buf_corrupt_page_release(this, node);
- if (recv_recovery_is_on())
- recv_sys.free_corrupted_page(expected_id);
+ buf_pool.corrupted_evict(this, buf_page_t::READ_FIX);
return err;
}
const bool recovery= recv_recovery_is_on();
- if (recovery)
- recv_recover_page(node.space, this);
+ if (recovery && !recv_recover_page(node.space, this))
+ return DB_PAGE_CORRUPTED;
const bool ibuf_may_exist= frame && !recv_no_ibuf_operations &&
(!expected_id.space() || !is_predefined_tablespace(expected_id.space())) &&
@@ -3755,10 +3722,6 @@ release_page:
lock.x_unlock(true);
- ut_d(auto n=) buf_pool.n_pend_reads--;
- ut_ad(n > 0);
- buf_pool.stat.n_pages_read++;
-
return DB_SUCCESS;
}