summaryrefslogtreecommitdiff
path: root/storage/innobase/include
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-11-17 09:19:32 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2022-11-17 09:19:32 +0200
commitd5332086d7aa1eaef9da5850d38dd1489fad7032 (patch)
treebd65941f8399f6f215d3bfb930d2fc2a44416cea /storage/innobase/include
parent0e6f2757d11502d74d21e4a75fa5247fc3334024 (diff)
parent9aea7d83c8d006519bdf1f3269136b3756ed7548 (diff)
downloadmariadb-git-d5332086d7aa1eaef9da5850d38dd1489fad7032.tar.gz
Merge 10.6 into 10.7
Diffstat (limited to 'storage/innobase/include')
-rw-r--r--storage/innobase/include/btr0btr.h136
-rw-r--r--storage/innobase/include/btr0btr.inl40
-rw-r--r--storage/innobase/include/btr0cur.h74
-rw-r--r--storage/innobase/include/btr0cur.inl12
-rw-r--r--storage/innobase/include/btr0pcur.h249
-rw-r--r--storage/innobase/include/btr0pcur.inl107
-rw-r--r--storage/innobase/include/btr0types.h96
-rw-r--r--storage/innobase/include/dyn0buf.h56
-rw-r--r--storage/innobase/include/gis0rtree.h22
-rw-r--r--storage/innobase/include/ibuf0ibuf.h38
-rw-r--r--storage/innobase/include/ibuf0ibuf.inl31
-rw-r--r--storage/innobase/include/ibuf0types.h31
-rw-r--r--storage/innobase/include/log0log.h7
-rw-r--r--storage/innobase/include/mtr0mtr.h264
-rw-r--r--storage/innobase/include/mtr0mtr.inl185
-rw-r--r--storage/innobase/include/page0cur.h22
-rw-r--r--storage/innobase/include/page0cur.inl19
-rw-r--r--storage/innobase/include/row0ins.h8
-rw-r--r--storage/innobase/include/row0row.h13
19 files changed, 502 insertions, 908 deletions
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index a4bf42adcfb..a2aa46b62da 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -55,103 +55,8 @@ not acceptable for it to lead to mysterious memory corruption, but it
is acceptable for the program to die with a clear assert failure. */
#define BTR_MAX_LEVELS 100
-/** Latching modes for btr_cur_search_to_nth_level(). */
-enum btr_latch_mode {
- /** Search a record on a leaf page and S-latch it. */
- BTR_SEARCH_LEAF = RW_S_LATCH,
- /** (Prepare to) modify a record on a leaf page and X-latch it. */
- BTR_MODIFY_LEAF = RW_X_LATCH,
- /** Obtain no latches. */
- BTR_NO_LATCHES = RW_NO_LATCH,
- /** Search the previous record. */
- BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
- /** Modify the previous record. */
- BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
- /** Start searching the entire B-tree. */
- BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
- /** Start modifying1 the entire B-tree. */
- BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
- /** Continue searching the entire B-tree. */
- BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
- /** Continue modifying the entire B-tree. */
- BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
-
- /* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
- exclusive. */
- /** The search tuple will be inserted to the secondary index
- at the searched position. When the leaf page is not in the
- buffer pool, try to use the change buffer. */
- BTR_INSERT = 64,
-
- /** Try to delete mark a secondary index leaf page record at
- the searched position using the change buffer when the page is
- not in the buffer pool. */
- BTR_DELETE_MARK = 128,
-
- /** Try to purge the record using the change buffer when the
- secondary index leaf page is not in the buffer pool. */
- BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
-
- /** The caller is already holding dict_index_t::lock S-latch. */
- BTR_ALREADY_S_LATCHED = 256,
- /** Search and S-latch a leaf page, assuming that the
- dict_index_t::lock S-latch is being held. */
- BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
- | BTR_ALREADY_S_LATCHED,
- /** Search the entire index tree, assuming that the
- dict_index_t::lock S-latch is being held. */
- BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
- | BTR_ALREADY_S_LATCHED,
- /** Search and X-latch a leaf page, assuming that the
- dict_index_t::lock S-latch is being held. */
- BTR_MODIFY_LEAF_ALREADY_S_LATCHED = BTR_MODIFY_LEAF
- | BTR_ALREADY_S_LATCHED,
-
- /** Attempt to delete-mark a secondary index record. */
- BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
- /** Attempt to delete-mark a secondary index record
- while holding the dict_index_t::lock S-latch. */
- BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
- | BTR_ALREADY_S_LATCHED,
- /** Attempt to purge a secondary index record. */
- BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
- /** Attempt to purge a secondary index record
- while holding the dict_index_t::lock S-latch. */
- BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
- | BTR_ALREADY_S_LATCHED,
-
- /** In the case of BTR_MODIFY_TREE, the caller specifies
- the intention to delete record only. It is used to optimize
- block->lock range.*/
- BTR_LATCH_FOR_DELETE = 512,
-
- /** Attempt to purge a secondary index record in the tree. */
- BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE
-};
-
-/** This flag ORed to BTR_INSERT says that we can ignore possible
-UNIQUE definition on secondary indexes when we decide if we can use
-the insert buffer to speed up inserts */
-#define BTR_IGNORE_SEC_UNIQUE 2048U
-
-/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
-to insert record only. It is used to optimize block->lock range.*/
-#define BTR_LATCH_FOR_INSERT 4096U
-
-/** This flag is for undo insert of rtree. For rtree, we need this flag
-to find proper rec to undo insert.*/
-#define BTR_RTREE_UNDO_INS 8192U
-
-/** In the case of BTR_MODIFY_LEAF, the caller intends to allocate or
-free the pages of externally stored fields. */
-#define BTR_MODIFY_EXTERNAL 16384U
-
-/** Try to delete mark the record at the searched position when the
-record is in spatial index */
-#define BTR_RTREE_DELETE_MARK 32768U
-
#define BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode) \
- ((latch_mode) & ulint(~(BTR_INSERT \
+ btr_latch_mode((latch_mode) & ~(BTR_INSERT \
| BTR_DELETE_MARK \
| BTR_RTREE_UNDO_INS \
| BTR_RTREE_DELETE_MARK \
@@ -159,13 +64,11 @@ record is in spatial index */
| BTR_IGNORE_SEC_UNIQUE \
| BTR_ALREADY_S_LATCHED \
| BTR_LATCH_FOR_INSERT \
- | BTR_LATCH_FOR_DELETE \
- | BTR_MODIFY_EXTERNAL)))
+ | BTR_LATCH_FOR_DELETE))
-#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \
- ((latch_mode) & ulint(~(BTR_LATCH_FOR_INSERT \
- | BTR_LATCH_FOR_DELETE \
- | BTR_MODIFY_EXTERNAL)))
+#define BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode) \
+ btr_latch_mode((latch_mode) \
+ & ~(BTR_LATCH_FOR_INSERT | BTR_LATCH_FOR_DELETE))
/**************************************************************//**
Checks and adjusts the root node of a tree during IMPORT TABLESPACE.
@@ -229,17 +132,6 @@ inline uint32_t btr_page_get_prev(const page_t* page)
}
/**************************************************************//**
-Releases the latch on a leaf page and bufferunfixes it. */
-UNIV_INLINE
-void
-btr_leaf_page_release(
-/*==================*/
- buf_block_t* block, /*!< in: buffer block */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
- BTR_MODIFY_LEAF */
- mtr_t* mtr) /*!< in: mtr */
- MY_ATTRIBUTE((nonnull));
-/**************************************************************//**
Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since
we read the last field according to offsets and assume that it contains
@@ -359,15 +251,12 @@ be done either within the same mini-transaction, or by invoking
ibuf_reset_free_bits() before mtr_commit(). On uncompressed pages,
IBUF_BITMAP_FREE is unaffected by reorganization.
+@param cursor page cursor
+@param mtr mini-transaction
@return error code
@retval DB_FAIL if reorganizing a ROW_FORMAT=COMPRESSED page failed */
-dberr_t
-btr_page_reorganize(
-/*================*/
- page_cur_t* cursor, /*!< in/out: page cursor */
- dict_index_t* index, /*!< in: the index tree of the page */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+dberr_t btr_page_reorganize(page_cur_t *cursor, mtr_t *mtr)
+ MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Decide if the page should be split at the convergence point of inserts
converging to the left.
@param[in] cursor insert position
@@ -445,13 +334,10 @@ inline void btr_set_min_rec_mark(rec_t *rec, const buf_block_t &block,
}
/** Seek to the parent page of a B-tree page.
-@param[in,out] index b-tree
-@param[in] block child page
@param[in,out] mtr mini-transaction
-@param[out] cursor cursor pointing to the x-latched parent page
+@param[in,out] cursor cursor pointing to the x-latched parent page
@return whether the cursor was successfully positioned */
-bool btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
- btr_cur_t* cursor)
+bool btr_page_get_father(mtr_t* mtr, btr_cur_t* cursor)
MY_ATTRIBUTE((nonnull,warn_unused_result));
#ifdef UNIV_DEBUG
/************************************************************//**
diff --git a/storage/innobase/include/btr0btr.inl b/storage/innobase/include/btr0btr.inl
index f92622cc400..9a9e39b6b4c 100644
--- a/storage/innobase/include/btr0btr.inl
+++ b/storage/innobase/include/btr0btr.inl
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2021, MariaDB Corporation.
+Copyright (c) 2015, 2022, 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
@@ -24,10 +24,7 @@ The B-tree
Created 6/2/1994 Heikki Tuuri
*******************************************************/
-#include "mach0data.h"
-#include "mtr0mtr.h"
#include "mtr0log.h"
-#include "page0zip.h"
/**************************************************************//**
Gets the index id field of a page.
@@ -112,38 +109,3 @@ btr_node_ptr_get_child_page_no(
return(page_no);
}
-
-/**************************************************************//**
-Releases the latches on a leaf page and bufferunfixes it. */
-UNIV_INLINE
-void
-btr_leaf_page_release(
-/*==================*/
- buf_block_t* block, /*!< in: buffer block */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
- BTR_MODIFY_LEAF */
- mtr_t* mtr) /*!< in: mtr */
-{
- ut_ad(latch_mode == BTR_SEARCH_LEAF
- || latch_mode == BTR_MODIFY_LEAF
- || latch_mode == BTR_NO_LATCHES);
-
- ut_ad(!mtr->memo_contains_flagged(block, MTR_MEMO_MODIFY));
-
- mtr_memo_type_t mode;
- switch (latch_mode) {
- case BTR_SEARCH_LEAF:
- mode = MTR_MEMO_PAGE_S_FIX;
- break;
- case BTR_MODIFY_LEAF:
- mode = MTR_MEMO_PAGE_X_FIX;
- break;
- case BTR_NO_LATCHES:
- mode = MTR_MEMO_BUF_FIX;
- break;
- default:
- ut_a(0);
- }
-
- mtr->memo_release(block, mode);
-}
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 6626b2e948a..aa890be9936 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -96,7 +96,7 @@ btr_cur_get_page(
Returns the index of a cursor.
@param cursor b-tree cursor
@return index */
-#define btr_cur_get_index(cursor) ((cursor)->index)
+#define btr_cur_get_index(cursor) ((cursor)->index())
/*********************************************************//**
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -137,7 +137,7 @@ bool
btr_cur_optimistic_latch_leaves(
buf_block_t* block,
ib_uint64_t modify_clock,
- ulint* latch_mode,
+ btr_latch_mode* latch_mode,
btr_cur_t* cursor,
mtr_t* mtr);
@@ -148,7 +148,6 @@ to node pointer page number fields on the upper levels of the tree!
Note that if mode is PAGE_CUR_LE, which is used in inserts, then
cursor->up_match and cursor->low_match both will have sensible values.
If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
-@param index index
@param level the tree level of search
@param tuple data tuple; NOTE: n_fields_cmp in tuple must be set so that
it cannot get compared to the node ptr page number field!
@@ -166,27 +165,13 @@ If mode is PAGE_CUR_GE, then up_match will a have a sensible value.
@param mtr mini-transaction
@param autoinc PAGE_ROOT_AUTO_INC to be written (0 if none)
@return DB_SUCCESS on success or error code otherwise */
-dberr_t btr_cur_search_to_nth_level(dict_index_t *index, ulint level,
+dberr_t btr_cur_search_to_nth_level(ulint level,
const dtuple_t *tuple,
- page_cur_mode_t mode, ulint latch_mode,
+ page_cur_mode_t mode,
+ btr_latch_mode latch_mode,
btr_cur_t *cursor, mtr_t *mtr,
ib_uint64_t autoinc= 0);
-/*****************************************************************//**
-Opens a cursor at either end of an index.
-@return DB_SUCCESS or error code */
-dberr_t
-btr_cur_open_at_index_side(
- bool from_left, /*!< in: true if open to the low end,
- false if to the high end */
- dict_index_t* index, /*!< in: index */
- ulint latch_mode, /*!< in: latch mode */
- btr_cur_t* cursor, /*!< in/out: cursor */
- ulint level, /*!< in: level to search for
- (0=leaf) */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
-
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree.
@return true if the index is available and we have put the cursor, false
@@ -194,7 +179,7 @@ if the index is unavailable */
bool
btr_cur_open_at_rnd_pos(
dict_index_t* index, /*!< in: index */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
+ btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull,warn_unused_result));
@@ -281,7 +266,6 @@ btr_cur_update_alloc_zip_func(
/*==========================*/
page_zip_des_t* page_zip,/*!< in/out: compressed page */
page_cur_t* cursor, /*!< in/out: B-tree page cursor */
- dict_index_t* index, /*!< in: the index corresponding to cursor */
#ifdef UNIV_DEBUG
rec_offs* offsets,/*!< in/out: offsets of the cursor record */
#endif /* UNIV_DEBUG */
@@ -291,11 +275,11 @@ btr_cur_update_alloc_zip_func(
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull, warn_unused_result));
#ifdef UNIV_DEBUG
-# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
- btr_cur_update_alloc_zip_func(page_zip,cursor,index,offsets,len,cr,mtr)
+# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
+ btr_cur_update_alloc_zip_func(page_zip,cursor,offsets,len,cr,mtr)
#else /* UNIV_DEBUG */
-# define btr_cur_update_alloc_zip(page_zip,cursor,index,offsets,len,cr,mtr) \
- btr_cur_update_alloc_zip_func(page_zip,cursor,index,len,cr,mtr)
+# define btr_cur_update_alloc_zip(page_zip,cursor,offsets,len,cr,mtr) \
+ btr_cur_update_alloc_zip_func(page_zip,cursor,len,cr,mtr)
#endif /* UNIV_DEBUG */
/** Apply an update vector to a record. No field size changes are allowed.
@@ -689,7 +673,7 @@ btr_rec_copy_externally_stored_field(
void
btr_cur_latch_leaves(
buf_block_t* block,
- ulint latch_mode,
+ btr_latch_mode latch_mode,
btr_cur_t* cursor,
mtr_t* mtr,
btr_latch_leaves_t* latch_leaves = nullptr);
@@ -752,7 +736,6 @@ enum btr_cur_method {
/** The tree cursor: the definition appears here only for the compiler
to know struct size! */
struct btr_cur_t {
- dict_index_t* index; /*!< index where positioned */
page_cur_t page_cur; /*!< page cursor */
purge_node_t* purge_node; /*!< purge node, for BTR_DELETE */
buf_block_t* left_block; /*!< this field is used to store
@@ -817,28 +800,19 @@ struct btr_cur_t {
information of the path through
the tree */
rtr_info_t* rtr_info; /*!< rtree search info */
- btr_cur_t():thr(NULL), rtr_info(NULL) {}
- /* default values */
- /** Zero-initialize all fields */
- void init()
- {
- index = NULL;
- memset(&page_cur, 0, sizeof page_cur);
- purge_node = NULL;
- left_block = NULL;
- thr = NULL;
- flag = btr_cur_method(0);
- tree_height = 0;
- up_match = 0;
- up_bytes = 0;
- low_match = 0;
- low_bytes = 0;
- n_fields = 0;
- n_bytes = 0;
- fold = 0;
- path_arr = NULL;
- rtr_info = NULL;
- }
+ btr_cur_t() { memset((void*) this, 0, sizeof *this); }
+
+ dict_index_t *index() const { return page_cur.index; }
+ buf_block_t *block() const { return page_cur.block; }
+
+ /** Open the cursor on the first or last record.
+ @param first true=first record, false=last record
+ @param index B-tree
+ @param latch_mode which latches to acquire
+ @param mtr mini-transaction
+ @return error code */
+ dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
+ mtr_t *mtr);
};
/** Modify the delete-mark flag of a record.
diff --git a/storage/innobase/include/btr0cur.inl b/storage/innobase/include/btr0cur.inl
index 76a2d3be49c..955cf34288e 100644
--- a/storage/innobase/include/btr0cur.inl
+++ b/storage/innobase/include/btr0cur.inl
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2021, MariaDB Corporation.
+Copyright (c) 2018, 2022, 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
@@ -72,7 +72,7 @@ btr_cur_position(
btr_cur_t* cursor) /*!< out: cursor */
{
page_cur_position(rec, block, btr_cur_get_page_cur(cursor));
- cursor->index = index;
+ cursor->page_cur.index = index;
}
/*********************************************************************//**
@@ -98,14 +98,14 @@ btr_cur_compress_recommendation(
if (!page_has_siblings(page)
|| page_get_data_size(page)
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor has dropped below a predefined
minimum value OR the level in the B-tree contains just
one page: we recommend compression if this is not the
root page. */
- return cursor->index->page
+ return cursor->index()->page
!= btr_cur_get_block(cursor)->page.id().page_no();
}
@@ -133,14 +133,14 @@ btr_cur_can_delete_without_compress(
if (!page_has_siblings(page) || page_get_n_recs(page) < 2
|| page_get_data_size(page) - rec_size
- < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index)) {
+ < BTR_CUR_PAGE_COMPRESS_LIMIT(cursor->index())) {
/* The page fillfactor will drop below a predefined
minimum value, OR the level in the B-tree contains just
one page, OR the page will become empty: we recommend
compression if this is not the root page. */
- return cursor->index->page
+ return cursor->index()->page
== btr_cur_get_block(cursor)->page.id().page_no();
}
diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h
index 5103484da29..cd8eacdc212 100644
--- a/storage/innobase/include/btr0pcur.h
+++ b/storage/innobase/include/btr0pcur.h
@@ -46,13 +46,6 @@ of a scroll cursor easier */
};
/**************************************************************//**
-Allocates memory for a persistent cursor object and initializes the cursor.
-@return own: persistent cursor */
-btr_pcur_t*
-btr_pcur_create_for_mysql(void);
-/*============================*/
-
-/**************************************************************//**
Resets a persistent cursor object, freeing ::old_rec_buf if it is
allocated and resetting the other members to their initial values. */
void
@@ -61,12 +54,6 @@ btr_pcur_reset(
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
/**************************************************************//**
-Frees the memory for a persistent cursor object. */
-void
-btr_pcur_free_for_mysql(
-/*====================*/
- btr_pcur_t* cursor); /*!< in, own: persistent cursor */
-/**************************************************************//**
Copies the stored position of a pcur to another pcur. */
void
btr_pcur_copy_stored_position(
@@ -83,21 +70,11 @@ btr_pcur_init(
/*==========*/
btr_pcur_t* pcur); /*!< in: persistent cursor */
-/** Free old_rec_buf.
-@param[in] pcur Persistent cursor holding old_rec to be freed. */
-UNIV_INLINE
-void
-btr_pcur_free(
- btr_pcur_t* pcur);
-
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
-btr_pcur_open_low(
-/*==============*/
- dict_index_t* index, /*!< in: index */
- ulint level, /*!< in: level in the btree */
+btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -105,17 +82,14 @@ btr_pcur_open_low(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the
record! */
- ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
+ btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-#define btr_pcur_open(i,t,md,l,c,m) \
- btr_pcur_open_low(i,0,t,md,l,c,0,m)
/** Opens an persistent cursor to an index tree without initializing the
cursor.
-@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -126,26 +100,11 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
-dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
- page_cur_mode_t mode, ulint latch_mode,
+dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
+ page_cur_mode_t mode,
+ btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr);
-/*****************************************************************//**
-Opens a persistent cursor at either end of an index. */
-UNIV_INLINE
-dberr_t
-btr_pcur_open_at_index_side(
-/*========================*/
- bool from_left, /*!< in: true if open to the low end,
- false if to the high end */
- dict_index_t* index, /*!< in: index */
- ulint latch_mode, /*!< in: latch mode */
- btr_pcur_t* pcur, /*!< in/out: cursor */
- bool init_pcur, /*!< in: whether to initialize pcur */
- ulint level, /*!< in: level to search for
- (0=leaf) */
- mtr_t* mtr) /*!< in/out: mini-transaction */
- MY_ATTRIBUTE((nonnull,warn_unused_result));
/**************************************************************//**
Gets the up_match value for a pcur after a search.
@return number of matched fields at the cursor or to the right if
@@ -356,102 +315,103 @@ enum pcur_pos_t {
/* The persistent B-tree cursor structure. This is used mainly for SQL
selects, updates, and deletes. */
-struct btr_pcur_t{
- /** Return value of restore_position() */
- enum restore_status {
- /** cursor position on user rec and points on the record with
- the same field values as in the stored record */
- SAME_ALL,
- /** cursor position is on user rec and points on the record with
- the same unique field values as in the stored record */
- SAME_UNIQ,
- /** cursor position is not on user rec or points on the record
- with not the same uniq field values as in the stored record */
- NOT_SAME,
- /** the index tree is corrupted */
- CORRUPTED
- };
- /** a B-tree cursor */
- btr_cur_t btr_cur;
- /** see TODO note below!
- BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES,
- depending on the latching state of the page and tree where the cursor
- is positioned; BTR_NO_LATCHES means that the cursor is not currently
- positioned:
- we say then that the cursor is detached; it can be restored to
- attached if the old position was stored in old_rec */
- ulint latch_mode;
- /** true if old_rec is stored */
- bool old_stored;
- /** if cursor position is stored, contains an initial segment of the
- latest record cursor was positioned either on, before or after */
- rec_t* old_rec;
- /** btr_cur.index->n_core_fields when old_rec was copied */
- uint16 old_n_core_fields;
- /** number of fields in old_rec */
- uint16 old_n_fields;
- /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
- whether cursor was on, before, or after the old_rec record */
- enum btr_pcur_pos_t rel_pos;
- /** buffer block when the position was stored */
- buf::Block_hint block_when_stored;
- /** the modify clock value of the buffer block when the cursor position
- was stored */
- ib_uint64_t modify_clock;
- /** btr_pcur_store_position() and btr_pcur_restore_position() state. */
- enum pcur_pos_t pos_state;
- /** PAGE_CUR_G, ... */
- page_cur_mode_t search_mode;
- /** the transaction, if we know it; otherwise this field is not defined;
- can ONLY BE USED in error prints in fatal assertion failures! */
- trx_t* trx_if_known;
- /*-----------------------------*/
- /* NOTE that the following fields may possess dynamically allocated
- memory which should be freed if not needed anymore! */
-
- /** NULL, or a dynamically allocated buffer for old_rec */
- byte* old_rec_buf;
- /** old_rec_buf size if old_rec_buf is not NULL */
- ulint buf_size;
-
- btr_pcur_t() :
- btr_cur(), latch_mode(RW_NO_LATCH),
- old_stored(false), old_rec(NULL),
- old_n_fields(0), rel_pos(btr_pcur_pos_t(0)),
- block_when_stored(),
- modify_clock(0), pos_state(BTR_PCUR_NOT_POSITIONED),
- search_mode(PAGE_CUR_UNSUPP), trx_if_known(NULL),
- old_rec_buf(NULL), buf_size(0)
- {
- btr_cur.init();
- }
-
- /** Return the index of this persistent cursor */
- dict_index_t* index() const { return(btr_cur.index); }
- MY_ATTRIBUTE((nonnull, warn_unused_result))
- /** Restores the stored position of a persistent cursor bufferfixing
- the page and obtaining the specified latches. If the cursor position
- was saved when the
- (1) cursor was positioned on a user record: this function restores the
- position to the last record LESS OR EQUAL to the stored record;
- (2) cursor was positioned on a page infimum record: restores the
- position to the last record LESS than the user record which was the
- successor of the page infimum;
- (3) cursor was positioned on the page supremum: restores to the first
- record GREATER than the user record which was the predecessor of the
- supremum.
- (4) cursor was positioned before the first or after the last in an
- empty tree: restores to before first or after the last in the tree.
- @param restore_latch_mode BTR_SEARCH_LEAF, ...
- @param mtr mtr
- @retval SAME_ALL cursor position on user rec and points on
- the record with the same field values as in the stored record,
- @retval SAME_UNIQ cursor position is on user rec and points on the
- record with the same unique field values as in the stored record,
- @retval NOT_SAME cursor position is not on user rec or points on
- the record with not the same uniq field values as in the stored
- @retval CORRUPTED if the index is corrupted */
- restore_status restore_position(ulint latch_mode, mtr_t *mtr);
+struct btr_pcur_t
+{
+ /** Return value of restore_position() */
+ enum restore_status {
+ /** cursor position on user rec and points on the record with
+ the same field values as in the stored record */
+ SAME_ALL,
+ /** cursor position is on user rec and points on the record with
+ the same unique field values as in the stored record */
+ SAME_UNIQ,
+ /** cursor position is not on user rec or points on the record
+ with not the same uniq field values as in the stored record */
+ NOT_SAME,
+ /** the index tree is corrupted */
+ CORRUPTED
+ };
+ /** a B-tree cursor */
+ btr_cur_t btr_cur;
+ /** @see BTR_PCUR_WAS_POSITIONED
+ BTR_SEARCH_LEAF, BTR_MODIFY_LEAF, BTR_MODIFY_TREE or BTR_NO_LATCHES,
+ depending on the latching state of the page and tree where the cursor
+ is positioned; BTR_NO_LATCHES means that the cursor is not currently
+ positioned:
+ we say then that the cursor is detached; it can be restored to
+ attached if the old position was stored in old_rec */
+ btr_latch_mode latch_mode= BTR_NO_LATCHES;
+ /** if cursor position is stored, contains an initial segment of the
+ latest record cursor was positioned either on, before or after */
+ rec_t *old_rec= nullptr;
+ /** btr_cur.index()->n_core_fields when old_rec was copied */
+ uint16 old_n_core_fields= 0;
+ /** number of fields in old_rec */
+ uint16 old_n_fields= 0;
+ /** BTR_PCUR_ON, BTR_PCUR_BEFORE, or BTR_PCUR_AFTER, depending on
+ whether cursor was on, before, or after the old_rec record */
+ btr_pcur_pos_t rel_pos= btr_pcur_pos_t(0);
+ /** buffer block when the position was stored */
+ buf::Block_hint block_when_stored;
+ /** the modify clock value of the buffer block when the cursor position
+ was stored */
+ ib_uint64_t modify_clock= 0;
+ /** btr_pcur_store_position() and btr_pcur_restore_position() state. */
+ enum pcur_pos_t pos_state= BTR_PCUR_NOT_POSITIONED;
+ page_cur_mode_t search_mode= PAGE_CUR_UNSUPP;
+ /** the transaction, if we know it; otherwise this field is not defined;
+ can ONLY BE USED in error prints in fatal assertion failures! */
+ trx_t *trx_if_known= nullptr;
+ /** a dynamically allocated buffer for old_rec */
+ byte *old_rec_buf= nullptr;
+ /** old_rec_buf size if old_rec_buf is not NULL */
+ ulint buf_size= 0;
+
+ /** Return the index of this persistent cursor */
+ dict_index_t *index() const { return(btr_cur.index()); }
+ MY_ATTRIBUTE((nonnull, warn_unused_result))
+ /** Restores the stored position of a persistent cursor bufferfixing
+ the page and obtaining the specified latches. If the cursor position
+ was saved when the
+ (1) cursor was positioned on a user record: this function restores the
+ position to the last record LESS OR EQUAL to the stored record;
+ (2) cursor was positioned on a page infimum record: restores the
+ position to the last record LESS than the user record which was the
+ successor of the page infimum;
+ (3) cursor was positioned on the page supremum: restores to the first
+ record GREATER than the user record which was the predecessor of the
+ supremum.
+ (4) cursor was positioned before the first or after the last in an
+ empty tree: restores to before first or after the last in the tree.
+ @param restore_latch_mode BTR_SEARCH_LEAF, ...
+ @param mtr mtr
+ @retval SAME_ALL cursor position on user rec and points on
+ the record with the same field values as in the stored record,
+ @retval SAME_UNIQ cursor position is on user rec and points on the
+ record with the same unique field values as in the stored record,
+ @retval NOT_SAME cursor position is not on user rec or points on
+ the record with not the same uniq field values as in the stored
+ @retval CORRUPTED if the index is corrupted */
+ restore_status restore_position(btr_latch_mode latch_mode, mtr_t *mtr);
+
+ /** Open the cursor on the first or last record.
+ @param first true=first record, false=last record
+ @param index B-tree
+ @param latch_mode which latches to acquire
+ @param mtr mini-transaction
+ @return error code */
+ dberr_t open_leaf(bool first, dict_index_t *index, btr_latch_mode latch_mode,
+ mtr_t *mtr)
+
+ {
+ this->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
+ search_mode= first ? PAGE_CUR_G : PAGE_CUR_L;
+ pos_state= BTR_PCUR_IS_POSITIONED;
+ old_rec= nullptr;
+
+ return btr_cur.open_leaf(first, index,
+ BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode), mtr);
+ }
};
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
@@ -479,10 +439,9 @@ MY_ATTRIBUTE((nonnull, warn_unused_result))
inline
dberr_t
btr_pcur_open_on_user_rec(
- dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ... */
- ulint latch_mode, /*!< in: BTR_SEARCH_LEAF or
+ btr_latch_mode latch_mode, /*!< in: BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
cursor */
@@ -490,7 +449,7 @@ btr_pcur_open_on_user_rec(
{
ut_ad(mode == PAGE_CUR_GE || mode == PAGE_CUR_G);
ut_ad(latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF);
- if (dberr_t err= btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr))
+ if (dberr_t err= btr_pcur_open(tuple, mode, latch_mode, cursor, 0, mtr))
return err;
if (!btr_pcur_is_after_last_on_page(cursor) ||
btr_pcur_is_after_last_in_tree(cursor))
diff --git a/storage/innobase/include/btr0pcur.inl b/storage/innobase/include/btr0pcur.inl
index 82801f4426d..551f8f20fca 100644
--- a/storage/innobase/include/btr0pcur.inl
+++ b/storage/innobase/include/btr0pcur.inl
@@ -36,7 +36,6 @@ btr_pcur_get_rel_pos(
{
ut_ad(cursor);
ut_ad(cursor->old_rec);
- ut_ad(cursor->old_stored);
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
@@ -163,7 +162,7 @@ btr_pcur_move_to_next_on_page(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
- cursor->old_stored = false;
+ cursor->old_rec = nullptr;
return page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
}
@@ -177,7 +176,7 @@ btr_pcur_move_to_prev_on_page(
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
- cursor->old_stored = false;
+ cursor->old_rec = nullptr;
return page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
}
@@ -196,7 +195,7 @@ btr_pcur_move_to_next_user_rec(
{
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
- cursor->old_stored = false;
+ cursor->old_rec = nullptr;
loop:
if (btr_pcur_is_after_last_on_page(cursor)) {
if (btr_pcur_is_after_last_in_tree(cursor)
@@ -230,7 +229,7 @@ btr_pcur_move_to_next(
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
- cursor->old_stored= false;
+ cursor->old_rec= nullptr;
if (btr_pcur_is_after_last_on_page(cursor))
return !btr_pcur_is_after_last_in_tree(cursor) &&
@@ -294,31 +293,17 @@ btr_pcur_init(
/*==========*/
btr_pcur_t* pcur) /*!< in: persistent cursor */
{
- pcur->old_stored = false;
pcur->old_rec_buf = NULL;
pcur->old_rec = NULL;
pcur->btr_cur.rtr_info = NULL;
}
-/** Free old_rec_buf.
-@param[in] pcur Persistent cursor holding old_rec to be freed. */
-UNIV_INLINE
-void
-btr_pcur_free(
- btr_pcur_t* pcur)
-{
- ut_free(pcur->old_rec_buf);
-}
-
/**************************************************************//**
Initializes and opens a persistent cursor to an index tree. */
inline
dberr_t
-btr_pcur_open_low(
-/*==============*/
- dict_index_t* index, /*!< in: index */
- ulint level, /*!< in: level in the btree */
+btr_pcur_open(
const dtuple_t* tuple, /*!< in: tuple on which search done */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L, ...;
NOTE that if the search is made using a unique
@@ -326,26 +311,24 @@ btr_pcur_open_low(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page from the
record! */
- ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
+ btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
ib_uint64_t autoinc,/*!< in: PAGE_ROOT_AUTO_INC to be written
(0 if none) */
mtr_t* mtr) /*!< in: mtr */
{
- ut_ad(!index->is_spatial());
- btr_pcur_init(cursor);
+ ut_ad(!cursor->index()->is_spatial());
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known= nullptr;
- return btr_cur_search_to_nth_level(index, level, tuple, mode, latch_mode,
+ return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor),
mtr, autoinc);
}
/** Opens an persistent cursor to an index tree without initializing the
cursor.
-@param index index
@param tuple tuple on which search done
@param mode PAGE_CUR_L, ...; NOTE that if the search is made using a
unique prefix of a record, mode should be PAGE_CUR_LE, not
@@ -356,59 +339,21 @@ cursor.
@param mtr mini-transaction
@return DB_SUCCESS on success or error code otherwise. */
inline
-dberr_t btr_pcur_open_with_no_init(dict_index_t *index, const dtuple_t *tuple,
- page_cur_mode_t mode, ulint latch_mode,
+dberr_t btr_pcur_open_with_no_init(const dtuple_t *tuple,
+ page_cur_mode_t mode,
+ btr_latch_mode latch_mode,
btr_pcur_t *cursor, mtr_t *mtr)
{
cursor->latch_mode= BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
cursor->search_mode= mode;
cursor->pos_state= BTR_PCUR_IS_POSITIONED;
- cursor->old_stored= false;
cursor->trx_if_known= nullptr;
/* Search with the tree cursor */
- return btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
+ return btr_cur_search_to_nth_level(0, tuple, mode, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
}
-/*****************************************************************//**
-Opens a persistent cursor at either end of an index. */
-UNIV_INLINE
-dberr_t
-btr_pcur_open_at_index_side(
-/*========================*/
- bool from_left, /*!< in: true if open to the low end,
- false if to the high end */
- dict_index_t* index, /*!< in: index */
- ulint latch_mode, /*!< in: latch mode */
- btr_pcur_t* pcur, /*!< in/out: cursor */
- bool init_pcur, /*!< in: whether to initialize pcur */
- ulint level, /*!< in: level to search for
- (0=leaf) */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- dberr_t err = DB_SUCCESS;
-
- pcur->latch_mode = BTR_LATCH_MODE_WITHOUT_FLAGS(latch_mode);
-
- pcur->search_mode = from_left ? PAGE_CUR_G : PAGE_CUR_L;
-
- if (init_pcur) {
- btr_pcur_init(pcur);
- }
-
- err = btr_cur_open_at_index_side(
- from_left, index, latch_mode,
- btr_pcur_get_btr_cur(pcur), level, mtr);
- pcur->pos_state = BTR_PCUR_IS_POSITIONED;
-
- pcur->old_stored = false;
-
- pcur->trx_if_known = NULL;
-
- return (err);
-}
-
/**************************************************************//**
Frees the possible memory heap of a persistent cursor and sets the latch
mode of the persistent cursor to BTR_NO_LATCHES.
@@ -425,25 +370,21 @@ btr_pcur_close(
/*===========*/
btr_pcur_t* cursor) /*!< in: persistent cursor */
{
- ut_free(cursor->old_rec_buf);
-
- if (cursor->btr_cur.rtr_info) {
- rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true);
- cursor->btr_cur.rtr_info = NULL;
- }
+ ut_free(cursor->old_rec_buf);
- cursor->old_rec = NULL;
- cursor->old_rec_buf = NULL;
- cursor->btr_cur.page_cur.rec = NULL;
- cursor->btr_cur.page_cur.block = NULL;
+ if (cursor->btr_cur.rtr_info)
+ rtr_clean_rtr_info(cursor->btr_cur.rtr_info, true);
- cursor->old_rec = NULL;
- cursor->old_stored = false;
+ cursor->btr_cur.rtr_info= nullptr;
+ cursor->old_rec = nullptr;
+ cursor->old_rec_buf = nullptr;
+ cursor->btr_cur.page_cur.rec = nullptr;
+ cursor->btr_cur.page_cur.block = nullptr;
- cursor->latch_mode = BTR_NO_LATCHES;
- cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
+ cursor->latch_mode = BTR_NO_LATCHES;
+ cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
- cursor->trx_if_known = NULL;
+ cursor->trx_if_known = nullptr;
}
/*********************************************************//**
@@ -459,5 +400,5 @@ btr_pcur_move_before_first_on_page(
page_cur_set_before_first(btr_pcur_get_block(cursor),
btr_pcur_get_page_cur(cursor));
- cursor->old_stored = false;
+ cursor->old_rec = nullptr;
}
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index 83c374e2561..6118bfbc128 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2019, MariaDB Corporation.
+Copyright (c) 2018, 2022, 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
@@ -24,8 +24,7 @@ The index tree general types
Created 2/17/1996 Heikki Tuuri
*************************************************************************/
-#ifndef btr0types_h
-#define btr0types_h
+#pragma once
#include "page0types.h"
#include "rem0types.h"
@@ -56,4 +55,93 @@ in the index record. */
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
(BTR_EXTERN_FIELD_REF_SIZE * 2)
-#endif
+/** Latching modes for btr_cur_search_to_nth_level(). */
+enum btr_latch_mode {
+ /** Search a record on a leaf page and S-latch it. */
+ BTR_SEARCH_LEAF = RW_S_LATCH,
+ /** (Prepare to) modify a record on a leaf page and X-latch it. */
+ BTR_MODIFY_LEAF = RW_X_LATCH,
+ /** Obtain no latches. */
+ BTR_NO_LATCHES = RW_NO_LATCH,
+ /** Search the previous record. */
+ BTR_SEARCH_PREV = 4 | BTR_SEARCH_LEAF,
+ /** Modify the previous record. */
+ BTR_MODIFY_PREV = 4 | BTR_MODIFY_LEAF,
+ /** Start searching the entire B-tree. */
+ BTR_SEARCH_TREE = 8 | BTR_SEARCH_LEAF,
+ /** Start modifying1 the entire B-tree. */
+ BTR_MODIFY_TREE = 8 | BTR_MODIFY_LEAF,
+ /** Continue searching the entire B-tree. */
+ BTR_CONT_SEARCH_TREE = 4 | BTR_SEARCH_TREE,
+ /** Continue modifying the entire B-tree. */
+ BTR_CONT_MODIFY_TREE = 4 | BTR_MODIFY_TREE,
+
+ /* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually
+ exclusive. */
+ /** The search tuple will be inserted to the secondary index
+ at the searched position. When the leaf page is not in the
+ buffer pool, try to use the change buffer. */
+ BTR_INSERT = 64,
+
+ /** Try to delete mark a secondary index leaf page record at
+ the searched position using the change buffer when the page is
+ not in the buffer pool. */
+ BTR_DELETE_MARK = 128,
+
+ /** Try to purge the record using the change buffer when the
+ secondary index leaf page is not in the buffer pool. */
+ BTR_DELETE = BTR_INSERT | BTR_DELETE_MARK,
+
+ /** The caller is already holding dict_index_t::lock S-latch. */
+ BTR_ALREADY_S_LATCHED = 256,
+ /** Search and S-latch a leaf page, assuming that the
+ dict_index_t::lock S-latch is being held. */
+ BTR_SEARCH_LEAF_ALREADY_S_LATCHED = BTR_SEARCH_LEAF
+ | BTR_ALREADY_S_LATCHED,
+ /** Search the entire index tree, assuming that the
+ dict_index_t::lock S-latch is being held. */
+ BTR_SEARCH_TREE_ALREADY_S_LATCHED = BTR_SEARCH_TREE
+ | BTR_ALREADY_S_LATCHED,
+ /** Search and X-latch a leaf page, assuming that the
+ dict_index_t::lock is being held in non-exclusive mode. */
+ BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF
+ | BTR_ALREADY_S_LATCHED,
+
+ /** Attempt to delete-mark a secondary index record. */
+ BTR_DELETE_MARK_LEAF = BTR_MODIFY_LEAF | BTR_DELETE_MARK,
+ /** Attempt to delete-mark a secondary index record
+ while holding the dict_index_t::lock S-latch. */
+ BTR_DELETE_MARK_LEAF_ALREADY_S_LATCHED = BTR_DELETE_MARK_LEAF
+ | BTR_ALREADY_S_LATCHED,
+ /** Attempt to purge a secondary index record. */
+ BTR_PURGE_LEAF = BTR_MODIFY_LEAF | BTR_DELETE,
+ /** Attempt to purge a secondary index record
+ while holding the dict_index_t::lock S-latch. */
+ BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
+ | BTR_ALREADY_S_LATCHED,
+
+ /** In the case of BTR_MODIFY_TREE, the caller specifies
+ the intention to delete record only. It is used to optimize
+ block->lock range.*/
+ BTR_LATCH_FOR_DELETE = 512,
+
+ /** In the case of BTR_MODIFY_TREE, the caller specifies
+ the intention to delete record only. It is used to optimize
+ block->lock range.*/
+ BTR_LATCH_FOR_INSERT = 1024,
+
+ /** Attempt to delete a record in the tree. */
+ BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
+
+ /** Attempt to insert a record into the tree. */
+ BTR_INSERT_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
+
+ /** This flag ORed to BTR_INSERT says that we can ignore possible
+ UNIQUE definition on secondary indexes when we decide if we can use
+ the insert buffer to speed up inserts */
+ BTR_IGNORE_SEC_UNIQUE = 2048,
+ /** Rollback in spatial index */
+ BTR_RTREE_UNDO_INS = 4096,
+ /** Try to delete mark a spatial index record */
+ BTR_RTREE_DELETE_MARK = 8192
+};
diff --git a/storage/innobase/include/dyn0buf.h b/storage/innobase/include/dyn0buf.h
index cb8b998f0ea..208e49c34a7 100644
--- a/storage/innobase/include/dyn0buf.h
+++ b/storage/innobase/include/dyn0buf.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2020, MariaDB Corporation.
+Copyright (c) 2018, 2022, 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
@@ -331,60 +331,6 @@ public:
}
/**
- Iterate over each block and call the functor.
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block(const Functor& functor) const
- {
- for (typename list_t::iterator it = m_list.begin(),
- end = m_list.end();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
- Iterate over all the blocks in reverse and call the iterator
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block_in_reverse(Functor& functor) const
- {
- for (list_t::reverse_iterator it = m_list.rbegin(),
- end = m_list.rend();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
- Iterate over all the blocks in reverse and call the iterator
- @return false if iteration was terminated. */
- template <typename Functor>
- bool for_each_block_in_reverse(const Functor& functor) const
- {
- for (list_t::reverse_iterator it = m_list.rbegin(),
- end = m_list.rend();
- it != end; ++it) {
-
- if (!functor(&*it)) {
- return false;
- }
- }
-
- return(true);
- }
-
- /**
@return the first block */
block_t* front()
MY_ATTRIBUTE((warn_unused_result))
diff --git a/storage/innobase/include/gis0rtree.h b/storage/innobase/include/gis0rtree.h
index 8cd5e384530..777f2432c93 100644
--- a/storage/innobase/include/gis0rtree.h
+++ b/storage/innobase/include/gis0rtree.h
@@ -256,23 +256,14 @@ rtr_get_mbr_from_tuple(
rtr_mbr* mbr); /*!< out: mbr to fill */
/* Get the rtree page father.
-@param[in] offsets work area for the return value
-@param[in] index rtree index
-@param[in] block child page in the index
@param[in,out] mtr mtr
@param[in] sea_cur search cursor, contains information
about parent nodes in search
-@param[out] cursor cursor on node pointer record,
+@param[in,out] cursor cursor on node pointer record,
its page x-latched
@return whether the cursor was successfully positioned */
-bool
-rtr_page_get_father(
- dict_index_t* index,
- buf_block_t* block,
- mtr_t* mtr,
- btr_cur_t* sea_cur,
- btr_cur_t* cursor)
- MY_ATTRIBUTE((nonnull(1,2,3,5), warn_unused_result));
+bool rtr_page_get_father(mtr_t *mtr, btr_cur_t *sea_cur, btr_cur_t *cursor)
+ MY_ATTRIBUTE((nonnull(1,3), warn_unused_result));
/************************************************************//**
Returns the father block to a page. It is assumed that mtr holds
@@ -283,8 +274,6 @@ rtr_page_get_father_block(
/*======================*/
rec_offs* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
- dict_index_t* index, /*!< in: b-tree index */
- buf_block_t* block, /*!< in: child page in the index */
mtr_t* mtr, /*!< in: mtr */
btr_cur_t* sea_cur,/*!< in: search cursor, contains information
about parent nodes in search */
@@ -298,7 +287,7 @@ rtr_store_parent_path(
/*==================*/
const buf_block_t* block, /*!< in: block of the page */
btr_cur_t* btr_cur,/*!< in/out: persistent cursor */
- ulint latch_mode,
+ btr_latch_mode latch_mode,
/*!< in: latch_mode */
ulint level, /*!< in: index level */
mtr_t* mtr); /*!< in: mtr */
@@ -310,7 +299,7 @@ bool
rtr_pcur_open(
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
- ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
+ btr_latch_mode latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
mtr_t* mtr) /*!< in: mtr */
MY_ATTRIBUTE((warn_unused_result));
@@ -432,7 +421,6 @@ rtr_check_same_block(
btr_cur_t* cur, /*!< in/out: position at the parent entry
pointing to the child if successful */
buf_block_t* parentb,/*!< in: parent page to check */
- buf_block_t* childb, /*!< in: child Page */
mem_heap_t* heap); /*!< in: memory heap */
/*********************************************************************//**
diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h
index e6f72b05087..c246b2ef513 100644
--- a/storage/innobase/include/ibuf0ibuf.h
+++ b/storage/innobase/include/ibuf0ibuf.h
@@ -30,7 +30,6 @@ Created 7/19/1997 Heikki Tuuri
#include "mtr0mtr.h"
#include "dict0mem.h"
#include "fsp0fsp.h"
-#include "ibuf0types.h"
/** Default value for maximum on-disk size of change buffer in terms
of percentage of the buffer pool. */
@@ -61,6 +60,37 @@ enum ibuf_use_t {
/** Operations that can currently be buffered. */
extern ulong innodb_change_buffering;
+/** Insert buffer struct */
+struct ibuf_t{
+ Atomic_relaxed<ulint> size; /*!< current size of the ibuf index
+ tree, in pages */
+ Atomic_relaxed<ulint> max_size; /*!< recommended maximum size of the
+ ibuf index tree, in pages */
+ ulint seg_size; /*!< allocated pages of the file
+ segment containing ibuf header and
+ tree */
+ bool empty; /*!< Protected by the page
+ latch of the root page of the
+ insert buffer tree
+ (FSP_IBUF_TREE_ROOT_PAGE_NO). true
+ if and only if the insert
+ buffer tree is empty. */
+ ulint free_list_len; /*!< length of the free list */
+ ulint height; /*!< tree height */
+ dict_index_t* index; /*!< insert buffer index */
+
+ /** number of pages merged */
+ Atomic_counter<ulint> n_merges;
+ Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
+ /*!< number of operations of each type
+ merged to index pages */
+ Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
+ /*!< number of operations of each type
+ discarded without merging due to the
+ tablespace being deleted or the
+ index being dropped */
+};
+
/** The insert buffer control structure */
extern ibuf_t ibuf;
@@ -339,9 +369,9 @@ void ibuf_delete_for_discarded_space(uint32_t space);
/** Contract the change buffer by reading pages to the buffer pool.
@return a lower limit for the combined size in bytes of entries which
-will be merged from ibuf trees to the pages read, 0 if ibuf is
-empty */
-ulint ibuf_merge_all();
+will be merged from ibuf trees to the pages read
+@retval 0 if ibuf.empty */
+ulint ibuf_contract();
/** Contracts insert buffer trees by reading pages referring to space_id
to the buffer pool.
diff --git a/storage/innobase/include/ibuf0ibuf.inl b/storage/innobase/include/ibuf0ibuf.inl
index 2c2620511c7..9f4e937f31d 100644
--- a/storage/innobase/include/ibuf0ibuf.inl
+++ b/storage/innobase/include/ibuf0ibuf.inl
@@ -64,37 +64,6 @@ ibuf_mtr_commit(
mtr_commit(mtr);
}
-/** Insert buffer struct */
-struct ibuf_t{
- ulint size; /*!< current size of the ibuf index
- tree, in pages */
- ulint max_size; /*!< recommended maximum size of the
- ibuf index tree, in pages */
- ulint seg_size; /*!< allocated pages of the file
- segment containing ibuf header and
- tree */
- bool empty; /*!< Protected by the page
- latch of the root page of the
- insert buffer tree
- (FSP_IBUF_TREE_ROOT_PAGE_NO). true
- if and only if the insert
- buffer tree is empty. */
- ulint free_list_len; /*!< length of the free list */
- ulint height; /*!< tree height */
- dict_index_t* index; /*!< insert buffer index */
-
- /** number of pages merged */
- Atomic_counter<ulint> n_merges;
- Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
- /*!< number of operations of each type
- merged to index pages */
- Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
- /*!< number of operations of each type
- discarded without merging due to the
- tablespace being deleted or the
- index being dropped */
-};
-
/************************************************************************//**
Sets the free bit of the page in the ibuf bitmap. This is done in a separate
mini-transaction, hence this operation does not restrict further work to only
diff --git a/storage/innobase/include/ibuf0types.h b/storage/innobase/include/ibuf0types.h
deleted file mode 100644
index 6b7c47208a0..00000000000
--- a/storage/innobase/include/ibuf0types.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1997, 2009, Oracle and/or its affiliates. All Rights Reserved.
-
-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
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/ibuf0types.h
-Insert buffer global types
-
-Created 7/29/1997 Heikki Tuuri
-*******************************************************/
-
-#ifndef ibuf0types_h
-#define ibuf0types_h
-
-struct ibuf_t;
-
-#endif
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 629ddacdf1b..0f9a4da049b 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, Google Inc.
-Copyright (c) 2017, 2021, MariaDB Corporation.
+Copyright (c) 2017, 2022, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -466,6 +466,11 @@ public:
size_t buf_free;
/** recommended maximum size of buf, after which the buffer is flushed */
size_t max_buf_free;
+
+ /** Log sequence number when a log file overwrite (broken crash recovery)
+ was noticed. Protected by mutex. */
+ lsn_t overwrite_warned;
+
/** mutex to serialize access to the flush list when we are putting
dirty blocks in the list. The idea behind this mutex is to be able
to release log_sys.mutex during mtr_commit and still ensure that
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 7f9bf27c6fb..ffc9b85193f 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -28,6 +28,8 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h"
#include "dyn0buf.h"
+#include "buf0buf.h"
+#include <vector>
/** Start a mini-transaction. */
#define mtr_start(m) (m)->start()
@@ -48,11 +50,6 @@ savepoint. */
@return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
-/** Release an object in the memo stack.
-@return true if released */
-#define mtr_memo_release(m, o, t) \
- (m)->memo_release((o), (t))
-
#ifdef UNIV_PFS_RWLOCK
# define mtr_s_lock_index(i,m) (m)->s_lock(__FILE__, __LINE__, &(i)->lock)
# define mtr_x_lock_index(i,m) (m)->x_lock(__FILE__, __LINE__, &(i)->lock)
@@ -66,19 +63,16 @@ savepoint. */
#define mtr_release_block_at_savepoint(m, s, b) \
(m)->release_block_at_savepoint((s), (b))
-#define mtr_block_sx_latch_at_savepoint(m, s, b) \
- (m)->sx_latch_at_savepoint((s), (b))
-
-#define mtr_block_x_latch_at_savepoint(m, s, b) \
- (m)->x_latch_at_savepoint((s), (b))
-
/** Mini-transaction memo stack slot. */
-struct mtr_memo_slot_t {
- /** pointer to the object */
- void* object;
-
- /** type of the stored object */
- mtr_memo_type_t type;
+struct mtr_memo_slot_t
+{
+ /** pointer to the object, or nullptr if released */
+ void *object;
+ /** type of the stored object */
+ mtr_memo_type_t type;
+
+ /** Release the object */
+ void release() const;
};
/** Mini-transaction handle and buffer */
@@ -89,14 +83,19 @@ struct mtr_t {
/** Commit the mini-transaction. */
void commit();
- /** Release latches till savepoint. To simplify the code only
- MTR_MEMO_S_LOCK and MTR_MEMO_PAGE_S_FIX slot types are allowed to be
- released, otherwise it would be neccesary to add one more argument in the
- function to point out what slot types are allowed for rollback, and this
- would be overengineering as currently the function is used only in one place
- in the code.
- @param savepoint savepoint, can be obtained with get_savepoint */
- void rollback_to_savepoint(ulint savepoint);
+ /** Release latches of unmodified buffer pages.
+ @param begin first slot to release
+ @param end last slot to release, or get_savepoint() */
+ void rollback_to_savepoint(ulint begin, ulint end);
+
+ /** 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()); }
+
+ /** Release the last acquired buffer page latch. */
+ void release_last_page()
+ { 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 */
@@ -117,26 +116,89 @@ struct mtr_t {
void commit_files(lsn_t checkpoint_lsn= 0);
/** @return mini-transaction savepoint (current size of m_memo) */
- ulint get_savepoint() const { ut_ad(is_active()); return m_memo.size(); }
+ ulint get_savepoint() const
+ {
+ ut_ad(is_active());
+ return m_memo ? m_memo->size() : 0;
+ }
- /** Release the (index tree) s-latch stored in an mtr memo after a
- savepoint.
- @param savepoint value returned by @see set_savepoint.
- @param lock latch to release */
- inline void release_s_latch_at_savepoint(
- ulint savepoint,
- index_lock* lock);
+ /** 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)
+ {
+ 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;
+ }
+ }
- /** Release the block in an mtr memo after a savepoint. */
- inline void release_block_at_savepoint(
- ulint savepoint,
- buf_block_t* block);
+ /** @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;
+ }
- /** SX-latch a not yet latched block after a savepoint. */
- inline void sx_latch_at_savepoint(ulint savepoint, buf_block_t* block);
+ /** X-latch a not yet latched block after a savepoint. */
+ void x_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_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);
+ }
- /** X-latch a not yet latched block after a savepoint. */
- inline void x_latch_at_savepoint(ulint savepoint, buf_block_t* block);
+ /** 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);
+ }
/** @return the logging mode */
mtr_log_t get_log_mode() const
@@ -290,19 +352,17 @@ struct mtr_t {
/** Acquire an exclusive tablespace latch.
@param space tablespace */
void x_lock_space(fil_space_t *space);
- /** Release an object in the memo stack.
- @param object object
- @param type object type
- @return bool if lock released */
- bool memo_release(const void *object, ulint type);
- /** Release a page latch.
- @param[in] ptr pointer to within a page frame
- @param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */
- void release_page(const void *ptr, mtr_memo_type_t type);
+
+ /** Release an index latch. */
+ 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);
/** Mark the given latched page as modified.
@param block page that will be modified */
void modify(const buf_block_t& block);
@@ -340,73 +400,93 @@ public:
@param rw_latch RW_S_LATCH, RW_SX_LATCH, RW_X_LATCH, RW_NO_LATCH */
void page_lock(buf_block_t *block, ulint rw_latch);
+ /** Acquire a latch on a buffer-fixed buffer pool block.
+ @param savepoint savepoint location of the buffer-fixed block
+ @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)
{
- mtr_memo_slot_t *slot= m_memo.at<mtr_memo_slot_t*>(savepoint);
- ut_ad(slot->type == MTR_MEMO_BUF_FIX);
- slot->type= MTR_MEMO_PAGE_SX_FIX;
+ 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;
}
/** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block);
- /** Upgrade X lock to X */
+ /** 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
@param shared whether to look for shared latch, instead of exclusive
@return whether space.latch is being held */
- bool memo_contains(const fil_space_t& space, bool shared= false)
+ bool memo_contains(const fil_space_t& space, bool shared= false) const
MY_ATTRIBUTE((warn_unused_result));
#ifdef UNIV_DEBUG
/** Check if we are holding an rw-latch in this mini-transaction
@param lock latch to search for
@param type held latch type
@return whether (lock,type) is contained */
- bool memo_contains(const index_lock &lock, mtr_memo_type_t type)
+ bool memo_contains(const index_lock &lock, mtr_memo_type_t type) const
MY_ATTRIBUTE((warn_unused_result));
- /** Check if memo contains the given item.
- @param object object to search
- @param flags specify types of object (can be ORred) of
- MTR_MEMO_PAGE_S_FIX ... values
- @return true if contains */
- bool memo_contains_flagged(const void* ptr, ulint flags) const;
-
- /** Check if memo contains the given page.
- @param[in] ptr pointer to within buffer frame
- @param[in] flags specify types of object with OR of
- MTR_MEMO_PAGE_S_FIX... values
- @return the block
- @retval NULL if not found */
- buf_block_t* memo_contains_page_flagged(
- const byte* ptr,
- ulint flags) const;
-
- /** @return true if mini-transaction contains modifications. */
- bool has_modifications() const { return m_modifications; }
+ /** Check if memo contains an index or buffer block latch.
+ @param object object to search
+ @param flags specify types of object latches
+ @return true if contains */
+ bool memo_contains_flagged(const void *object, ulint flags) const
+ MY_ATTRIBUTE((warn_unused_result, nonnull));
+
+ /** Check if memo contains the given page.
+ @param ptr pointer to within page frame
+ @param flags types latch to look for
+ @return the block
+ @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. */
+ bool has_modifications() const { return m_modifications; }
#endif /* UNIV_DEBUG */
- /** @return true if a record was added to the mini-transaction */
- bool is_dirty() const { return m_made_dirty; }
-
- /** Push an object to an mtr memo stack.
- @param object object
- @param type object type: MTR_MEMO_S_LOCK, ... */
- inline void memo_push(void* object, mtr_memo_type_t type);
-
- /** Check if this mini-transaction is dirtying a clean page.
- @param block block being x-fixed
- @return true if the mtr is dirtying a clean page. */
- static inline bool is_block_dirtied(const buf_block_t* block)
- MY_ATTRIBUTE((warn_unused_result));
+ /** Push an object to an mtr memo stack.
+ @param object object
+ @param type object type: MTR_MEMO_S_LOCK, ... */
+ void memo_push(void *object, 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});
+ else
+ m_memo->emplace_back(mtr_memo_slot_t{object, type});
+ }
/** @return the size of the log is empty */
size_t get_log_size() const { return m_log.size(); }
/** @return whether the log and memo are empty */
- bool is_empty() const { return m_memo.size() == 0 && m_log.size() == 0; }
+ bool is_empty() const { return !get_savepoint() && !get_log_size(); }
/** Write an OPT_PAGE_CHECKSUM record. */
inline void page_checksum(const buf_page_t &bpage);
@@ -657,6 +737,8 @@ private:
@return {start_lsn,flush_ahead} */
inline std::pair<lsn_t,page_flush_ahead> finish_write(ulint len);
+ /** Release all latches. */
+ void release();
/** Release the resources */
inline void release_resources();
@@ -708,7 +790,7 @@ private:
#endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
- mtr_buf_t m_memo;
+ std::vector<mtr_memo_slot_t> *m_memo= nullptr;
/** mini-transaction log */
mtr_buf_t m_log;
@@ -724,5 +806,3 @@ private:
/** set of freed page ids */
range_set *m_freed_pages= nullptr;
};
-
-#include "mtr0mtr.inl"
diff --git a/storage/innobase/include/mtr0mtr.inl b/storage/innobase/include/mtr0mtr.inl
deleted file mode 100644
index 75be7adc6a5..00000000000
--- a/storage/innobase/include/mtr0mtr.inl
+++ /dev/null
@@ -1,185 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2022, 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
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/mtr0mtr.ic
-Mini-transaction buffer
-
-Created 11/26/1995 Heikki Tuuri
-*******************************************************/
-
-#include "buf0buf.h"
-
-/** Check if a mini-transaction is dirtying a clean page.
-@return true if the mtr is dirtying a clean page. */
-inline bool mtr_t::is_block_dirtied(const buf_block_t *block)
-{
- ut_ad(block->page.in_file());
- ut_ad(block->page.frame);
- ut_ad(block->page.buf_fix_count());
- return block->page.oldest_modification() <= 1 &&
- block->page.id().space() < SRV_TMP_SPACE_ID;
-}
-
-/**
-Pushes an object to an mtr memo stack. */
-void
-mtr_t::memo_push(void* object, mtr_memo_type_t type)
-{
- ut_ad(is_active());
- ut_ad(object != NULL);
- ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
- ut_ad(type <= MTR_MEMO_SPACE_S_LOCK);
- ut_ad(type == MTR_MEMO_PAGE_X_MODIFY || ut_is_2pow(type));
-
- /* 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. */
-
- if (!m_made_dirty
- && (type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX))) {
-
- m_made_dirty = is_block_dirtied(
- reinterpret_cast<const buf_block_t*>(object));
- }
-
- mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
-
- slot->type = type;
- slot->object = object;
-}
-
-/**
-Releases the (index tree) s-latch stored in an mtr memo after a
-savepoint. */
-void
-mtr_t::release_s_latch_at_savepoint(
- ulint savepoint,
- index_lock* lock)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == lock);
- ut_ad(slot->type == MTR_MEMO_S_LOCK);
-
- lock->s_unlock();
-
- slot->object = NULL;
-}
-
-/**
-SX-latches the not yet latched block after a savepoint. */
-
-void
-mtr_t::sx_latch_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- 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<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == block);
-
- /* == RW_NO_LATCH */
- ut_a(slot->type == MTR_MEMO_BUF_FIX);
-
- block->page.lock.u_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty) {
- m_made_dirty = is_block_dirtied(block);
- }
-
- slot->type = MTR_MEMO_PAGE_SX_FIX;
-}
-
-/**
-X-latches the not yet latched block after a savepoint. */
-
-void
-mtr_t::x_latch_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
- ut_ad(m_memo.size() > savepoint);
-
- 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<mtr_memo_slot_t*>(savepoint);
-
- ut_ad(slot->object == block);
-
- /* == RW_NO_LATCH */
- ut_a(slot->type == MTR_MEMO_BUF_FIX);
-
- block->page.lock.x_lock();
- ut_ad(!block->page.is_io_fixed());
-
- if (!m_made_dirty) {
- m_made_dirty = is_block_dirtied(block);
- }
-
- slot->type = MTR_MEMO_PAGE_X_FIX;
-}
-
-/**
-Releases the block in an mtr memo after a savepoint. */
-
-void
-mtr_t::release_block_at_savepoint(
- ulint savepoint,
- buf_block_t* block)
-{
- ut_ad(is_active());
-
- mtr_memo_slot_t *slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
-
- ut_a(slot->object == block);
- 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;
- }
-}
diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h
index 80542299482..28aa30565e4 100644
--- a/storage/innobase/include/page0cur.h
+++ b/storage/innobase/include/page0cur.h
@@ -129,7 +129,6 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
- dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
@@ -143,7 +142,6 @@ rec_t*
page_cur_insert_rec_low(
/*====================*/
const page_cur_t*cur, /*!< in: page cursor */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: record to insert after cur */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -165,7 +163,6 @@ page_cur_insert_rec_zip(
/*====================*/
page_cur_t* cursor, /*!< in/out: page cursor,
logical position unchanged */
- dict_index_t* index, /*!< in: record descriptor */
const rec_t* rec, /*!< in: pointer to a physical record */
rec_offs* offsets,/*!< in/out: rec_get_offsets(rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -177,7 +174,6 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
- const dict_index_t* index, /*!< in: record descriptor */
const rec_offs* offsets,/*!< in: rec_get_offsets(
cursor->rec, index) */
mtr_t* mtr) /*!< in/out: mini-transaction */
@@ -239,8 +235,6 @@ Searches the right position for a page cursor. */
bool
page_cur_search_with_match(
/*=======================*/
- const buf_block_t* block, /*!< in: buffer block */
- const dict_index_t* index, /*!< in: record descriptor */
const dtuple_t* tuple, /*!< in: data tuple */
page_cur_mode_t mode, /*!< in: PAGE_CUR_L,
PAGE_CUR_LE, PAGE_CUR_G, or
@@ -251,13 +245,11 @@ page_cur_search_with_match(
ulint* ilow_matched_fields,
/*!< in/out: already matched
fields in lower limit record */
- page_cur_t* cursor, /*!< out: page cursor */
+ page_cur_t* cursor, /*!< in/out: page cursor */
rtr_info_t* rtr_info);/*!< in/out: rtree search stack */
#ifdef BTR_CUR_HASH_ADAPT
MY_ATTRIBUTE((warn_unused_result))
/** Search the right position for a page cursor.
-@param[in] block buffer block
-@param[in] index index tree
@param[in] tuple key to be searched for
@param[in] mode search mode
@param[in,out] iup_matched_fields already matched fields in the
@@ -268,11 +260,9 @@ first partially matched field in the upper limit record
lower limit record
@param[in,out] ilow_matched_bytes already matched bytes in the
first partially matched field in the lower limit record
-@param[out] cursor page cursor */
+@param[in,out] cursor page cursor */
bool
page_cur_search_with_match_bytes(
- const buf_block_t* block,
- const dict_index_t* index,
const dtuple_t* tuple,
page_cur_mode_t mode,
ulint* iup_matched_fields,
@@ -284,16 +274,12 @@ page_cur_search_with_match_bytes(
/***********************************************************//**
Positions a page cursor on a randomly chosen user record on a page. If there
are no user records, sets the cursor on the infimum record. */
-void
-page_cur_open_on_rnd_user_rec(
-/*==========================*/
- buf_block_t* block, /*!< in: page */
- page_cur_t* cursor);/*!< out: page cursor */
+void page_cur_open_on_rnd_user_rec(page_cur_t *cursor);
/** Index page cursor */
struct page_cur_t{
- const dict_index_t* index;
+ dict_index_t* index;
rec_t* rec; /*!< pointer to a record on page */
rec_offs* offsets;
buf_block_t* block; /*!< pointer to the block containing rec */
diff --git a/storage/innobase/include/page0cur.inl b/storage/innobase/include/page0cur.inl
index 8f69dc22878..1638b5749ff 100644
--- a/storage/innobase/include/page0cur.inl
+++ b/storage/innobase/include/page0cur.inl
@@ -167,14 +167,12 @@ page_cur_tuple_insert(
/*==================*/
page_cur_t* cursor, /*!< in/out: a page cursor */
const dtuple_t* tuple, /*!< in: pointer to a data tuple */
- dict_index_t* index, /*!< in: record descriptor */
rec_offs** offsets,/*!< out: offsets on *rec */
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
ulint n_ext, /*!< in: number of externally stored columns */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- rec_t* rec;
- ulint size = rec_get_converted_size(index, tuple, n_ext);
+ ulint size = rec_get_converted_size(cursor->index, tuple, n_ext);
if (!*heap) {
*heap = mem_heap_create(size
@@ -183,21 +181,20 @@ page_cur_tuple_insert(
* sizeof **offsets);
}
- rec = rec_convert_dtuple_to_rec((byte*) mem_heap_alloc(*heap, size),
- index, tuple, n_ext);
+ rec_t* rec = rec_convert_dtuple_to_rec(
+ static_cast<byte*>(mem_heap_alloc(*heap, size)),
+ cursor->index, tuple, n_ext);
- *offsets = rec_get_offsets(rec, index, *offsets,
+ *offsets = rec_get_offsets(rec, cursor->index, *offsets,
page_is_leaf(cursor->block->page.frame)
- ? index->n_core_fields : 0,
+ ? cursor->index->n_core_fields : 0,
ULINT_UNDEFINED, heap);
ut_ad(size == rec_offs_size(*offsets));
if (is_buf_block_get_page_zip(cursor->block)) {
- rec = page_cur_insert_rec_zip(
- cursor, index, rec, *offsets, mtr);
+ rec = page_cur_insert_rec_zip(cursor, rec, *offsets, mtr);
} else {
- rec = page_cur_insert_rec_low(cursor,
- index, rec, *offsets, mtr);
+ rec = page_cur_insert_rec_low(cursor, rec, *offsets, mtr);
}
ut_ad(!rec || !cmp_dtuple_rec(tuple, rec, *offsets));
diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h
index 25c09258b3c..1f8af6030d1 100644
--- a/storage/innobase/include/row0ins.h
+++ b/storage/innobase/include/row0ins.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2021, MariaDB Corporation.
+Copyright (c) 2017, 2022, 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
@@ -78,7 +78,7 @@ dberr_t
row_ins_clust_index_entry_low(
/*==========================*/
ulint flags, /*!< in: undo logging and locking flags */
- ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */
@@ -94,13 +94,13 @@ same fields is found, the other record is necessarily marked deleted.
It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
-@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
+@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
@return error code */
dberr_t
row_ins_sec_index_entry_low(
/*========================*/
ulint flags, /*!< in: undo logging and locking flags */
- ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */
diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h
index 1e0fdc65238..a1350740e2a 100644
--- a/storage/innobase/include/row0row.h
+++ b/storage/innobase/include/row0row.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2020, MariaDB Corporation.
+Copyright (c) 2016, 2022, 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
@@ -303,13 +303,13 @@ row_build_row_ref_fast(
/***************************************************************//**
Searches the clustered index record for a row, if we have the row
reference.
-@return TRUE if found */
-ibool
+@return true if found */
+bool
row_search_on_row_ref(
/*==================*/
btr_pcur_t* pcur, /*!< out: persistent cursor, which must
be closed by the caller */
- ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const dict_table_t* table, /*!< in: table */
const dtuple_t* ref, /*!< in: row reference */
mtr_t* mtr) /*!< in/out: mtr */
@@ -321,7 +321,7 @@ on the secondary index record are preserved.
rec_t*
row_get_clust_rec(
/*==============*/
- ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
const rec_t* rec, /*!< in: record in a secondary index */
dict_index_t* index, /*!< in: secondary index */
dict_index_t** clust_index,/*!< out: clustered index */
@@ -363,9 +363,8 @@ Searches an index record.
enum row_search_result
row_search_index_entry(
/*===================*/
- dict_index_t* index, /*!< in: index */
const dtuple_t* entry, /*!< in: index entry */
- ulint mode, /*!< in: BTR_MODIFY_LEAF, ... */
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF, ... */
btr_pcur_t* pcur, /*!< in/out: persistent cursor, which must
be closed by the caller */
mtr_t* mtr) /*!< in: mtr */