diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-08-31 17:52:16 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-08-31 17:52:16 +0300 |
commit | bdf62ece6ce8d397c3ee3e4669b4e7a62da4f939 (patch) | |
tree | 982c02d239ea8ebd64390d63fe5fe19eb07157cf | |
parent | f410974f0f38999a08ad0d3f9c109ee184db7f31 (diff) | |
download | mariadb-git-bdf62ece6ce8d397c3ee3e4669b4e7a62da4f939.tar.gz |
MDEV-29374 InnoDB recovery fails with "Data structure corruption"
recv_sys_t::free_corrupted_page(): Identify the corrupted page in
an error or warning message.
buf_page_free(): Just in case, register the page as modified.
This should already have been done in mtr_t::free() as part of
fseg_free_page_low().
mtr_t::memo_push(): Simplify a condition, so that when invoked
with MTR_MEMO_PAGE_X_MODIFY, we will do the right thing.
fseg_free_page_low(): Remove an accidentally added return statement
that prevented mtr_t::free() from being called. This fixes a regression
that was introduced in
commit 0b47c126e31cddda1e94588799599e138400bcf8 (MDEV-13542).
-rw-r--r-- | mysql-test/suite/encryption/r/innodb-redo-badkey.result | 1 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/corrupted_during_recovery.test | 1 | ||||
-rw-r--r-- | mysql-test/suite/encryption/t/innodb-redo-badkey.test | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/corrupted_during_recovery.test | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test | 1 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 2 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 1 | ||||
-rw-r--r-- | storage/innobase/include/mtr0mtr.inl | 8 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 6 |
9 files changed, 16 insertions, 6 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result index 9d583b32101..34fd043a7bd 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result +++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result @@ -8,6 +8,7 @@ call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed r call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); +call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page "); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); call mtr.add_suppression("\\[ERROR\\] InnoDB: Cannot decrypt \\[page id: space="); diff --git a/mysql-test/suite/encryption/t/corrupted_during_recovery.test b/mysql-test/suite/encryption/t/corrupted_during_recovery.test index 70650d0f746..bccac2bb182 100644 --- a/mysql-test/suite/encryption/t/corrupted_during_recovery.test +++ b/mysql-test/suite/encryption/t/corrupted_during_recovery.test @@ -9,6 +9,7 @@ call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed r call mtr.add_suppression("InnoDB: Failed to read page [123] from file '.*test.t1\\.ibd': Table is encrypted but decrypt failed"); call mtr.add_suppression("InnoDB: The page \\[page id: space=\\d+, page number=3\\] in file '.*test.t1\\.ibd' cannot be decrypted"); call mtr.add_suppression("InnoDB: Table in tablespace \\d+ encrypted. However key management plugin or used key_version \\d+ is not found or used encryption algorithm or method does not match. Can't continue opening the table."); +call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page "); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test index fba342aad04..393ca4ad375 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test @@ -17,6 +17,7 @@ call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed r call mtr.add_suppression("InnoDB: Failed to read page .* from file '.*'"); call mtr.add_suppression("InnoDB: OPT_PAGE_CHECKSUM mismatch"); call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore corruption"); +call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page "); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); # for innodb_checksum_algorithm=full_crc32 only diff --git a/mysql-test/suite/innodb/t/corrupted_during_recovery.test b/mysql-test/suite/innodb/t/corrupted_during_recovery.test index fd3ddaa8204..31d353efa38 100644 --- a/mysql-test/suite/innodb/t/corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/corrupted_during_recovery.test @@ -6,6 +6,7 @@ call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); call mtr.add_suppression("InnoDB: Failed to read page 3 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted."); +call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page .*, page number=3\\]"); call mtr.add_suppression("InnoDB: Table `test`.`t1` is corrupted. Please drop the table and recreate."); call mtr.add_suppression("InnoDB: File '.*test/t1\\.ibd' is corrupted"); call mtr.add_suppression("InnoDB: A long wait .* was observed for dict_sys"); diff --git a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test index d4391f89ec1..d28712fec5c 100644 --- a/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test +++ b/mysql-test/suite/innodb/t/leaf_page_corrupted_during_recovery.test @@ -4,6 +4,7 @@ --disable_query_log call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed read of file '.*test.t1\\.ibd' page"); call mtr.add_suppression("\\[ERROR\\] InnoDB: Failed to read page 19 from file '.*test.t1\\.ibd': Page read from tablespace is corrupted\\."); +call mtr.add_suppression("InnoDB: (Unable to apply log to|Discarding log for) corrupted page .*, page number=19\\]"); call mtr.add_suppression("\\[ERROR\\] InnoDB: Plugin initialization aborted at srv0start\\.cc.* with error Data structure corruption"); call mtr.add_suppression("\\[ERROR\\] Plugin 'InnoDB' (init function|registration)"); call mtr.add_suppression("\\[ERROR\\] InnoDB: We detected index corruption"); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index eaf0f955a1f..c1e9dedf72d 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2128,7 +2128,7 @@ void buf_page_free(fil_space_t *space, uint32_t page, mtr_t *mtr) btr_search_drop_page_hash_index(block); #endif /* BTR_CUR_HASH_ADAPT */ block->page.set_freed(block->page.state()); - mtr->memo_push(block, MTR_MEMO_PAGE_X_FIX); + mtr->memo_push(block, MTR_MEMO_PAGE_X_MODIFY); } /** Get read access to a compressed page (usually of type diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 153a0e88c63..12e9a6913ba 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -2593,7 +2593,6 @@ corrupted: if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } - return err; } mtr->free(*space, static_cast<uint32_t>(offset)); diff --git a/storage/innobase/include/mtr0mtr.inl b/storage/innobase/include/mtr0mtr.inl index 71b476a2f5d..75be7adc6a5 100644 --- a/storage/innobase/include/mtr0mtr.inl +++ b/storage/innobase/include/mtr0mtr.inl @@ -48,13 +48,13 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) ut_ad(type <= MTR_MEMO_SPACE_S_LOCK); ut_ad(type == MTR_MEMO_PAGE_X_MODIFY || ut_is_2pow(type)); - /* If this mtr has x-fixed a clean page then we set - the made_dirty flag. This tells us if we need to + /* If this mtr has U or X latched a clean page then we set + the m_made_dirty flag. This tells us if we need to grab log_sys.flush_order_mutex at mtr_t::commit() so that we - can insert the dirtied page into the flush list. */ + can insert the dirtied page into the buf_pool.flush_list. */ if (!m_made_dirty - && (type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX)) { + && (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))) { m_made_dirty = is_block_dirtied( reinterpret_cast<const buf_block_t*>(object)); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index fc2d50da62c..f584e929480 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2949,7 +2949,13 @@ ATTRIBUTE_COLD void recv_sys_t::free_corrupted_page(page_id_t page_id) p->second.log.clear(); pages.erase(p); if (!srv_force_recovery) + { set_corrupt_fs(); + ib::error() << "Unable to apply log to corrupted page " << page_id + << "; set innodb_force_recovery to ignore"; + } + else + ib::warn() << "Discarding log for corrupted page " << page_id; } if (pages.empty()) |