summaryrefslogtreecommitdiff
path: root/storage/innobase/mtr
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-12-18 17:12:57 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-12-18 19:23:34 +0200
commit0c23e32d27a11bae6dd38703eba674ef6eeb34f4 (patch)
tree3a75bd013f7e2b5d87057fc200fe109308e3bce3 /storage/innobase/mtr
parentcd093d79f990cfa7923d3f3ca9352c4f0ee1415d (diff)
downloadmariadb-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.cc31
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);