diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index cfa1534c37f7b..a7b81850c8017 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1066,8 +1066,8 @@ bool fil_space_t::read_page0(const byte *dpage, bool no_lsn) noexcept return ok; } -void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, uint32_t flags) - noexcept +void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, + uint32_t flags, lsn_t lsn) noexcept { ut_ad(id < SRV_SPACE_ID_UPPER_BOUND); mysql_mutex_assert_owner(&recv_sys.mutex); @@ -1079,7 +1079,7 @@ void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, uint32_t flags) if (size) space->recv_size= size; if (flags != FSP_FLAGS_FCRC32_MASK_MARKER) - space->flags= flags; + recv_sys.update_space_flags(space, flags, lsn); } mysql_mutex_unlock(&fil_system.mutex); } diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 8c957e64cbb9e..90830d0a144c8 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1672,9 +1672,10 @@ fil_space_free( /** Set the recovered size of a tablespace in pages. @param id tablespace ID @param size recovered size in pages -@param flags tablespace flags */ +@param flags tablespace flags +@param lsn lsn of the redo log */ void fil_space_set_recv_size_and_flags(ulint id, uint32_t size, - uint32_t flags) noexcept; + uint32_t flags, lsn_t lsn) noexcept; /*******************************************************************//** Sets the max tablespace id counter if the given number is bigger than the diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index a4365706d5ba6..9f487933e6075 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -268,6 +268,8 @@ struct recv_sys_t /** set when an inconsistency with the file system contents is detected during log scan or apply */ bool found_corrupt_fs; + /** Last applied LSN for space->flags updates (used to prevent stale updates) */ + std::map space_flags_lsn; public: /** whether we are applying redo log records during crash recovery. This is protected by recv_sys.mutex */ @@ -351,6 +353,8 @@ struct recv_sys_t if (pages_it != pages.end() && pages_it->first.space() == space_id) pages_it= pages.end(); } + /** Update space->flags only if lsn >= last recorded space-flags LSN */ + void update_space_flags(fil_space_t *space, uint32_t flags, lsn_t lsn); private: /** Attempt to initialize a page based on redo log records. diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index effb3ced6735d..e68ac485dbb0b 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1093,6 +1093,17 @@ class mlog_init_t static mlog_init_t mlog_init; +/** Update space->flags only if lsn >= last recorded space-flags LSN */ +void recv_sys_t::update_space_flags(fil_space_t *space, uint32_t flags, lsn_t lsn) +{ + auto it= space_flags_lsn.find(space->id); + if (it == space_flags_lsn.end() || lsn >= it->second) + { + space->flags= flags; + space_flags_lsn[space->id]= lsn; + } +} + /** Try to recover a tablespace that was not readable earlier @param p iterator to the page @param name tablespace file name @@ -1334,7 +1345,7 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id, if (f.size || f.flags != f.initial_flags) { fil_space_set_recv_size_and_flags( - space->id, f.size, f.flags); + space->id, f.size, f.flags, lsn); } f.space = space; @@ -2723,7 +2734,7 @@ bool recv_sys_t::parse(lsn_t checkpoint_lsn, store_t *store, bool apply) if (has_flags) it->second.flags= flags; } - fil_space_set_recv_size_and_flags(space_id, size, flags); + fil_space_set_recv_size_and_flags(space_id, size, flags, start_lsn); } } last_offset+= rlen; @@ -3081,9 +3092,10 @@ static buf_block_t *recv_recover_page(buf_block_t *block, mtr_t &mtr, : fil_space_t::get(block->page.id().space())) { switch (a) { case log_phys_t::APPLIED_TO_FSP_HEADER: - s->flags = mach_read_from_4( - FSP_HEADER_OFFSET - + FSP_SPACE_FLAGS + frame); + recv_sys.update_space_flags( + s, mach_read_from_4(FSP_HEADER_OFFSET + + FSP_SPACE_FLAGS + frame), + l->start_lsn); s->size_in_header = mach_read_from_4( FSP_HEADER_OFFSET + FSP_SIZE + frame);