diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-03-30 21:36:56 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-03-30 21:36:56 +0300 |
commit | 04bac13b30df18e90a72b9454ac36bc264792974 (patch) | |
tree | 0c92eda85ae1d783b1897b817b0c14e80d044890 | |
parent | e895041ba915b4b01f35755d569038abba06d4a7 (diff) | |
download | mariadb-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.cc | 111 | ||||
-rw-r--r-- | storage/innobase/dict/dict0crea.cc | 36 | ||||
-rw-r--r-- | storage/innobase/include/btr0btr.h | 12 | ||||
-rw-r--r-- | storage/innobase/row/row0trunc.cc | 6 |
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 |