diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-18 17:12:57 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-12-18 19:23:34 +0200 |
commit | 0c23e32d27a11bae6dd38703eba674ef6eeb34f4 (patch) | |
tree | 3a75bd013f7e2b5d87057fc200fe109308e3bce3 /storage/innobase/mtr | |
parent | cd093d79f990cfa7923d3f3ca9352c4f0ee1415d (diff) | |
download | mariadb-git-0c23e32d27a11bae6dd38703eba674ef6eeb34f4.tar.gz |
MDEV-24445 Using innodb_undo_tablespaces corrupts system tablespace
In the rewrite of MDEV-8139 (based on MDEV-15528), we introduced a
wrong assumption that any persistent tablespace that is not an .ibd
file is the system tablespace. This assumption is broken when
innodb_undo_tablespaces (files undo001, undo002, ...) are being used.
By default, we have innodb_undo_tablespaces=0 (the persistent undo
log is being stored in the system tablespace).
In MDEV-15528 and MDEV-8139 we rewrote the page scrubbing logic
so that it will follow the tried-and-true write-ahead logging
protocol, first writing FREE_PAGE records and then in the page
flushing, zerofilling or hole-punching freed pages.
Unfortunately, the implementation included a wrong assumption that
that anything that is not in an .ibd file must be the system tablespace.
This wrong assumption would cause overwrites of valid data pages in
the system tablespace.
mtr_t::m_freed_in_system_tablespace: Remove.
mtr_t::m_freed_space: The tablespace associated with m_freed_pages.
buf_page_free(): Take the tablespace and page number as a parameter,
instead of taking a page identifier.
Diffstat (limited to 'storage/innobase/mtr')
-rw-r--r-- | storage/innobase/mtr/mtr0mtr.cc | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 60c91364b15..2f29e4bff89 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -354,8 +354,10 @@ struct ReleaseBlocks void mtr_t::start() { ut_ad(!m_freed_pages); + ut_ad(!m_freed_space); MEM_UNDEFINED(this, sizeof *this); - MEM_MAKE_DEFINED(&m_freed_pages, sizeof(m_freed_pages)); + MEM_MAKE_DEFINED(&m_freed_space, sizeof m_freed_space); + MEM_MAKE_DEFINED(&m_freed_pages, sizeof m_freed_pages); ut_d(m_start= true); ut_d(m_commit= false); @@ -373,7 +375,7 @@ void mtr_t::start() ut_d(m_user_space_id= TRX_SYS_SPACE); m_user_space= nullptr; m_commit_lsn= 0; - m_freed_in_system_tablespace= m_trim_pages= false; + m_trim_pages= false; } /** Release the resources */ @@ -418,28 +420,23 @@ void mtr_t::commit() if (m_freed_pages) { ut_ad(!m_freed_pages->empty()); - fil_space_t *freed_space= m_user_space; - /* Get the freed tablespace in case of predefined tablespace */ - if (!freed_space) - { - ut_ad(is_freed_system_tablespace_page()); - freed_space= fil_system.sys_space; - } - - ut_ad(memo_contains(*freed_space)); + ut_ad(m_freed_space); + ut_ad(memo_contains(*m_freed_space)); + ut_ad(is_named_space(m_freed_space)); /* Update the last freed lsn */ - freed_space->update_last_freed_lsn(m_commit_lsn); + m_freed_space->update_last_freed_lsn(m_commit_lsn); if (!is_trim_pages()) for (const auto &range : *m_freed_pages) - freed_space->add_free_range(range); + m_freed_space->add_free_range(range); else - freed_space->clear_freed_ranges(); + m_freed_space->clear_freed_ranges(); delete m_freed_pages; m_freed_pages= nullptr; - /* Reset of m_trim_pages and m_freed_in_system_tablespace - happens in mtr_t::start() */ + /* mtr_t::start() will reset m_trim_pages */ } + else + ut_ad(!m_freed_space); m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks> (ReleaseBlocks(lsns.first, m_commit_lsn, @@ -476,8 +473,8 @@ void mtr_t::commit_files(lsn_t checkpoint_lsn) ut_ad(!m_made_dirty); ut_ad(m_memo.size() == 0); ut_ad(!srv_read_only_mode); + ut_ad(!m_freed_space); ut_ad(!m_freed_pages); - ut_ad(!m_freed_in_system_tablespace); if (checkpoint_lsn) { byte* ptr = m_log.push<byte*>(SIZE_OF_FILE_CHECKPOINT); |