diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6d2e67c427a36..a001b3cef30dd 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1102,7 +1102,7 @@ void fil_space_set_recv_size_and_flags(uint32_t id, uint32_t size, if (size) space->recv_size= size; if (flags != FSP_FLAGS_FCRC32_MASK_MARKER) - space->flags= flags; + recv_sys.update_space_flags(space, flags, recv_sys.start_lsn); } mysql_mutex_unlock(&fil_system.mutex); } diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index f321744e7bb74..d63052a466b2e 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -275,6 +275,9 @@ struct recv_sys_t /** iterator to pages, used by parse() */ map::iterator pages_it; + /** Last applied LSN for space->flags updates (used to prevent stale updates) */ + std::map space_flags_lsn; + /** The allocated size of tmp_buf. The 1+8 extra bytes are needed for FORMAT_ENC_11 in parse(). */ static constexpr size_t tmp_buf_size{MTR_SIZE_MAX + 9}; @@ -324,6 +327,9 @@ struct recv_sys_t 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: /** In parse_tail(), handle INIT_PAGE or FREE_PAGE @param id page that is being initialized or freed */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 0231d039ff031..1ceaf3ecc3d45 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -134,6 +134,17 @@ const byte *mtr_t::parse_length(const byte *l, uint32_t *size) noexcept return l; } +/** 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; + } +} + /** If the following is TRUE, the buffer pool file pages must be invalidated after recovery and no ibuf operations are allowed; this becomes TRUE if the log record hash table becomes too full, and log records must be merged @@ -3485,10 +3496,12 @@ static buf_block_t *recv_recover_page(buf_block_t *block, mtr_t &mtr, ? space : fil_space_t::get(block->page.id().space())) { switch (a) { - case log_phys_t::APPLIED_TO_FSP_HEADER: - s->flags = mach_read_from_4( + case log_phys_t::APPLIED_TO_FSP_HEADER: { + uint32_t flags = mach_read_from_4( FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + frame); + recv_sys.update_space_flags(s, flags, + l->start_lsn); s->size_in_header = mach_read_from_4( FSP_HEADER_OFFSET + FSP_SIZE + frame); @@ -3499,6 +3512,7 @@ static buf_block_t *recv_recover_page(buf_block_t *block, mtr_t &mtr, FSP_HEADER_OFFSET + FSP_FREE + FLST_LEN + frame); break; + } default: byte* b= frame + fsp_header_get_encryption_offset(