summaryrefslogtreecommitdiff
path: root/storage/innobase/dict
diff options
context:
space:
mode:
authorVlad Lesin <vlad_lesin@mail.ru>2022-08-31 17:49:38 +0300
committerVlad Lesin <vlad_lesin@mail.ru>2022-10-05 17:35:21 +0300
commitc0eda62aec1de8b74ca51791df5ad142dee2ef08 (patch)
treebd9046fda7b040b33ede0c1439d6ab581f6da043 /storage/innobase/dict
parent111cbdf3dae9c5f8e256db21c83307e5477055b8 (diff)
downloadmariadb-git-c0eda62aec1de8b74ca51791df5ad142dee2ef08.tar.gz
MDEV-27927 row_sel_try_search_shortcut_for_mysql() does not latch a page, violating read view isolation
btr_search_guess_on_hash() would only acquire an index page latch if it is invoked with ahi_latch=NULL. If it's invoked from row_sel_try_search_shortcut_for_mysql() with ahi_latch!=NULL, a page will not be latched, and row_search_mvcc() will get a pointer to the record, which can be changed by some other transaction before the record was stored in result buffer with row_sel_store_mysql_rec() call. ahi_latch argument of btr_cur_search_to_nth_level_func() and btr_pcur_open_with_no_init_func() is used only for row_sel_try_search_shortcut_for_mysql(). btr_cur_search_to_nth_level_func(..., ahi_latch !=0, ...) is invoked only from btr_pcur_open_with_no_init_func(..., ahi_latch !=0, ...), which, in turns, is invoked only from row_sel_try_search_shortcut_for_mysql(). I suppose that separate case with ahi_latch!=0 was intentionally implemented to protect row_sel_store_mysql_rec() call in row_search_mvcc() just after row_sel_try_search_shortcut_for_mysql() call. After the ahi_latch was moved from row_seach_mvcc() to row_sel_try_search_shortcut_for_mysql(), there is no need in it at all if btr_search_guess_on_hash() latches a page unconditionally. And if btr_search_guess_on_hash() latched the page, any access to the record in row_sel_try_search_shortcut_for_mysql() after btr_pcur_open_with_no_init() call will be protected with the page latch. The fix is to remove ahi_latch argument from btr_pcur_open_with_no_init_func(), btr_cur_search_to_nth_level_func() and btr_search_guess_on_hash(). There will not be test, as to test it we need to freeze some SELECT execution in the point between row_sel_try_search_shortcut_for_mysql() and row_sel_store_mysql_rec() calls in row_search_mvcc(), and to change the record in some other transaction to let row_sel_store_mysql_rec() to store changed record in result buffer. Buf we can't do this with the fix, as the page will be latched in btr_search_guess_on_hash() call.
Diffstat (limited to 'storage/innobase/dict')
-rw-r--r--storage/innobase/dict/dict0dict.cc4
1 files changed, 2 insertions, 2 deletions
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index eb0f10d55f4..d843115082e 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -5435,7 +5435,7 @@ dict_set_corrupted(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF,
- &cursor, 0, __FILE__, __LINE__, &mtr);
+ &cursor, __FILE__, __LINE__, &mtr);
if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type
@@ -5538,7 +5538,7 @@ dict_index_set_merge_threshold(
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF,
- &cursor, 0, __FILE__, __LINE__, &mtr);
+ &cursor, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple)
&& rec_get_n_fields_old(btr_cur_get_rec(&cursor))