diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-04-22 13:29:48 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-04-22 13:29:48 +0300 |
commit | 64ef8caa5416f1eb85423b5868b9db6184e3bebc (patch) | |
tree | e0f9b812a5a0035f42ded0c55f816f186bd98367 | |
parent | 54c460ace606157f2a23706ec98e9de70aba767e (diff) | |
parent | 9f3fe6ad4de262be48413b38719bcb4151746629 (diff) | |
download | mariadb-git-bb-10.6-MDEV-24589.tar.gz |
Merge 10.5 into 10.6bb-10.6-MDEV-24589
-rw-r--r-- | mysql-test/main/flush_read_lock.result | 11 | ||||
-rw-r--r-- | mysql-test/main/flush_read_lock.test | 17 | ||||
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 39 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 131 | ||||
-rw-r--r-- | storage/innobase/fut/fut0lst.cc | 30 | ||||
-rw-r--r-- | storage/innobase/include/fut0fut.h | 17 |
6 files changed, 142 insertions, 103 deletions
diff --git a/mysql-test/main/flush_read_lock.result b/mysql-test/main/flush_read_lock.result index 169b68b90c4..948b4fb062b 100644 --- a/mysql-test/main/flush_read_lock.result +++ b/mysql-test/main/flush_read_lock.result @@ -1392,19 +1392,22 @@ insert into t3_trans values (1); xa end 'test1'; xa prepare 'test1'; # Disconnect temporary connection +set debug_sync='thread_end SIGNAL test1_prepare'; disconnect con_tmp; +connection con1; +set debug_sync='now WAIT_FOR test1_prepare'; # Create temporary connection for XA transaction. -connect con_tmp,localhost,root,,; +connect con_tmp1,localhost,root,,; xa start 'test2'; insert into t3_trans values (2); xa end 'test2'; xa prepare 'test2'; # Disconnect temporary connection -set debug_sync='thread_end SIGNAL detached'; -disconnect con_tmp; +set debug_sync='thread_end SIGNAL test2_prepare'; +disconnect con_tmp1; # Switching to connection 'con1'. connection con1; -set debug_sync='now WAIT_FOR detached'; +set debug_sync='now WAIT_FOR test2_prepare'; flush tables with read lock; # Switching to connection 'default'. connection default; diff --git a/mysql-test/main/flush_read_lock.test b/mysql-test/main/flush_read_lock.test index c92d583e3a9..f24f6e389f1 100644 --- a/mysql-test/main/flush_read_lock.test +++ b/mysql-test/main/flush_read_lock.test @@ -1703,25 +1703,34 @@ insert into t3_trans values (1); xa end 'test1'; xa prepare 'test1'; --echo # Disconnect temporary connection +set debug_sync='thread_end SIGNAL test1_prepare'; disconnect con_tmp; +connection $con_aux1; +set debug_sync='now WAIT_FOR test1_prepare'; + + --echo # Create temporary connection for XA transaction. -connect (con_tmp,localhost,root,,); +connect (con_tmp1,localhost,root,,); xa start 'test2'; insert into t3_trans values (2); xa end 'test2'; xa prepare 'test2'; --echo # Disconnect temporary connection -set debug_sync='thread_end SIGNAL detached'; -disconnect con_tmp; +set debug_sync='thread_end SIGNAL test2_prepare'; +disconnect con_tmp1; + + --echo # Switching to connection '$con_aux1'. connection $con_aux1; -set debug_sync='now WAIT_FOR detached'; +set debug_sync='now WAIT_FOR test2_prepare'; flush tables with read lock; + --echo # Switching to connection 'default'. connection default; --echo # Send XA ROLLBACK 'test1' --send xa rollback 'test1' --echo # Switching to connection '$con_aux1'. + connection $con_aux1; --echo # Wait until XA ROLLBACK is blocked. let $wait_condition= diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 19c280eea90..9bfa7beee2d 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -960,10 +960,14 @@ btr_free_root_check( ut_ad(page_id.space() != SRV_TMP_SPACE_ID); ut_ad(index_id != BTR_FREED_INDEX_ID); - buf_block_t* block = buf_page_get( - page_id, zip_size, RW_X_LATCH, mtr); + buf_block_t* block = buf_page_get_gen( + page_id, zip_size, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, + mtr); - if (block) { + if (!block) { + } else if (block->page.status == buf_page_t::FREED) { + block = NULL; + } else { if (fil_page_index_page_check(block->frame) && index_id == btr_page_get_index_id(block->frame)) { /* This should be a root page. @@ -1230,23 +1234,20 @@ void dict_index_t::clear(que_thr_t *thr) @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] index_id PAGE_INDEX_ID contents @param[in,out] mtr mini-transaction */ -void -btr_free_if_exists( - const page_id_t page_id, - ulint zip_size, - index_id_t index_id, - mtr_t* mtr) +void btr_free_if_exists(const page_id_t page_id, ulint zip_size, + index_id_t index_id, mtr_t *mtr) { - buf_block_t* root = btr_free_root_check( - page_id, zip_size, index_id, mtr); - - if (root == NULL) { - return; - } - - btr_free_but_not_root(root, mtr->get_log_mode()); - mtr->set_named_space_id(page_id.space()); - btr_free_root(root, mtr); + if (fil_space_t *space= fil_space_t::get(page_id.space())) + { + if (buf_block_t *root= btr_free_root_check(page_id, zip_size, index_id, + mtr)) + { + btr_free_but_not_root(root, mtr->get_log_mode()); + mtr->set_named_space(space); + btr_free_root(root, mtr); + } + space->release(); + } } /** Free an index tree in a temporary tablespace. diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index defdb35b575..cb7bc46b046 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -434,6 +434,7 @@ extent descriptor resides is x-locked. @param[in] space tablespace @param[in] lst_node file address of the list node contained in the descriptor +@param[in] mode BUF_GET or BUF_GET_POSSIBLY_FREED @param[out] block extent descriptor block @param[in,out] mtr mini-transaction @return pointer to the extent descriptor */ @@ -443,13 +444,14 @@ xdes_t* xdes_lst_get_descriptor( const fil_space_t* space, fil_addr_t lst_node, + ulint mode, buf_block_t** block, mtr_t* mtr) { - ut_ad(mtr->memo_contains(*space)); - return fut_get_ptr(space->id, space->zip_size(), - lst_node, RW_SX_LATCH, mtr, block) - - XDES_FLST_NODE; + ut_ad(mtr->memo_contains(*space)); + auto b= fut_get_ptr(space->id, space->zip_size(), lst_node, RW_SX_LATCH, + mode, mtr, block); + return b ? b - XDES_FLST_NODE : nullptr; } /********************************************************************//** @@ -985,8 +987,8 @@ fsp_alloc_free_extent( } } - descr = xdes_lst_get_descriptor(space, first, &desc_block, - mtr); + descr = xdes_lst_get_descriptor(space, first, BUF_GET, + &desc_block, mtr); } flst_remove(header, FSP_HEADER_OFFSET + FSP_FREE, desc_block, @@ -1108,8 +1110,8 @@ fsp_alloc_free_page( descr - xdes->frame + XDES_FLST_NODE), mtr); } else { - descr = xdes_lst_get_descriptor(space, first, &xdes, - mtr); + descr = xdes_lst_get_descriptor(space, first, + BUF_GET, &xdes, mtr); } /* Reset the hint */ @@ -1470,6 +1472,7 @@ static void fsp_free_seg_inode( @param[in] header segment header @param[in] space space id @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] mode BUF_GET or BUF_GET_POSSIBLY_FREED @param[in,out] mtr mini-transaction @param[out] block inode block, or NULL to ignore @return segment inode, page x-latched; NULL if the inode is free */ @@ -1479,6 +1482,7 @@ fseg_inode_try_get( const fseg_header_t* header, ulint space, ulint zip_size, + ulint mode, mtr_t* mtr, buf_block_t** block) { @@ -1489,11 +1493,11 @@ fseg_inode_try_get( inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET); ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE)); - inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mtr, - block); - - if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) { + inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mode, + mtr, block); + if (UNIV_UNLIKELY(!inode)) { + } else if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) { inode = NULL; } else { ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) @@ -1519,10 +1523,10 @@ fseg_inode_get( mtr_t* mtr, buf_block_t** block = NULL) { - fseg_inode_t* inode - = fseg_inode_try_get(header, space, zip_size, mtr, block); - ut_a(inode); - return(inode); + fseg_inode_t *inode= fseg_inode_try_get(header, space, zip_size, BUF_GET, + mtr, block); + ut_a(inode); + return inode; } /** Get the page number from the nth fragment page slot. @@ -1880,7 +1884,8 @@ fseg_alloc_free_extent( first = flst_get_first(inode + FSEG_FREE); - descr = xdes_lst_get_descriptor(space, first, xdes, mtr); + descr = xdes_lst_get_descriptor(space, first, BUF_GET, xdes, + mtr); } else { /* Segment free list was empty, allocate from space */ descr = fsp_alloc_free_extent(space, 0, xdes, mtr); @@ -2066,7 +2071,8 @@ take_hinted_page: return(NULL); } - ret_descr = xdes_lst_get_descriptor(space, first, &xdes, mtr); + ret_descr = xdes_lst_get_descriptor(space, first, BUF_GET, + &xdes, mtr); ret_page = xdes_find_free(ret_descr); if (ret_page == FIL_NULL) { ut_ad(!has_done_reservation); @@ -2538,36 +2544,29 @@ fseg_free_page_low( @param[in] offset page number @param[in,out] mtr mini-transaction @param[in] have_latch whether space->x_lock() was already called */ -void -fseg_free_page( - fseg_header_t* seg_header, - fil_space_t* space, - uint32_t offset, - mtr_t* mtr, - bool have_latch) +void fseg_free_page(fseg_header_t *seg_header, fil_space_t *space, + uint32_t offset, mtr_t *mtr, bool have_latch) { - DBUG_ENTER("fseg_free_page"); - fseg_inode_t* seg_inode; - buf_block_t* iblock; - if (have_latch) { - ut_ad(space->is_owner()); - } else { - mtr->x_lock_space(space); - } - - DBUG_LOG("fseg_free_page", "space_id: " << space->id - << ", page_no: " << offset); - - seg_inode = fseg_inode_get(seg_header, space->id, space->zip_size(), - mtr, - &iblock); - if (!space->full_crc32()) { - fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); - } - - fseg_free_page_low(seg_inode, iblock, space, offset, mtr); + DBUG_ENTER("fseg_free_page"); + buf_block_t *iblock; + if (have_latch) + ut_ad(space->is_owner()); + else + mtr->x_lock_space(space); + + DBUG_PRINT("fseg_free_page", + ("space_id: " ULINTPF ", page_no: %u", space->id, offset)); + + if (fseg_inode_t *seg_inode= fseg_inode_try_get(seg_header, + space->id, space->zip_size(), + BUF_GET, mtr, &iblock)) + { + if (!space->full_crc32()) + fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); + fseg_free_page_low(seg_inode, iblock, space, offset, mtr); + } - DBUG_VOID_RETURN; + DBUG_VOID_RETURN; } /** Determine whether a page is free. @@ -2714,11 +2713,15 @@ fseg_free_step( ut_a(!xdes_is_free(descr, header_page % FSP_EXTENT_SIZE)); buf_block_t* iblock; const ulint zip_size = space->zip_size(); - inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock); + inode = fseg_inode_try_get(header, space_id, zip_size, + BUF_GET_POSSIBLY_FREED, mtr, &iblock); + if (space->is_stopping()) { + DBUG_RETURN(true); + } if (inode == NULL) { - ib::info() << "Double free of inode from " - << page_id_t(space_id, header_page); + ib::warn() << "Double free of inode from " + << page_id_t(space_id, header_page); DBUG_RETURN(true); } @@ -2727,6 +2730,10 @@ fseg_free_step( } descr = fseg_get_first_extent(inode, space, mtr); + if (space->is_stopping()) { + DBUG_RETURN(true); + } + if (descr != NULL) { /* Free the extent held by the segment */ fseg_free_extent(inode, iblock, space, xdes_get_offset(descr), @@ -2779,8 +2786,6 @@ fseg_free_step_not_header( #endif /* BTR_CUR_HASH_ADAPT */ ) { - ulint n; - xdes_t* descr; fseg_inode_t* inode; const uint32_t space_id = page_get_space_id(page_align(header)); @@ -2789,15 +2794,24 @@ fseg_free_step_not_header( fil_space_t* space = mtr->x_lock_space(space_id); buf_block_t* iblock; - inode = fseg_inode_get(header, space_id, space->zip_size(), mtr, - &iblock); + inode = fseg_inode_try_get(header, space_id, space->zip_size(), + BUF_GET_POSSIBLY_FREED, mtr, &iblock); + if (space->is_stopping()) { + return true; + } + + if (!inode) { + ib::warn() << "Double free of " + << page_id_t(space_id, + page_get_page_no(page_align(header))); + return true; + } + if (!space->full_crc32()) { fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); } - descr = fseg_get_first_extent(inode, space, mtr); - - if (descr != NULL) { + if (xdes_t* descr = fseg_get_first_extent(inode, space, mtr)) { /* Free the extent held by the segment */ fseg_free_extent(inode, iblock, space, xdes_get_offset(descr), mtr @@ -2810,7 +2824,7 @@ fseg_free_step_not_header( /* Free a frag page */ - n = fseg_find_last_used_frag_page_slot(inode); + ulint n = fseg_find_last_used_frag_page_slot(inode); ut_a(n != ULINT_UNDEFINED); @@ -2864,7 +2878,8 @@ fseg_get_first_extent( buf_block_t *xdes; return(first.page == FIL_NULL ? NULL - : xdes_lst_get_descriptor(space, first, &xdes, mtr)); + : xdes_lst_get_descriptor(space, first, BUF_GET_POSSIBLY_FREED, + &xdes, mtr)); } #ifdef UNIV_BTR_PRINT diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index e084f0b7935..122d31c1f6d 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, 2020, MariaDB Corporation. +Copyright (c) 2019, 2021, 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 @@ -151,7 +151,8 @@ static void flst_insert_after(buf_block_t *base, uint16_t boffset, { buf_block_t *block; flst_node_t *next= fut_get_ptr(add->page.id().space(), add->zip_size(), - next_addr, RW_SX_LATCH, mtr, &block); + next_addr, RW_SX_LATCH, BUF_GET, mtr, + &block); flst_write_addr(*block, next + FLST_PREV, add->page.id().page_no(), aoffset, mtr); } @@ -202,7 +203,8 @@ static void flst_insert_before(buf_block_t *base, uint16_t boffset, { buf_block_t *block; flst_node_t *prev= fut_get_ptr(add->page.id().space(), add->zip_size(), - prev_addr, RW_SX_LATCH, mtr, &block); + prev_addr, RW_SX_LATCH, BUF_GET, mtr, + &block); flst_write_addr(*block, prev + FLST_NEXT, add->page.id().page_no(), aoffset, mtr); } @@ -253,7 +255,7 @@ void flst_add_last(buf_block_t *base, uint16_t boffset, const flst_node_t *c= addr.page == add->page.id().page_no() ? add->frame + addr.boffset : fut_get_ptr(add->page.id().space(), add->zip_size(), addr, - RW_SX_LATCH, mtr, &cur); + RW_SX_LATCH, BUF_GET, mtr, &cur); flst_insert_after(base, boffset, cur, static_cast<uint16_t>(c - cur->frame), add, aoffset, mtr); @@ -286,7 +288,7 @@ void flst_add_first(buf_block_t *base, uint16_t boffset, const flst_node_t *c= addr.page == add->page.id().page_no() ? add->frame + addr.boffset : fut_get_ptr(add->page.id().space(), add->zip_size(), addr, - RW_SX_LATCH, mtr, &cur); + RW_SX_LATCH, BUF_GET, mtr, &cur); flst_insert_before(base, boffset, cur, static_cast<uint16_t>(c - cur->frame), add, aoffset, mtr); @@ -321,9 +323,10 @@ void flst_remove(buf_block_t *base, uint16_t boffset, flst_node_t *prev= prev_addr.page == cur->page.id().page_no() ? cur->frame + prev_addr.boffset : fut_get_ptr(cur->page.id().space(), cur->zip_size(), prev_addr, - RW_SX_LATCH, mtr, &block); - flst_write_addr(*block, prev + FLST_NEXT, - next_addr.page, next_addr.boffset, mtr); + RW_SX_LATCH, BUF_GET_POSSIBLY_FREED, mtr, &block); + if (prev) + flst_write_addr(*block, prev + FLST_NEXT, + next_addr.page, next_addr.boffset, mtr); } if (next_addr.page == FIL_NULL) @@ -335,9 +338,10 @@ void flst_remove(buf_block_t *base, uint16_t boffset, flst_node_t *next= next_addr.page == cur->page.id().page_no() ? cur->frame + next_addr.boffset : fut_get_ptr(cur->page.id().space(), cur->zip_size(), next_addr, - RW_SX_LATCH, mtr, &block); - flst_write_addr(*block, next + FLST_PREV, - prev_addr.page, prev_addr.boffset, mtr); + RW_SX_LATCH, BUF_GET_POSSIBLY_FREED, mtr, &block); + if (next) + flst_write_addr(*block, next + FLST_PREV, + prev_addr.page, prev_addr.boffset, mtr); } byte *len= &base->frame[boffset + FLST_LEN]; @@ -368,7 +372,7 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) mtr2.start(); const flst_node_t *node= fut_get_ptr(base->page.id().space(), base->zip_size(), addr, - RW_SX_LATCH, &mtr2); + RW_SX_LATCH, BUF_GET, &mtr2); addr= flst_get_next_addr(node); mtr2.commit(); } @@ -382,7 +386,7 @@ void flst_validate(const buf_block_t *base, uint16_t boffset, mtr_t *mtr) mtr2.start(); const flst_node_t *node= fut_get_ptr(base->page.id().space(), base->zip_size(), addr, - RW_SX_LATCH, &mtr2); + RW_SX_LATCH, BUF_GET, &mtr2); addr= flst_get_prev_addr(node); mtr2.commit(); } diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h index 72a94ef6d42..9d9e44b69b1 100644 --- a/storage/innobase/include/fut0fut.h +++ b/storage/innobase/include/fut0fut.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 2021, 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 @@ -35,6 +35,7 @@ Created 12/13/1995 Heikki Tuuri @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] addr file address @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH +@param[in] mode BUF_GET or BUF_GET_POSSIBLY_FREED @param[out] ptr_block file page @param[in,out] mtr mini-transaction @return pointer to a byte in (*ptr_block)->frame; the *ptr_block is @@ -46,6 +47,7 @@ fut_get_ptr( ulint zip_size, fil_addr_t addr, rw_lock_type_t rw_latch, + ulint mode, mtr_t* mtr, buf_block_t** ptr_block = NULL) { @@ -57,10 +59,15 @@ fut_get_ptr( || (rw_latch == RW_X_LATCH) || (rw_latch == RW_SX_LATCH)); - block = buf_page_get(page_id_t(space, addr.page), zip_size, - rw_latch, mtr); - - ptr = buf_block_get_frame(block) + addr.boffset; + block = buf_page_get_gen(page_id_t(space, addr.page), zip_size, + rw_latch, nullptr, mode, mtr); + if (!block) { + } else if (mode == BUF_GET_POSSIBLY_FREED + && block->page.status == buf_page_t::FREED) { + block = nullptr; + } else { + ptr = buf_block_get_frame(block) + addr.boffset; + } if (ptr_block != NULL) { *ptr_block = block; |