summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-02-22 18:07:15 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-02-22 18:08:10 +0530
commitd7fc4f5236048daf6ac853ae4b4946cd0e24acb0 (patch)
tree0c3d354d944584d24fdad8ae91e9cd6e52ea5251 /storage
parent374f4c3f8ce35eb86d9b6ff515022eeae9f5c888 (diff)
downloadmariadb-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.cc71
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));