summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-03-30 21:36:56 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-03-30 21:36:56 +0300
commit04bac13b30df18e90a72b9454ac36bc264792974 (patch)
tree0c92eda85ae1d783b1897b817b0c14e80d044890
parente895041ba915b4b01f35755d569038abba06d4a7 (diff)
downloadmariadb-git-04bac13b30df18e90a72b9454ac36bc264792974.tar.gz
Revert "MDEV-12266: Remove lookups when dropping indexes"
This reverts commit d2660362920a82588508028f263dad9c16f08865. The patch would cause a crash when DROP TABLE is executed and the .ibd file is missing. It is not easy to fix this; there is some delicate logic in fil_space_get_page_size().
-rw-r--r--storage/innobase/btr/btr0btr.cc111
-rw-r--r--storage/innobase/dict/dict0crea.cc36
-rw-r--r--storage/innobase/include/btr0btr.h12
-rw-r--r--storage/innobase/row/row0trunc.cc6
4 files changed, 90 insertions, 75 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 785c5fc2efd..07cec1844a6 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -1140,8 +1140,8 @@ btr_free_root_invalidate(
}
/** Prepare to free a B-tree.
-@param[in,out] space tablespace
-@param[in] page root page number
+@param[in] page_id page id
+@param[in] page_size page size
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction
@return root block, to invoke btr_free_but_not_root() and btr_free_root()
@@ -1149,32 +1149,32 @@ btr_free_root_invalidate(
static MY_ATTRIBUTE((warn_unused_result))
buf_block_t*
btr_free_root_check(
- fil_space_t* space,
- ulint page,
- index_id_t index_id,
- mtr_t* mtr)
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ index_id_t index_id,
+ mtr_t* mtr)
{
- ut_ad(space->purpose == FIL_TYPE_TABLESPACE);
+ ut_ad(page_id.space() != SRV_TMP_SPACE_ID);
ut_ad(index_id != BTR_FREED_INDEX_ID);
- if (buf_block_t* block = buf_page_get(
- page_id_t(space->id, page), page_size_t(space->flags),
- RW_X_LATCH, mtr)) {
+ buf_block_t* block = buf_page_get(
+ page_id, page_size, RW_X_LATCH, mtr);
+
+ if (block) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
- if (!fil_page_index_page_check(block->frame)
- || index_id != btr_page_get_index_id(block->frame)) {
- return NULL;
+ if (fil_page_index_page_check(block->frame)
+ && index_id == btr_page_get_index_id(block->frame)) {
+ /* This should be a root page.
+ It should not be possible to reassign the same
+ index_id for some other index in the tablespace. */
+ ut_ad(page_is_root(block->frame));
+ } else {
+ block = NULL;
}
-
- /* This should be a root page.
- It should not be possible to reassign the same
- index_id for some other index in the tablespace. */
- ut_ad(page_is_root(block->frame));
- return block;
}
- return NULL;
+ return(block);
}
/** Create the root node for a new index tree.
@@ -1348,26 +1348,29 @@ btr_create(
/** Free a B-tree except the root page. The root page MUST be freed after
this by calling btr_free_root.
-@param[in,out] space tablespace, or NULL
@param[in,out] block root page
@param[in] log_mode mtr logging mode */
static
void
btr_free_but_not_root(
- fil_space_t* space,
buf_block_t* block,
mtr_log_t log_mode)
{
ibool finished;
mtr_t mtr;
- page_t* root = block->frame;
- ut_ad(page_is_root(root));
- ut_ad(!space || block->page.id.space() == space->id);
+ ut_ad(page_is_root(block->frame));
leaf_loop:
- mtr.start();
- mtr.set_log_mode(log_mode);
- if (space) mtr.set_named_space(space);
+ mtr_start(&mtr);
+ mtr_set_log_mode(&mtr, log_mode);
+ mtr.set_named_space_id(block->page.id.space());
+
+ page_t* root = block->frame;
+
+ if (!root) {
+ mtr_commit(&mtr);
+ return;
+ }
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
@@ -1381,15 +1384,18 @@ leaf_loop:
finished = fseg_free_step(root + PAGE_HEADER + PAGE_BTR_SEG_LEAF,
true, &mtr);
- mtr.commit();
+ mtr_commit(&mtr);
if (!finished) {
+
goto leaf_loop;
}
top_loop:
- mtr.start();
- mtr.set_log_mode(log_mode);
- if (space) mtr.set_named_space(space);
+ mtr_start(&mtr);
+ mtr_set_log_mode(&mtr, log_mode);
+ mtr.set_named_space_id(block->page.id.space());
+
+ root = block->frame;
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
@@ -1398,7 +1404,7 @@ top_loop:
finished = fseg_free_step_not_header(
root + PAGE_HEADER + PAGE_BTR_SEG_TOP, true, &mtr);
- mtr.commit();
+ mtr_commit(&mtr);
if (!finished) {
goto top_loop;
@@ -1406,25 +1412,29 @@ top_loop:
}
/** Free a persistent index tree if it exists.
-@param[in,out] space tablespace
-@param[in] page root page number
+@param[in] page_id root page id
+@param[in] page_size page size
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
- fil_space_t* space,
- ulint page,
- index_id_t index_id,
- mtr_t* mtr)
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ index_id_t index_id,
+ mtr_t* mtr)
{
- if (buf_block_t* root = btr_free_root_check(space, page, index_id,
- mtr)) {
- ut_ad(page_is_root(root->frame));
- btr_free_but_not_root(space, root, mtr->get_log_mode());
- mtr->set_named_space(space);
- btr_free_root(root, mtr);
- btr_free_root_invalidate(root, mtr);
+ buf_block_t* root = btr_free_root_check(
+ page_id, page_size, index_id, mtr);
+
+ if (root == NULL) {
+ return;
}
+
+ ut_ad(page_is_root(root->frame));
+ btr_free_but_not_root(root, mtr->get_log_mode());
+ mtr->set_named_space_id(page_id.space());
+ btr_free_root(root, mtr);
+ btr_free_root_invalidate(root, mtr);
}
/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
@@ -1439,10 +1449,13 @@ btr_free(
mtr.start();
mtr.set_log_mode(MTR_LOG_NO_REDO);
- if (buf_block_t* block = buf_page_get(page_id, page_size, RW_X_LATCH,
- &mtr)) {
+ buf_block_t* block = buf_page_get(
+ page_id, page_size, RW_X_LATCH, &mtr);
+
+ if (block) {
ut_ad(page_is_root(block->frame));
- btr_free_but_not_root(NULL, block, MTR_LOG_NO_REDO);
+
+ btr_free_but_not_root(block, MTR_LOG_NO_REDO);
btr_free_root(block, &mtr);
}
mtr.commit();
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 57c48044681..9d664913cc3 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -911,6 +911,7 @@ dict_drop_index_tree(
{
const byte* ptr;
ulint len;
+ ulint space;
ulint root_page_no;
ut_ad(mutex_own(&dict_sys->mutex));
@@ -937,36 +938,35 @@ dict_drop_index_tree(
ut_ad(len == 4);
- ulint space_id = mach_read_from_4(ptr);
+ space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
ptr = rec_get_nth_field_old(
rec, DICT_FLD__SYS_INDEXES__ID, &len);
ut_ad(len == 8);
+ bool found;
+ const page_size_t page_size(fil_space_get_page_size(space,
+ &found));
+
+ if (!found) {
+ /* It is a single table tablespace and the .ibd file is
+ missing: do nothing */
+
+ return(false);
+ }
+
/* If tablespace is scheduled for truncate, do not try to drop
the indexes in that tablespace. There is a truncate fixup action
which will take care of it. */
- if (srv_is_tablespace_truncated(space_id)) {
- return false;
+ if (srv_is_tablespace_truncated(space)) {
+ return(false);
}
- /* We cannot use fil_space_acquire_silent() here,
- because it would return NULL due to the pending
- DROP or TRUNCATE operation. */
- mutex_enter(&fil_system.mutex);
-
- if (fil_space_t* space = fil_space_get_by_id(space_id)) {
- space->n_pending_ops++;
- mutex_exit(&fil_system.mutex);
- btr_free_if_exists(space, root_page_no,
- mach_read_from_8(ptr), mtr);
- fil_space_release(space);
- return true;
- }
+ btr_free_if_exists(page_id_t(space, root_page_no), page_size,
+ mach_read_from_8(ptr), mtr);
- mutex_exit(&fil_system.mutex);
- return false;
+ return(true);
}
/*******************************************************************//**
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 4cb5fc5451f..a4f93280ff1 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -373,16 +373,16 @@ btr_create(
mtr_t* mtr);
/** Free a persistent index tree if it exists.
-@param[in,out] space tablespace
-@param[in] page root page number
+@param[in] page_id root page id
+@param[in] page_size page size
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
- fil_space_t* space,
- ulint page,
- index_id_t index_id,
- mtr_t* mtr);
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ index_id_t index_id,
+ mtr_t* mtr);
/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
@param[in] page_id root page id
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc
index deeac4f52a7..b3a996d990a 100644
--- a/storage/innobase/row/row0trunc.cc
+++ b/storage/innobase/row/row0trunc.cc
@@ -3021,8 +3021,10 @@ void truncate_t::drop_indexes(fil_space_t* space) const
}
if (root_page_no != FIL_NULL) {
- btr_free_if_exists(space, root_page_no, it->m_id,
- &mtr);
+ const page_id_t root_page_id(space->id, root_page_no);
+
+ btr_free_if_exists(
+ root_page_id, page_size, it->m_id, &mtr);
}
/* If tree is already freed then we might return immediately