diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2021-02-22 18:07:15 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2021-02-22 18:08:10 +0530 |
commit | d7fc4f5236048daf6ac853ae4b4946cd0e24acb0 (patch) | |
tree | 0c3d354d944584d24fdad8ae91e9cd6e52ea5251 /storage | |
parent | 374f4c3f8ce35eb86d9b6ff515022eeae9f5c888 (diff) | |
download | mariadb-git-d7fc4f5236048daf6ac853ae4b4946cd0e24acb0.tar.gz |
MDEV-24863 AHI entries mismatch with the index while reloading the evicted tables.
- This is caused by commit ad6171b91cac33e70bb28fa6865488b2c65e858c
(MDEV-22456). InnoDB reloads the evicted table again from dictionary.
In that case, AHI entries and current index object mismatches
happens. When index object mismatches then InnoDB should drop
the page hash AHI entries for the block. In
btr_search_drop_page_hash_index(), InnoDB should take exclusive
lock on the AHI latch if index is already freed to avoid the
freed memory access during buf_pool_resize()
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/btr/btr0sea.cc | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 79e6326ac1c..7b80d22c778 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2017, 2020, MariaDB Corporation. +Copyright (c) 2017, 2021, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -624,6 +624,12 @@ btr_search_update_hash_ref( return; } + if (cursor->index != index) { + ut_ad(cursor->index->id == index->id); + btr_search_drop_page_hash_index(block); + return; + } + ut_ad(block->page.id.space() == index->space); ut_a(index == cursor->index); ut_ad(!dict_index_is_ibuf(index)); @@ -1139,18 +1145,28 @@ retry: % btr_ahi_parts; latch = btr_search_latches[ahi_slot]; + dict_index_t* index = block->index; ut_ad(!btr_search_own_any(RW_LOCK_S)); ut_ad(!btr_search_own_any(RW_LOCK_X)); - rw_lock_s_lock(latch); + bool is_freed = index && index->freed(); + if (is_freed) { + rw_lock_x_lock(latch); + } else { + rw_lock_s_lock(latch); + } + assert_block_ahi_valid(block); - if (!block->index || !btr_search_enabled) { - rw_lock_s_unlock(latch); + if (!index || !btr_search_enabled) { + if (is_freed) { + rw_lock_x_unlock(latch); + } else { + rw_lock_s_unlock(latch); + } return; } - dict_index_t* index = block->index; #ifdef MYSQL_INDEX_DISABLE_AHI ut_ad(!index->disable_ahi); #endif @@ -1167,7 +1183,9 @@ retry: /* NOTE: The AHI fields of block must not be accessed after releasing search latch, as the index page might only be s-latched! */ - rw_lock_s_unlock(latch); + if (!is_freed) { + rw_lock_s_unlock(latch); + } ut_a(n_fields > 0 || n_bytes > 0); @@ -1215,16 +1233,18 @@ next_rec: mem_heap_free(heap); } - rw_lock_x_lock(latch); + if (!is_freed) { + rw_lock_x_lock(latch); - if (UNIV_UNLIKELY(!block->index)) { - /* Someone else has meanwhile dropped the hash index */ + if (UNIV_UNLIKELY(!block->index)) { + /* Someone else has meanwhile dropped the + hash index */ + goto cleanup; + } - goto cleanup; + ut_a(block->index == index); } - ut_a(block->index == index); - if (block->curr_n_fields != n_fields || block->curr_n_bytes != n_bytes) { @@ -1544,19 +1564,25 @@ btr_search_move_or_delete_hash_entries( rw_lock_s_lock(latch); ut_a(!new_block->index || new_block->index == index); - ut_a(!block->index || block->index == index); + ut_a(!block->index || block->index->id == index->id); ut_ad(!(new_block->index || block->index) || !dict_index_is_ibuf(index)); assert_block_ahi_valid(block); assert_block_ahi_valid(new_block); if (new_block->index) { +drop_exit: rw_lock_s_unlock(latch); btr_search_drop_page_hash_index(block); return; } if (block->index) { + + if (block->index != index) { + goto drop_exit; + } + ulint n_fields = block->curr_n_fields; ulint n_bytes = block->curr_n_bytes; ibool left_side = block->curr_left_side; @@ -1576,7 +1602,6 @@ btr_search_move_or_delete_hash_entries( ut_ad(left_side == block->curr_left_side); return; } - rw_lock_s_unlock(latch); } @@ -1616,6 +1641,12 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor) return; } + if (index != cursor->index) { + ut_ad(index->id == cursor->index->id); + btr_search_drop_page_hash_index(block); + return; + } + ut_ad(block->page.id.space() == index->space); ut_a(index == cursor->index); ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0); @@ -1688,6 +1719,12 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor) return; } + if (cursor->index != index) { + ut_ad(cursor->index->id == index->id); + btr_search_drop_page_hash_index(block); + return; + } + ut_a(cursor->index == index); ut_ad(!dict_index_is_ibuf(index)); @@ -1774,6 +1811,12 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) #ifdef MYSQL_INDEX_DISABLE_AHI ut_a(!index->disable_ahi); #endif + if (index != cursor->index) { + ut_ad(index->id == cursor->index->id); + btr_search_drop_page_hash_index(block); + return; + } + ut_a(index == cursor->index); ut_ad(!dict_index_is_ibuf(index)); |