summaryrefslogtreecommitdiff
path: root/storage/innobase/include/mtr0mtr.h
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/mtr0mtr.h')
-rw-r--r--storage/innobase/include/mtr0mtr.h228
1 files changed, 95 insertions, 133 deletions
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index abc1f65e692..299f658e98a 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2022, MariaDB Corporation.
+Copyright (c) 2013, 2023, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -29,7 +29,7 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h"
#include "dyn0buf.h"
#include "buf0buf.h"
-#include <vector>
+#include "small_vector.h"
/** Start a mini-transaction. */
#define mtr_start(m) (m)->start()
@@ -37,15 +37,6 @@ Created 11/26/1995 Heikki Tuuri
/** Commit a mini-transaction. */
#define mtr_commit(m) (m)->commit()
-/** Set and return a savepoint in mtr.
-@return savepoint */
-#define mtr_set_savepoint(m) (m)->get_savepoint()
-
-/** Release the (index tree) s-latch stored in an mtr memo after a
-savepoint. */
-#define mtr_release_s_latch_at_savepoint(m, s, l) \
- (m)->release_s_latch_at_savepoint((s), (l))
-
/** Change the logging mode of a mini-transaction.
@return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
@@ -60,13 +51,10 @@ savepoint. */
# define mtr_sx_lock_index(i,m) (m)->u_lock(&(i)->lock)
#endif
-#define mtr_release_block_at_savepoint(m, s, b) \
- (m)->release_block_at_savepoint((s), (b))
-
/** Mini-transaction memo stack slot. */
struct mtr_memo_slot_t
{
- /** pointer to the object, or nullptr if released */
+ /** pointer to the object */
void *object;
/** type of the stored object */
mtr_memo_type_t type;
@@ -77,6 +65,9 @@ struct mtr_memo_slot_t
/** Mini-transaction handle and buffer */
struct mtr_t {
+ mtr_t();
+ ~mtr_t();
+
/** Start a mini-transaction. */
void start();
@@ -91,11 +82,11 @@ struct mtr_t {
/** Release latches of unmodified buffer pages.
@param begin first slot to release */
void rollback_to_savepoint(ulint begin)
- { rollback_to_savepoint(begin, m_memo->size()); }
+ { rollback_to_savepoint(begin, m_memo.size()); }
/** Release the last acquired buffer page latch. */
void release_last_page()
- { auto s= m_memo->size(); rollback_to_savepoint(s - 1, s); }
+ { auto s= m_memo.size(); rollback_to_savepoint(s - 1, s); }
/** Commit a mini-transaction that is shrinking a tablespace.
@param space tablespace that is being shrunk */
@@ -120,86 +111,39 @@ struct mtr_t {
ulint get_savepoint() const
{
ut_ad(is_active());
- return m_memo ? m_memo->size() : 0;
+ return m_memo.size();
}
- /** Release the (index tree) s-latch stored in an mtr memo after a savepoint.
- @param savepoint value returned by get_savepoint()
- @param lock index latch to release */
- void release_s_latch_at_savepoint(ulint savepoint, index_lock *lock)
+ /** Get the block at a savepoint */
+ buf_block_t *at_savepoint(ulint savepoint) const
{
ut_ad(is_active());
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.object == lock);
- ut_ad(slot.type == MTR_MEMO_S_LOCK);
- slot.object= nullptr;
- lock->s_unlock();
- }
- /** Release the block in an mtr memo after a savepoint. */
- void release_block_at_savepoint(ulint savepoint, buf_block_t *block)
- {
- ut_ad(is_active());
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.object == block);
- ut_ad(!(slot.type & MTR_MEMO_MODIFY));
- slot.object= nullptr;
- block->page.unfix();
-
- switch (slot.type) {
- case MTR_MEMO_PAGE_S_FIX:
- block->page.lock.s_unlock();
- break;
- case MTR_MEMO_PAGE_SX_FIX:
- case MTR_MEMO_PAGE_X_FIX:
- block->page.lock.u_or_x_unlock(slot.type == MTR_MEMO_PAGE_SX_FIX);
- break;
- default:
- break;
- }
- }
-
- /** @return if we are about to make a clean buffer block dirty */
- static bool is_block_dirtied(const buf_page_t &b)
- {
- ut_ad(b.in_file());
- ut_ad(b.frame);
- ut_ad(b.buf_fix_count());
- return b.oldest_modification() <= 1 && b.id().space() < SRV_TMP_SPACE_ID;
+ const mtr_memo_slot_t &slot= m_memo[savepoint];
+ ut_ad(slot.type < MTR_MEMO_S_LOCK);
+ ut_ad(slot.object);
+ return static_cast<buf_block_t*>(slot.object);
}
- /** X-latch a not yet latched block after a savepoint. */
- void x_latch_at_savepoint(ulint savepoint, buf_block_t *block)
+ /** Try to get a block at a savepoint.
+ @param savepoint the savepoint right before the block was acquired
+ @return the block at the savepoint
+ @retval nullptr if no buffer block was registered at that savepoint */
+ buf_block_t *block_at_savepoint(ulint savepoint) const
{
ut_ad(is_active());
- ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
- MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.object == block);
- ut_ad(slot.type == MTR_MEMO_BUF_FIX);
- slot.type= MTR_MEMO_PAGE_X_FIX;
- block->page.lock.x_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty)
- m_made_dirty= is_block_dirtied(block->page);
+ const mtr_memo_slot_t &slot= m_memo[savepoint];
+ return slot.type < MTR_MEMO_S_LOCK
+ ? static_cast<buf_block_t*>(slot.object)
+ : nullptr;
}
- /** U-latch a not yet latched block after a savepoint. */
- void sx_latch_at_savepoint(ulint savepoint, buf_block_t *block)
- {
- ut_ad(is_active());
- ut_ad(!memo_contains_flagged(block, MTR_MEMO_PAGE_S_FIX |
- MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.object == block);
- ut_ad(slot.type == MTR_MEMO_BUF_FIX);
- slot.type= MTR_MEMO_PAGE_SX_FIX;
- block->page.lock.u_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty)
- m_made_dirty= is_block_dirtied(block->page);
- }
+ /** Retrieve a page that has already been latched.
+ @param id page identifier
+ @param type page latch type
+ @return block
+ @retval nullptr if the block had not been latched yet */
+ buf_block_t *get_already_latched(const page_id_t id, mtr_memo_type_t type)
+ const;
/** @return the logging mode */
mtr_log_t get_log_mode() const
@@ -358,23 +302,17 @@ struct mtr_t {
void release(const index_lock &lock) { release(&lock); }
/** Release a latch to an unmodified page. */
void release(const buf_block_t &block) { release(&block); }
-
- /** Note that the mini-transaction will modify data. */
- void flag_modified() { m_modifications = true; }
private:
/** Release an unmodified object. */
void release(const void *object);
+public:
/** Mark the given latched page as modified.
@param block page that will be modified */
- void modify(const buf_block_t& block);
-public:
- /** Note that the mini-transaction will modify a block. */
- void set_modified(const buf_block_t &block)
- { flag_modified(); if (m_log_mode != MTR_LOG_NONE) modify(block); }
+ void set_modified(const buf_block_t &block);
/** Set the state to not-modified. This will not log the changes.
This is only used during redo log apply, to avoid logging the changes. */
- void discard_modifications() { m_modifications = false; }
+ void discard_modifications() { m_modifications= false; }
/** Get the LSN of commit().
@return the commit LSN
@@ -403,28 +341,17 @@ public:
@param rw_latch latch to acquire */
void upgrade_buffer_fix(ulint savepoint, rw_lock_type_t rw_latch);
- /** Register a page latch on a buffer-fixed block was buffer-fixed.
- @param latch latch type */
- void u_lock_register(ulint savepoint)
+ /** Register a change to the page latch state. */
+ void lock_register(ulint savepoint, mtr_memo_type_t type)
{
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.type == MTR_MEMO_BUF_FIX);
- slot.type= MTR_MEMO_PAGE_SX_FIX;
- }
-
- /** Register a page latch on a buffer-fixed block was buffer-fixed.
- @param latch latch type */
- void s_lock_register(ulint savepoint)
- {
- mtr_memo_slot_t &slot= m_memo->at(savepoint);
- ut_ad(slot.type == MTR_MEMO_BUF_FIX);
- slot.type= MTR_MEMO_PAGE_S_FIX;
+ mtr_memo_slot_t &slot= m_memo[savepoint];
+ ut_ad(slot.type <= MTR_MEMO_BUF_FIX);
+ ut_ad(type <= MTR_MEMO_BUF_FIX);
+ slot.type= type;
}
/** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block);
- /** Upgrade U lock to X */
- void lock_upgrade(const index_lock &lock);
/** Check if we are holding tablespace latch
@param space tablespace to search for
@@ -454,31 +381,66 @@ public:
@retval nullptr if not found */
buf_block_t *memo_contains_page_flagged(const byte *ptr, ulint flags) const;
- /** @return true if mini-transaction contains modifications. */
+ /** @return whether this mini-transaction modifies persistent data */
bool has_modifications() const { return m_modifications; }
#endif /* UNIV_DEBUG */
- /** Push an object to an mtr memo stack.
- @param object object
+ /** Push a buffer page to an the memo.
+ @param block buffer block
@param type object type: MTR_MEMO_S_LOCK, ... */
- void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
+ void memo_push(buf_block_t *block, mtr_memo_type_t type)
+ __attribute__((nonnull))
{
ut_ad(is_active());
- /* 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 buf_pool.flush_list.
-
- FIXME: Do this only when the MTR_MEMO_MODIFY flag is set! */
- if (!m_made_dirty &&
- (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)))
- m_made_dirty=
- is_block_dirtied(*static_cast<const buf_page_t*>(object));
-
- if (!m_memo)
- m_memo= new std::vector<mtr_memo_slot_t>(1, {object, type});
+ ut_ad(type <= MTR_MEMO_PAGE_SX_MODIFY);
+ ut_ad(block->page.buf_fix_count());
+ ut_ad(block->page.in_file());
+#ifdef UNIV_DEBUG
+ switch (type) {
+ case MTR_MEMO_PAGE_S_FIX:
+ ut_ad(block->page.lock.have_s());
+ break;
+ case MTR_MEMO_PAGE_X_FIX: case MTR_MEMO_PAGE_X_MODIFY:
+ ut_ad(block->page.lock.have_x());
+ break;
+ case MTR_MEMO_PAGE_SX_FIX: case MTR_MEMO_PAGE_SX_MODIFY:
+ ut_ad(block->page.lock.have_u_or_x());
+ break;
+ case MTR_MEMO_BUF_FIX:
+ break;
+ case MTR_MEMO_MODIFY:
+ case MTR_MEMO_S_LOCK: case MTR_MEMO_X_LOCK: case MTR_MEMO_SX_LOCK:
+ case MTR_MEMO_SPACE_X_LOCK: case MTR_MEMO_SPACE_S_LOCK:
+ ut_ad("invalid type" == 0);
+ }
+#endif
+ if (!(type & MTR_MEMO_MODIFY));
+ else if (block->page.id().space() >= SRV_TMP_SPACE_ID)
+ {
+ block->page.set_temp_modified();
+ type= mtr_memo_type_t(type & ~MTR_MEMO_MODIFY);
+ }
else
- m_memo->emplace_back(mtr_memo_slot_t{object, type});
+ {
+ m_modifications= true;
+ if (!m_made_dirty)
+ /* If we are going to modify a previously clean persistent page,
+ we must set m_made_dirty, so that commit() will acquire
+ log_sys.flush_order_mutex and insert the block into
+ buf_pool.flush_list. */
+ m_made_dirty= block->page.oldest_modification() <= 1;
+ }
+ m_memo.emplace_back(mtr_memo_slot_t{block, type});
+ }
+
+ /** Push an index lock or tablespace latch to the memo.
+ @param object index lock or tablespace latch
+ @param type object type: MTR_MEMO_S_LOCK, ... */
+ void memo_push(void *object, mtr_memo_type_t type) __attribute__((nonnull))
+ {
+ ut_ad(is_active());
+ ut_ad(type >= MTR_MEMO_S_LOCK);
+ m_memo.emplace_back(mtr_memo_slot_t{object, type});
}
/** @return the size of the log is empty */
@@ -783,7 +745,7 @@ private:
/** specifies which operations should be logged; default MTR_LOG_ALL */
uint16_t m_log_mode:2;
- /** whether at least one buffer pool page was written to */
+ /** whether at least one persistent page was written to */
uint16_t m_modifications:1;
/** whether at least one previously clean buffer pool page was written to */
@@ -809,7 +771,7 @@ private:
#endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
- std::vector<mtr_memo_slot_t> *m_memo= nullptr;
+ small_vector<mtr_memo_slot_t, 16> m_memo;
/** mini-transaction log */
mtr_buf_t m_log;