summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/disabled.def1
-rw-r--r--storage/innobase/buf/buf0buf.cc5
-rw-r--r--storage/innobase/fil/fil0fil.cc65
-rw-r--r--storage/innobase/fsp/fsp0file.cc6
-rw-r--r--storage/innobase/include/db0err.h1
-rw-r--r--storage/innobase/include/fil0fil.h12
-rw-r--r--storage/innobase/log/log0recv.cc276
-rw-r--r--storage/innobase/os/os0file.cc22
-rw-r--r--storage/innobase/ut/ut0ut.cc2
9 files changed, 259 insertions, 131 deletions
diff --git a/mysql-test/suite/innodb/disabled.def b/mysql-test/suite/innodb/disabled.def
index 35c941f8af7..adc9aa27fc1 100644
--- a/mysql-test/suite/innodb/disabled.def
+++ b/mysql-test/suite/innodb/disabled.def
@@ -11,3 +11,4 @@
##############################################################################
create-index-debug : MDEV-13680 InnoDB may crash when btr_page_alloc() fails
+log_file_name : MDEV-24626 Remove synchronous write of page0 and flushing file during file creation
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 416e8be746c..594c7dcc314 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3267,11 +3267,12 @@ buf_block_t*
buf_page_create(fil_space_t *space, uint32_t offset,
ulint zip_size, mtr_t *mtr, buf_block_t *free_block)
{
- page_id_t page_id(space->id, offset);
+ page_id_t page_id (space ? space->id : offset, space ? offset : 0);
ut_ad(mtr->is_active());
ut_ad(page_id.space() != 0 || !zip_size);
- space->free_page(offset, false);
+ if (space)
+ space->free_page(offset, false);
free_block->initialise(page_id, zip_size, 1);
const ulint fold= page_id.fold();
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 7cd619827fa..ef511a0d419 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -347,8 +347,9 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle,
/** Open a tablespace file.
@param node data file
+@param validate validate the page0
@return whether the file was successfully opened */
-static bool fil_node_open_file_low(fil_node_t *node)
+static bool fil_node_open_file_low(fil_node_t *node, bool validate=true)
{
ut_ad(!node->is_open());
ut_ad(node->space->is_closing());
@@ -383,7 +384,7 @@ static bool fil_node_open_file_low(fil_node_t *node)
}
if (node->size);
- else if (!node->read_page0() || !fil_comp_algo_validate(node->space))
+ else if (!node->read_page0(validate) || !fil_comp_algo_validate(node->space))
{
os_file_close(node->handle);
node->handle= OS_FILE_CLOSED;
@@ -406,8 +407,9 @@ static bool fil_node_open_file_low(fil_node_t *node)
/** Open a tablespace file.
@param node data file
+@param validate_page0 validate the page0
@return whether the file was successfully opened */
-static bool fil_node_open_file(fil_node_t *node)
+bool fil_node_open_file(fil_node_t *node, bool validate_page0)
{
mysql_mutex_assert_owner(&fil_system.mutex);
ut_ad(!node->is_open());
@@ -439,7 +441,7 @@ static bool fil_node_open_file(fil_node_t *node)
}
}
- return fil_node_open_file_low(node);
+ return fil_node_open_file_low(node, validate_page0);
}
/** Close the file handle. */
@@ -638,7 +640,7 @@ fil_space_extend_must_retry(
}
/** @return whether the file is usable for io() */
-ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex)
+ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex, bool validate_page0)
{
ut_ad(referenced());
if (!have_mutex)
@@ -648,7 +650,8 @@ ATTRIBUTE_COLD bool fil_space_t::prepare(bool have_mutex)
ut_ad(!id || purpose == FIL_TYPE_TEMPORARY ||
node == UT_LIST_GET_FIRST(chain));
- const bool is_open= node && (node->is_open() || fil_node_open_file(node));
+ const bool is_open= node && (node->is_open()
+ || fil_node_open_file(node, validate_page0));
if (!is_open)
release();
@@ -1446,7 +1449,7 @@ fil_write_flushed_lsn(
@param id tablespace identifier
@return tablespace
@retval nullptr if the tablespace is missing or inaccessible */
-fil_space_t *fil_space_t::get(ulint id)
+fil_space_t *fil_space_t::get(ulint id, bool validate_page0)
{
mysql_mutex_lock(&fil_system.mutex);
fil_space_t *space= fil_space_get_by_id(id);
@@ -1456,8 +1459,9 @@ fil_space_t *fil_space_t::get(ulint id)
if (n & STOPPING)
space= nullptr;
- if ((n & CLOSING) && !space->prepare())
+ if ((n & CLOSING) && !space->prepare(false, validate_page0)) {
space= nullptr;
+ }
return space;
}
@@ -2309,45 +2313,8 @@ err_exit:
crypt_data->fill_page0(flags, page);
}
- if (ulint zip_size = fil_space_t::zip_size(flags)) {
- page_zip_des_t page_zip;
- page_zip_set_size(&page_zip, zip_size);
- page_zip.data = page + srv_page_size;
-#ifdef UNIV_DEBUG
- page_zip.m_start = 0;
-#endif /* UNIV_DEBUG */
- page_zip.m_end = 0;
- page_zip.m_nonempty = 0;
- page_zip.n_blobs = 0;
-
- buf_flush_init_for_writing(NULL, page, &page_zip, false);
-
- *err = os_file_write(IORequestWrite, path, file,
- page_zip.data, 0, zip_size);
- } else {
- buf_flush_init_for_writing(NULL, page, NULL,
- fil_space_t::full_crc32(flags));
-
- *err = os_file_write(IORequestWrite, path, file,
- page, 0, srv_page_size);
- }
-
aligned_free(page);
- if (*err != DB_SUCCESS) {
- ib::error()
- << "Could not write the first page to"
- << " tablespace '" << path << "'";
- goto err_exit;
- }
-
- if (!os_file_flush(file)) {
- ib::error() << "File flush of tablespace '"
- << path << "' failed";
- *err = DB_ERROR;
- goto err_exit;
- }
-
if (has_data_dir) {
/* Make the ISL file if the IBD file is not
in the default location. */
@@ -2900,7 +2867,7 @@ fil_ibd_load(
/* Read and validate the first page of the tablespace.
Assign a tablespace name based on the tablespace type. */
- switch (file.validate_for_recovery()) {
+ switch (dberr_t err= file.validate_for_recovery()) {
os_offset_t minimum_size;
case DB_SUCCESS:
if (file.space_id() != space_id) {
@@ -2913,6 +2880,8 @@ fil_ibd_load(
<< space_id << ".";
return(FIL_LOAD_ID_CHANGED);
}
+ /* fall through */
+ case DB_DEFER_TABLESPACE:
/* Get and test the file size. */
size = os_file_get_size(file.handle());
@@ -2933,16 +2902,16 @@ fil_ibd_load(
<< file.filepath() << "' is only " << size
<< ", should be at least " << minimum_size
<< "!";
+ } else if (err == DB_DEFER_TABLESPACE) {
+ return FIL_LOAD_DEFER;
} else {
/* Everything is fine so far. */
break;
}
/* fall through */
-
case DB_TABLESPACE_EXISTS:
return(FIL_LOAD_INVALID);
-
default:
return(FIL_LOAD_NOT_FOUND);
}
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 57164113647..7e455d3501a 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -447,6 +447,7 @@ Datafile::validate_for_recovery()
switch (err) {
case DB_SUCCESS:
case DB_TABLESPACE_EXISTS:
+ case DB_DEFER_TABLESPACE:
break;
default:
@@ -535,6 +536,11 @@ err_exit:
}
if (nonzero_bytes == 0) {
+ if (recv_recovery_is_on()) {
+ free_first_page();
+ return DB_DEFER_TABLESPACE;
+ }
+
error_txt = "Header page consists of zero bytes";
goto err_exit;
}
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 6cfc63f4a9e..41835451a30 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -173,6 +173,7 @@ enum dberr_t {
DB_END_OF_INDEX,
DB_NOT_FOUND, /*!< Generic error code for "Not found"
type of errors */
+ DB_DEFER_TABLESPACE,
};
#endif
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index a5c5a22f8ca..e30d4eed4d9 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -917,7 +917,7 @@ public:
@param id tablespace identifier
@return tablespace
@retval nullptr if the tablespace is missing or inaccessible */
- static fil_space_t *get(ulint id);
+ static fil_space_t *get(ulint id, bool validate_page0=true);
/** Add/remove the free page in the freed ranges list.
@param[in] offset page number to be added
@@ -1030,7 +1030,8 @@ public:
private:
/** @return whether the file is usable for io() */
- ATTRIBUTE_COLD bool prepare(bool have_mutex= false);
+ ATTRIBUTE_COLD bool prepare(
+ bool have_mutex= false, bool validate_page0=true);
#endif /*!UNIV_INNOCHECKSUM */
};
@@ -1082,7 +1083,7 @@ struct fil_node_t final
/** Read the first page of a data file.
@return whether the page was found valid */
- bool read_page0();
+ bool read_page0(bool validate=true);
/** Determine some file metadata when creating or reading the file.
@param file the file that is being created, or OS_FILE_CLOSED */
@@ -1518,6 +1519,7 @@ inline uint32_t fil_space_t::get_size()
return size;
}
+bool fil_node_open_file(fil_node_t *node, bool validate_page0=true);
#include "fil0crypt.h"
/*******************************************************************//**
@@ -1678,7 +1680,9 @@ enum fil_load_status {
/** The file(s) were not found */
FIL_LOAD_NOT_FOUND,
/** The file(s) were not valid */
- FIL_LOAD_INVALID
+ FIL_LOAD_INVALID,
+ /** The tablespace file was defered to open. */
+ FIL_LOAD_DEFER
};
/** Open a single-file tablespace and add it to the InnoDB data structures.
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 2b8c9e64b47..16a1c9617c7 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -587,6 +587,8 @@ static recv_spaces_t recv_spaces;
/** The last parsed FILE_RENAME records */
static std::map<uint32_t,std::string> renamed_spaces;
+static std::set<uint32_t> defer_spaces;
+
/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
@param[in] create whether the file is being created
@@ -824,6 +826,8 @@ fil_name_process(char* name, ulint len, ulint space_id, bool deleted)
fil_space_free(space_id, false);
f.space = NULL;
}
+
+ defer_spaces.erase((uint32_t)space_id);
}
ut_ad(f.space == NULL);
@@ -885,7 +889,10 @@ same_space:
<< " for tablespace " << space_id;
}
break;
-
+ case FIL_LOAD_DEFER:
+ if (!p.second) f.name= fname.name;
+ defer_spaces.emplace(space_id);
+ break;
case FIL_LOAD_INVALID:
ut_ad(space == NULL);
if (srv_force_recovery == 0) {
@@ -2083,6 +2090,8 @@ same_page:
const bool is_init= (b & 0x70) <= INIT_PAGE;
switch (*store) {
case STORE_IF_EXISTS:
+ if (defer_spaces.find(space_id) != defer_spaces.end())
+ goto store_defer;
if (fil_space_t *space= fil_space_t::get(space_id))
{
const auto size= space->get_size();
@@ -2094,6 +2103,7 @@ same_page:
continue;
/* fall through */
case STORE_YES:
+store_defer:
if (!mlog_init.will_avoid_read(id, start_lsn))
add(id, start_lsn, end_lsn, recs,
static_cast<size_t>(l + rlen - recs));
@@ -2590,41 +2600,56 @@ inline buf_block_t *recv_sys_t::recover_low(const page_id_t page_id,
ut_ad(recs.state == page_recv_t::RECV_WILL_NOT_READ);
buf_block_t* block= nullptr;
mlog_init_t::init &i= mlog_init.last(page_id);
+ bool first_page= (page_id.page_no() == 0);
const lsn_t end_lsn = recs.log.last()->lsn;
+
if (end_lsn < i.lsn)
DBUG_LOG("ib_log", "skip log for page " << page_id
<< " LSN " << end_lsn << " < " << i.lsn);
- else if (fil_space_t *space= fil_space_t::get(page_id.space()))
+ fil_space_t *space= fil_space_t::get(page_id.space());
+ if (!space && !first_page)
+ return block;
+
+ mtr.start();
+ mtr.set_log_mode(MTR_LOG_NO_REDO);
+
+ ulint zip_size= space ? space->zip_size() : 0;
+ if (!space)
{
- mtr.start();
- mtr.set_log_mode(MTR_LOG_NO_REDO);
- block= buf_page_create(space, page_id.page_no(), space->zip_size(), &mtr,
- b);
- if (UNIV_UNLIKELY(block != b))
- {
- /* The page happened to exist in the buffer pool, or it was just
- being read in. Before buf_page_get_with_no_latch() returned to
- buf_page_create(), all changes must have been applied to the
- page already. */
- ut_ad(pages.find(page_id) == pages.end());
- mtr.commit();
- block= nullptr;
- }
- else
- {
- ut_ad(&recs == &pages.find(page_id)->second);
- i.created= true;
- recv_recover_page(block, mtr, p, space, &i);
- ut_ad(mtr.has_committed());
- recs.log.clear();
- map::iterator r= p++;
- pages.erase(r);
- if (pages.empty())
- pthread_cond_signal(&cond);
- }
- space->release();
+ auto it= recv_spaces.find(page_id.space());
+ ut_ad(it != recv_spaces.end());
+ uint32_t flags= it->second.flags;
+ zip_size= fil_space_t::zip_size(flags);
}
+ block= buf_page_create(
+ space, space ? page_id.page_no() : page_id.space(), zip_size, &mtr, b);
+ if (UNIV_UNLIKELY(block != b))
+ {
+ /* The page happened to exist in the buffer pool, or it was just
+ being read in. Before buf_page_get_with_no_latch() returned to
+ buf_page_create(), all changes must have been applied to the
+ page already. */
+ ut_ad(pages.find(page_id) == pages.end());
+ mtr.commit();
+ block= nullptr;
+ }
+ else
+ {
+ ut_ad(&recs == &pages.find(page_id)->second);
+ i.created= true;
+ recv_recover_page(block, mtr, p, space, &i);
+ ut_ad(mtr.has_committed());
+ recs.log.clear();
+ map::iterator r= p++;
+ pages.erase(r);
+ if (pages.empty())
+ pthread_cond_signal(&cond);
+ }
+
+ if (space)
+ space->release();
+
return block;
}
@@ -2652,6 +2677,122 @@ buf_block_t *recv_sys_t::recover_low(const page_id_t page_id)
return block;
}
+/** Report a missing tablespace for which page-redo log exists.
+@param[in] err previous error code
+@param[in] i tablespace descriptor
+@return new error code */
+static
+dberr_t
+recv_init_missing_space(dberr_t err, const recv_spaces_t::const_iterator& i)
+{
+ if (srv_operation == SRV_OPERATION_RESTORE
+ || srv_operation == SRV_OPERATION_RESTORE_EXPORT) {
+ if (i->second.name.find(TEMP_TABLE_PATH_PREFIX)
+ != std::string::npos) {
+ ib::warn() << "Tablespace " << i->first << " was not"
+ " found at " << i->second.name << " when"
+ " restoring a (partial?) backup. All redo log"
+ " for this file will be ignored!";
+ }
+ return(err);
+ }
+
+ if (srv_force_recovery == 0) {
+ ib::error() << "Tablespace " << i->first << " was not"
+ " found at " << i->second.name << ".";
+
+ if (err == DB_SUCCESS) {
+ ib::error() << "Set innodb_force_recovery=1 to"
+ " ignore this and to permanently lose"
+ " all changes to the tablespace.";
+ err = DB_TABLESPACE_NOT_FOUND;
+ }
+ } else {
+ ib::warn() << "Tablespace " << i->first << " was not"
+ " found at " << i->second.name << ", and"
+ " innodb_force_recovery was set. All redo log"
+ " for this tablespace will be ignored!";
+ }
+
+ return(err);
+}
+
+static dberr_t
+recv_validate_deferred_first_page(buf_block_t *first_block)
+{
+ ut_ad(first_block);
+ auto it= recv_spaces.find(first_block->page.id().space());
+ ut_ad(it != recv_spaces.end());
+ byte *first_page= UNIV_LIKELY_NULL(first_block->page.zip.data)
+ ? first_block->page.zip.data
+ : first_block->frame;
+
+ if (buf_is_zeroes(span<const byte> (first_page, srv_page_size)))
+err_exit:
+ return DB_CORRUPTION;
+ uint32_t space_id= mach_read_from_4(first_page + FIL_PAGE_SPACE_ID);
+ uint32_t flags= fsp_header_get_flags(first_page);
+ uint32_t page_no= mach_read_from_4(first_page + FIL_PAGE_OFFSET);
+ if (space_id >= SRV_SPACE_ID_UPPER_BOUND
+ || page_no > 0
+ || flags != it->second.flags
+ || !fil_space_t::is_valid_flags(flags, space_id)
+ || fil_space_t::logical_size(flags) != srv_page_size)
+ goto err_exit;
+ return DB_SUCCESS;
+}
+
+static dberr_t recv_create_deferred_space(buf_block_t *first_block)
+{
+ auto it= recv_spaces.find(first_block->page.id().space());
+ ut_ad(it != recv_spaces.end());
+ byte *page= UNIV_LIKELY_NULL(first_block->page.zip.data)
+ ? first_block->page.zip.data
+ : first_block->frame;
+ char *space_name= fil_path_to_space_name(it->second.name.c_str());
+ const uint32_t size = fsp_header_get_field(page, FSP_SIZE);
+ const uint32_t free_limit = fsp_header_get_field(
+ page, FSP_FREE_LIMIT);
+ const uint32_t free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
+ + page);
+
+ fil_space_crypt_t *crypt_data= fil_space_read_crypt_data(
+ fil_space_t::zip_size(it->second.flags), page);
+ fil_space_t *space= fil_space_t::create(
+ space_name, it->first, it->second.flags, FIL_TYPE_TABLESPACE,
+ crypt_data);
+ if (!space)
+ return DB_TABLESPACE_NOT_FOUND;
+ space->add(it->second.name.c_str(), OS_FILE_CLOSED, 0, false, false);
+
+ space->recv_size= it->second.size;
+ space->size_in_header = size;
+ space->free_limit = free_limit;
+ space->free_len = free_len;
+ space= fil_space_t::get(space->id, false);
+ space->release();
+
+ return DB_SUCCESS;
+}
+
+static dberr_t recv_init_deferred_space(uint32_t space)
+{
+ page_id_t defer_first_page(space, 0);
+ buf_block_t *first_block= recv_sys.recover(defer_first_page);
+ if (first_block)
+ {
+ dberr_t err= recv_validate_deferred_first_page(first_block);
+ if (err == DB_SUCCESS)
+ {
+ err= recv_create_deferred_space(first_block);
+ defer_spaces.erase(space);
+ }
+ return err;
+ }
+
+ return DB_CORRUPTION;
+}
+
/** Apply buffered log to persistent data pages.
@param last_batch whether it is possible to write more redo log */
void recv_sys_t::apply(bool last_batch)
@@ -2723,6 +2864,24 @@ void recv_sys_t::apply(bool last_batch)
page_recv_t &recs= p->second;
ut_ad(!recs.log.empty());
+ auto it= defer_spaces.find(page_id.space());
+
+ if (it != defer_spaces.end())
+ {
+ mysql_mutex_unlock(&mutex);
+ dberr_t err= recv_init_deferred_space(page_id.space());
+ if (err != DB_SUCCESS)
+ {
+ auto i= recv_spaces.find(page_id.space());
+ err= recv_init_missing_space(DB_SUCCESS, i);
+ recv_sys.set_corrupt_log();
+ return;
+ }
+ mysql_mutex_lock(&mutex);
+ p= pages.lower_bound(page_id);
+ continue;
+ }
+
switch (recs.state) {
case page_recv_t::RECV_BEING_READ:
case page_recv_t::RECV_BEING_PROCESSED:
@@ -3255,46 +3414,6 @@ recv_group_scan_log_recs(
DBUG_RETURN(store == STORE_NO);
}
-/** Report a missing tablespace for which page-redo log exists.
-@param[in] err previous error code
-@param[in] i tablespace descriptor
-@return new error code */
-static
-dberr_t
-recv_init_missing_space(dberr_t err, const recv_spaces_t::const_iterator& i)
-{
- if (srv_operation == SRV_OPERATION_RESTORE
- || srv_operation == SRV_OPERATION_RESTORE_EXPORT) {
- if (i->second.name.find(TEMP_TABLE_PATH_PREFIX)
- != std::string::npos) {
- ib::warn() << "Tablespace " << i->first << " was not"
- " found at " << i->second.name << " when"
- " restoring a (partial?) backup. All redo log"
- " for this file will be ignored!";
- }
- return(err);
- }
-
- if (srv_force_recovery == 0) {
- ib::error() << "Tablespace " << i->first << " was not"
- " found at " << i->second.name << ".";
-
- if (err == DB_SUCCESS) {
- ib::error() << "Set innodb_force_recovery=1 to"
- " ignore this and to permanently lose"
- " all changes to the tablespace.";
- err = DB_TABLESPACE_NOT_FOUND;
- }
- } else {
- ib::warn() << "Tablespace " << i->first << " was not"
- " found at " << i->second.name << ", and"
- " innodb_force_recovery was set. All redo log"
- " for this tablespace will be ignored!";
- }
-
- return(err);
-}
-
/** Report the missing tablespace and discard the redo logs for the deleted
tablespace.
@param[in] rescan rescan of redo logs is needed
@@ -3322,6 +3441,10 @@ next:
recv_spaces_t::iterator i = recv_spaces.find(space);
ut_ad(i != recv_spaces.end());
+ if (defer_spaces.find((uint32_t)space) != defer_spaces.end()) {
+ goto next;
+ }
+
switch (i->second.status) {
case file_name_t::NORMAL:
goto next;
@@ -3352,6 +3475,9 @@ func_exit:
continue;
}
+ if (defer_spaces.find((uint32_t)rs.first) != defer_spaces.end())
+ continue;
+
missing_tablespace = true;
if (srv_force_recovery > 0) {
@@ -3742,6 +3868,18 @@ completed:
recv_lsn_checks_on = true;
+ while(defer_spaces.size()) {
+ uint32_t space_id = *(defer_spaces.begin());
+ dberr_t err= recv_init_deferred_space(space_id);
+ if (err != DB_SUCCESS) {
+ err= recv_init_missing_space(
+ DB_SUCCESS,
+ recv_spaces.find(space_id));
+ recv_sys.set_corrupt_log();
+ return err;
+ }
+ }
+
/* The database is now ready to start almost normal processing of user
transactions: transaction rollbacks and the application of the log
records in the hash table can be run in background. */
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 605c77b577e..3fe115710b9 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -4475,8 +4475,9 @@ void fil_node_t::find_metadata(os_file_t file
}
/** Read the first page of a data file.
+@param validate validate the page0
@return whether the page was found valid */
-bool fil_node_t::read_page0()
+bool fil_node_t::read_page0(bool validate)
{
mysql_mutex_assert_owner(&fil_system.mutex);
const unsigned psize = space->physical_size();
@@ -4500,6 +4501,10 @@ bool fil_node_t::read_page0()
return false;
}
+ if (!validate)
+ goto skip_page0;
+
+ {
page_t *page= static_cast<byte*>(aligned_malloc(psize, psize));
if (os_file_read(IORequestRead, handle, page, 0, psize)
!= DB_SUCCESS) {
@@ -4558,6 +4563,14 @@ invalid:
return false;
}
+ space->flags = (space->flags & FSP_FLAGS_MEM_MASK) | flags;
+ ut_ad(space->free_limit == 0 || space->free_limit == free_limit);
+ ut_ad(space->free_len == 0 || space->free_len == free_len);
+ space->size_in_header = size;
+ space->free_limit = free_limit;
+ space->free_len = free_len;
+ }
+skip_page0:
#ifdef UNIV_LINUX
find_metadata(handle, &statbuf);
#else
@@ -4573,16 +4586,9 @@ invalid:
size_bytes &= ~os_offset_t(mask);
}
- space->flags = (space->flags & FSP_FLAGS_MEM_MASK) | flags;
-
space->punch_hole = space->is_compressed();
this->size = uint32_t(size_bytes / psize);
space->set_sizes(this->size);
- ut_ad(space->free_limit == 0 || space->free_limit == free_limit);
- ut_ad(space->free_len == 0 || space->free_len == free_len);
- space->size_in_header = size;
- space->free_limit = free_limit;
- space->free_len = free_len;
return true;
}
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index fa04af6de13..0a896aa15cb 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -468,6 +468,8 @@ ut_strerr(
return ("File system does not support punch hole (trim) operation.");
case DB_PAGE_CORRUPTED:
return("Page read from tablespace is corrupted.");
+ case DB_DEFER_TABLESPACE:
+ return("Deferring the tablespace to load till InnoDB recovers page0");
/* do not add default: in order to produce a warning if new code
is added to the enum but not added here */