@@ -224,6 +224,11 @@ btr_cur_latch_leaves(
224
224
225
225
spatial = dict_index_is_spatial (cursor->index ) && cursor->rtr_info ;
226
226
ut_ad (block->page .in_file ());
227
+ ut_ad (srv_read_only_mode
228
+ || mtr->memo_contains_flagged (&cursor->index ->lock ,
229
+ MTR_MEMO_S_LOCK
230
+ | MTR_MEMO_X_LOCK
231
+ | MTR_MEMO_SX_LOCK));
227
232
228
233
switch (latch_mode) {
229
234
case BTR_SEARCH_LEAF:
@@ -338,10 +343,10 @@ btr_cur_latch_leaves(
338
343
case BTR_SEARCH_PREV:
339
344
case BTR_MODIFY_PREV:
340
345
mode = latch_mode == BTR_SEARCH_PREV ? RW_S_LATCH : RW_X_LATCH;
341
- /* latch also left sibling */
342
- block->lock .s_lock ();
346
+ /* Because we are holding index->lock, no page splits
347
+ or merges may run concurrently, and we may read
348
+ FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
343
349
left_page_no = btr_page_get_prev (block->frame );
344
- block->lock .s_unlock ();
345
350
346
351
if (left_page_no != FIL_NULL) {
347
352
latch_leaves.savepoints [0 ] = mtr_set_savepoint (mtr);
@@ -753,6 +758,7 @@ bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
753
758
@param[in,out] cursor cursor
754
759
@param[in] mtr mini-transaction
755
760
@return true if success */
761
+ TRANSACTIONAL_TARGET
756
762
bool
757
763
btr_cur_optimistic_latch_leaves (
758
764
buf_block_t * block,
@@ -774,14 +780,16 @@ btr_cur_optimistic_latch_leaves(
774
780
modify_clock, mtr));
775
781
case BTR_SEARCH_PREV:
776
782
case BTR_MODIFY_PREV:
777
- block->lock .s_lock ();
778
- if (block->modify_clock != modify_clock) {
779
- block->lock .s_unlock ();
780
- return false ;
783
+ uint32_t curr_page_no, left_page_no;
784
+ {
785
+ transactional_shared_lock_guard<block_lock> g{
786
+ block->lock };
787
+ if (block->modify_clock != modify_clock) {
788
+ return false ;
789
+ }
790
+ curr_page_no = block->page .id ().page_no ();
791
+ left_page_no = btr_page_get_prev (block->frame );
781
792
}
782
- const uint32_t curr_page_no = block->page .id ().page_no ();
783
- const uint32_t left_page_no = btr_page_get_prev (block->frame );
784
- block->lock .s_unlock ();
785
793
786
794
const rw_lock_type_t mode = *latch_mode == BTR_SEARCH_PREV
787
795
? RW_S_LATCH : RW_X_LATCH;
@@ -1271,7 +1279,6 @@ btr_cur_search_to_nth_level_func(
1271
1279
ulint n_releases = 0 ;
1272
1280
bool detected_same_key_root = false ;
1273
1281
1274
- bool retrying_for_search_prev = false ;
1275
1282
ulint leftmost_from_level = 0 ;
1276
1283
buf_block_t ** prev_tree_blocks = NULL ;
1277
1284
ulint* prev_tree_savepoints = NULL ;
@@ -1494,9 +1501,6 @@ btr_cur_search_to_nth_level_func(
1494
1501
default :
1495
1502
if (!srv_read_only_mode) {
1496
1503
if (s_latch_by_caller) {
1497
- ut_ad (mtr->memo_contains_flagged (
1498
- &index->lock , MTR_MEMO_S_LOCK
1499
- | MTR_MEMO_SX_LOCK));
1500
1504
} else if (!modify_external) {
1501
1505
/* BTR_SEARCH_TREE is intended to be used with
1502
1506
BTR_ALREADY_S_LATCHED */
@@ -1568,7 +1572,7 @@ btr_cur_search_to_nth_level_func(
1568
1572
if (height != 0 ) {
1569
1573
/* We are about to fetch the root or a non-leaf page. */
1570
1574
if ((latch_mode != BTR_MODIFY_TREE || height == level)
1571
- && !retrying_for_search_prev ) {
1575
+ && !prev_tree_blocks ) {
1572
1576
/* If doesn't have SX or X latch of index,
1573
1577
each pages should be latched before reading. */
1574
1578
if (height == ULINT_UNDEFINED
@@ -1698,18 +1702,18 @@ btr_cur_search_to_nth_level_func(
1698
1702
goto retry_page_get;
1699
1703
}
1700
1704
1701
- if (retrying_for_search_prev && height != 0 ) {
1705
+ if (height && prev_tree_blocks ) {
1702
1706
/* also latch left sibling */
1703
- uint32_t left_page_no;
1704
1707
buf_block_t * get_block;
1705
1708
1706
1709
ut_ad (rw_latch == RW_NO_LATCH);
1707
1710
1708
1711
rw_latch = upper_rw_latch;
1709
1712
1710
- block->lock .s_lock ();
1711
- left_page_no = btr_page_get_prev (buf_block_get_frame (block));
1712
- block->lock .s_unlock ();
1713
+ /* Because we are holding index->lock, no page splits
1714
+ or merges may run concurrently, and we may read
1715
+ FIL_PAGE_PREV from a buffer-fixed, unlatched page. */
1716
+ uint32_t left_page_no = btr_page_get_prev (block->frame );
1713
1717
1714
1718
if (left_page_no != FIL_NULL) {
1715
1719
ut_ad (prev_n_blocks < leftmost_from_level);
@@ -1852,7 +1856,7 @@ btr_cur_search_to_nth_level_func(
1852
1856
}
1853
1857
1854
1858
/* release upper blocks */
1855
- if (retrying_for_search_prev ) {
1859
+ if (prev_tree_blocks ) {
1856
1860
ut_ad (!autoinc);
1857
1861
for (;
1858
1862
prev_n_releases < prev_n_blocks;
@@ -2238,7 +2242,7 @@ btr_cur_search_to_nth_level_func(
2238
2242
BTR_MODIFY_PREV latches prev_page of the leaf page. */
2239
2243
if ((latch_mode == BTR_SEARCH_PREV
2240
2244
|| latch_mode == BTR_MODIFY_PREV)
2241
- && !retrying_for_search_prev ) {
2245
+ && !prev_tree_blocks ) {
2242
2246
/* block should be latched for consistent
2243
2247
btr_page_get_prev() */
2244
2248
ut_ad (mtr->memo_contains_flagged (
@@ -2258,8 +2262,6 @@ btr_cur_search_to_nth_level_func(
2258
2262
if (height == 0 && leftmost_from_level > 0 ) {
2259
2263
/* should retry to get also prev_page
2260
2264
from level==leftmost_from_level. */
2261
- retrying_for_search_prev = true ;
2262
-
2263
2265
prev_tree_blocks = static_cast <buf_block_t **>(
2264
2266
ut_malloc_nokey (sizeof (buf_block_t *)
2265
2267
* leftmost_from_level));
@@ -2481,10 +2483,8 @@ btr_cur_search_to_nth_level_func(
2481
2483
mem_heap_free (heap);
2482
2484
}
2483
2485
2484
- if (retrying_for_search_prev) {
2485
- ut_free (prev_tree_blocks);
2486
- ut_free (prev_tree_savepoints);
2487
- }
2486
+ ut_free (prev_tree_blocks);
2487
+ ut_free (prev_tree_savepoints);
2488
2488
2489
2489
if (mbr_adj) {
2490
2490
/* remember that we will need to adjust parent MBR */
0 commit comments