summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/atomic/disabled.def13
-rw-r--r--storage/innobase/btr/btr0btr.cc52
-rw-r--r--storage/innobase/btr/btr0cur.cc7
-rw-r--r--storage/innobase/btr/btr0sea.cc39
-rw-r--r--storage/innobase/buf/buf0buf.cc12
-rw-r--r--storage/innobase/include/btr0sea.h17
-rw-r--r--storage/innobase/include/mtr0mtr.h13
-rw-r--r--storage/innobase/log/log0recv.cc27
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc36
9 files changed, 162 insertions, 54 deletions
diff --git a/mysql-test/suite/atomic/disabled.def b/mysql-test/suite/atomic/disabled.def
deleted file mode 100644
index 6d8defe344a..00000000000
--- a/mysql-test/suite/atomic/disabled.def
+++ /dev/null
@@ -1,13 +0,0 @@
-##############################################################################
-#
-# List the test cases that are to be disabled temporarily.
-#
-# Separate the test case name and the comment with ':'.
-#
-# <testcasename> : BUG#<xxxx> <date disabled> <disabler> <comment>
-#
-# Do not use any TAB characters for whitespace.
-#
-##############################################################################
-
-rename_trigger : MDEV-29282 atomic.rename_trigger fails occasionly
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 7334a2e1757..9ce96f66e64 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -513,9 +513,28 @@ btr_page_alloc_low(
page should be initialized. */
dberr_t* err) /*!< out: error code */
{
- buf_block_t *root= btr_root_block_get(index, RW_SX_LATCH, mtr, err);
+ const auto savepoint= mtr->get_savepoint();
+ buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, err);
if (UNIV_UNLIKELY(!root))
return root;
+
+ if (mtr->have_u_or_x_latch(*root))
+ {
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!root->index || !root->index->freed());
+#endif
+ mtr->release_block_at_savepoint(savepoint, root);
+ }
+ else
+ {
+ mtr->u_lock_register(savepoint);
+ root->page.lock.u_lock();
+#ifdef BTR_CUR_HASH_ADAPT
+ if (root->index)
+ mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX);
+#endif
+ }
+
fseg_header_t *seg_header= root->page.frame +
(level ? PAGE_HEADER + PAGE_BTR_SEG_TOP : PAGE_HEADER + PAGE_BTR_SEG_LEAF);
return fseg_alloc_free_page_general(seg_header, hint_page_no, file_direction,
@@ -584,8 +603,8 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
bool blob, bool space_latched)
{
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
-#ifdef BTR_CUR_HASH_ADAPT
- if (block->index && !block->index->freed())
+#if defined BTR_CUR_HASH_ADAPT && defined UNIV_DEBUG
+ if (btr_search_check_marked_free_index(block))
{
ut_ad(!blob);
ut_ad(page_is_leaf(block->page.frame));
@@ -610,11 +629,30 @@ dberr_t btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
fil_space_t *space= index->table->space;
dberr_t err;
- if (page_t* root = btr_root_get(index, mtr, &err))
+
+ const auto savepoint= mtr->get_savepoint();
+ if (buf_block_t *root= btr_root_block_get(index, RW_NO_LATCH, mtr, &err))
{
- err= fseg_free_page(&root[blob || page_is_leaf(block->page.frame)
- ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
- : PAGE_HEADER + PAGE_BTR_SEG_TOP],
+ if (mtr->have_u_or_x_latch(*root))
+ {
+#ifdef BTR_CUR_HASH_ADAPT
+ ut_ad(!root->index || !root->index->freed());
+#endif
+ mtr->release_block_at_savepoint(savepoint, root);
+ }
+ else
+ {
+ mtr->u_lock_register(savepoint);
+ root->page.lock.u_lock();
+#ifdef BTR_CUR_HASH_ADAPT
+ if (root->index)
+ mtr_t::defer_drop_ahi(root, MTR_MEMO_PAGE_SX_FIX);
+#endif
+ }
+ err= fseg_free_page(&root->page.frame[blob ||
+ page_is_leaf(block->page.frame)
+ ? PAGE_HEADER + PAGE_BTR_SEG_LEAF
+ : PAGE_HEADER + PAGE_BTR_SEG_TOP],
space, page, mtr, space_latched);
}
if (err == DB_SUCCESS)
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 7a9480cdf4e..4272c760f8d 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -283,7 +283,7 @@ latch_block:
block->page.fix();
block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
- ut_ad(!block->index || !block->index->freed());
+ ut_ad(!btr_search_check_marked_free_index(block));
#endif
if (UNIV_LIKELY_NULL(rtr_info)) {
@@ -7024,7 +7024,8 @@ btr_store_big_rec_extern_fields(
rec_block->page.fix();
rec_block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
- ut_ad(!rec_block->index || !rec_block->index->freed());
+ ut_ad(!btr_search_check_marked_free_index(
+ rec_block));
#endif
uint32_t hint_prev = prev_page_no;
@@ -7401,7 +7402,7 @@ skip_free:
block->fix();
block->page.lock.x_lock();
#ifdef BTR_CUR_HASH_ADAPT
- ut_ad(!block->index || !block->index->freed());
+ ut_ad(!btr_search_check_marked_free_index(block));
#endif
const page_t* page = buf_block_get_frame(ext_block);
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 137a8b10d9f..4fb3cfd5f68 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -1279,8 +1279,11 @@ fail_and_release_page:
index page for which we know that
block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash
- i.e.: it is in state BUF_BLOCK_REMOVE_HASH */
-void btr_search_drop_page_hash_index(buf_block_t* block)
+ i.e.: it is in state BUF_BLOCK_REMOVE_HASH
+@param[in] garbage_collect drop ahi only if the index is marked
+ as freed */
+void btr_search_drop_page_hash_index(buf_block_t* block,
+ bool garbage_collect)
{
ulint n_fields;
ulint n_bytes;
@@ -1316,13 +1319,21 @@ retry:
auto part = btr_search_sys.get_part(index_id,
block->page.id().space());
+ part->latch.rd_lock(SRW_LOCK_CALL);
+
dict_index_t* index = block->index;
bool is_freed = index && index->freed();
if (is_freed) {
+ part->latch.rd_unlock();
part->latch.wr_lock(SRW_LOCK_CALL);
- } else {
- part->latch.rd_lock(SRW_LOCK_CALL);
+ if (index != block->index) {
+ part->latch.wr_unlock();
+ goto retry;
+ }
+ } else if (garbage_collect) {
+ part->latch.rd_unlock();
+ return;
}
assert_block_ahi_valid(block);
@@ -1797,12 +1808,13 @@ drop_exit:
return;
}
+ ahi_latch->rd_lock(SRW_LOCK_CALL);
+
if (index->freed()) {
+ ahi_latch->rd_unlock();
goto drop_exit;
}
- ahi_latch->rd_lock(SRW_LOCK_CALL);
-
if (block->index) {
uint16_t n_fields = block->curr_n_fields;
uint16_t n_bytes = block->curr_n_bytes;
@@ -2394,5 +2406,20 @@ btr_search_validate()
return(true);
}
+#ifdef UNIV_DEBUG
+bool btr_search_check_marked_free_index(const buf_block_t *block)
+{
+ if (!block->index)
+ return false;
+
+ btr_search_s_lock_all();
+
+ bool is_freed = block->index && block->index->freed();
+
+ btr_search_s_unlock_all();
+
+ return is_freed;
+}
+#endif
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 42055246a12..c26bbda9473 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -2761,11 +2761,7 @@ re_evict:
&& state < buf_page_t::WRITE_FIX));
#ifdef BTR_CUR_HASH_ADAPT
- if (dict_index_t* index = block->index) {
- if (index->freed()) {
- btr_search_drop_page_hash_index(block);
- }
- }
+ btr_search_drop_page_hash_index(block, true);
#endif /* BTR_CUR_HASH_ADAPT */
dberr_t e;
@@ -2823,10 +2819,8 @@ get_latch:
}
get_latch_valid:
#ifdef BTR_CUR_HASH_ADAPT
- if (dict_index_t* index = block->index) {
- if (index->freed()) {
- mtr_t::defer_drop_ahi(block, fix_type);
- }
+ if (block->index) {
+ mtr_t::defer_drop_ahi(block, fix_type);
}
#endif /* BTR_CUR_HASH_ADAPT */
mtr->memo_push(block, fix_type);
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index 106582286a9..c66e412c27c 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -100,8 +100,11 @@ btr_search_move_or_delete_hash_entries(
index page for which we know that
block->buf_fix_count == 0 or it is an index page which
has already been removed from the buf_pool.page_hash
- i.e.: it is in state BUF_BLOCK_REMOVE_HASH */
-void btr_search_drop_page_hash_index(buf_block_t* block);
+ i.e.: it is in state BUF_BLOCK_REMOVE_HASH
+@param[in] garbage_collect drop ahi only if the index is marked
+ as freed */
+void btr_search_drop_page_hash_index(buf_block_t* block,
+ bool garbage_collect= false);
/** Drop possible adaptive hash index entries when a page is evicted
from the buffer pool or freed in a file, or the index is being dropped.
@@ -146,16 +149,24 @@ static inline void btr_search_s_lock_all();
/** Unlock all search latches from shared mode. */
static inline void btr_search_s_unlock_all();
+#ifdef UNIV_DEBUG
+/** @return if the index is marked as freed */
+bool btr_search_check_marked_free_index(const buf_block_t *block);
+#endif /* UNIV_DEBUG */
+
#else /* BTR_CUR_HASH_ADAPT */
# define btr_search_sys_create()
# define btr_search_sys_free()
-# define btr_search_drop_page_hash_index(block)
+# define btr_search_drop_page_hash_index(block,garbage_collect)
# define btr_search_s_lock_all(index)
# define btr_search_s_unlock_all(index)
# define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block)
# define btr_search_update_hash_on_insert(cursor, ahi_latch)
# define btr_search_update_hash_on_delete(cursor)
+#ifdef UNIV_DEBUG
+# define btr_search_check_marked_free_index(block)
+#endif /* UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
#ifdef BTR_CUR_ADAPT
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 8a3fe59ac59..edf583aa466 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -177,6 +177,10 @@ struct mtr_t {
@param block buffer pool block to search for */
bool have_x_latch(const buf_block_t &block) const;
+ /** Check if we are holding a block latch in S or U mode
+ @param block buffer pool block to search for */
+ bool have_u_or_x_latch(const buf_block_t &block) const;
+
/** Copy the tablespaces associated with the mini-transaction
(needed for generating FILE_MODIFY records)
@param[in] mtr mini-transaction that may modify
@@ -336,6 +340,15 @@ 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);
+ /** 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;
+ }
+
/** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block);
/** Upgrade X lock to X */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 9b6f778b859..ff0858a2a70 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -829,7 +829,29 @@ processed:
fil_space_t *space= fil_space_t::create(it->first, flags,
FIL_TYPE_TABLESPACE, crypt_data);
ut_ad(space);
- space->add(name.c_str(), OS_FILE_CLOSED, size, false, false);
+ const char* filename= name.c_str();
+ if (srv_operation == SRV_OPERATION_RESTORE)
+ {
+ const char* tbl_name = strrchr(filename, '/');
+#ifdef _WIN32
+ if (const char *last = strrchr(filename, '\\'))
+ {
+ if (last > tbl_name)
+ tbl_name = last;
+ }
+#endif
+ if (tbl_name)
+ {
+ while (--tbl_name > filename
+#ifdef _WIN32
+ && *tbl_name != '\\'
+#endif
+ && *tbl_name != '/');
+ if (tbl_name > filename)
+ filename = tbl_name + 1;
+ }
+ }
+ space->add(filename, OS_FILE_CLOSED, size, false, false);
space->recv_size= it->second.size;
space->size_in_header= size;
return space;
@@ -1227,9 +1249,6 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id,
d->deleted = true;
goto got_deleted;
}
- if (ftype == FILE_RENAME) {
- d->file_name= fname.name;
- }
goto reload;
}
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 594982f07c2..c4236883632 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -1220,6 +1220,21 @@ struct FindBlockX
}
};
+/** Find out whether a block was not X or U latched by the mini-transaction */
+struct FindBlockUX
+{
+ const buf_block_t &block;
+
+ FindBlockUX(const buf_block_t &block): block(block) {}
+
+ /** @return whether the block was not found x-latched */
+ bool operator()(const mtr_memo_slot_t *slot) const
+ {
+ return slot->object != &block ||
+ !(slot->type & (MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX));
+ }
+};
+
#ifdef UNIV_DEBUG
/** Assert that the block is not present in the mini-transaction */
struct FindNoBlock
@@ -1250,6 +1265,14 @@ bool mtr_t::have_x_latch(const buf_block_t &block) const
return true;
}
+bool mtr_t::have_u_or_x_latch(const buf_block_t &block) const
+{
+ if (m_memo.for_each_block(CIterate<FindBlockUX>(FindBlockUX(block))))
+ return false;
+ ut_ad(block.page.lock.have_u_or_x());
+ return true;
+}
+
/** Check if we are holding exclusive tablespace latch
@param space tablespace to search for
@param shared whether to look for shared latch, instead of exclusive
@@ -1282,18 +1305,14 @@ void mtr_t::defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type)
/* Temporarily release our S-latch. */
block->page.lock.s_unlock();
block->page.lock.x_lock();
- if (dict_index_t *index= block->index)
- if (index->freed())
- btr_search_drop_page_hash_index(block);
+ btr_search_drop_page_hash_index(block, true);
block->page.lock.x_unlock();
block->page.lock.s_lock();
ut_ad(!block->page.is_read_fixed());
break;
case MTR_MEMO_PAGE_SX_FIX:
block->page.lock.u_x_upgrade();
- if (dict_index_t *index= block->index)
- if (index->freed())
- btr_search_drop_page_hash_index(block);
+ btr_search_drop_page_hash_index(block, true);
block->page.lock.x_u_downgrade();
break;
case MTR_MEMO_PAGE_X_FIX:
@@ -1383,9 +1402,8 @@ void mtr_t::page_lock(buf_block_t *block, ulint rw_latch)
}
#ifdef BTR_CUR_HASH_ADAPT
- if (dict_index_t *index= block->index)
- if (index->freed())
- defer_drop_ahi(block, fix_type);
+ if (block->index)
+ defer_drop_ahi(block, fix_type);
#endif /* BTR_CUR_HASH_ADAPT */
done: