diff options
Diffstat (limited to 'innobase/btr')
-rw-r--r-- | innobase/btr/btr0btr.c | 2 | ||||
-rw-r--r-- | innobase/btr/btr0cur.c | 130 | ||||
-rw-r--r-- | innobase/btr/btr0pcur.c | 70 | ||||
-rw-r--r-- | innobase/btr/btr0sea.c | 2 |
4 files changed, 146 insertions, 58 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 6da323867fb..e4e957ea7b6 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -2347,6 +2347,8 @@ btr_validate_level( mtr_start(&mtr); + mtr_x_lock(dict_tree_get_lock(tree), &mtr); + page = btr_root_get(tree, &mtr); space = buf_frame_get_space_id(page); diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 7783f618d6d..a64ed8b6fe1 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -256,7 +256,8 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; #endif - if (latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ + if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED + && latch_mode <= BTR_MODIFY_LEAF && info->last_hash_succ && !estimate && btr_search_guess_on_hash(index, info, tuple, mode, latch_mode, cursor, @@ -344,9 +345,7 @@ btr_cur_search_to_nth_level( retry_page_get: page = buf_page_get_gen(space, page_no, rw_latch, guess, buf_mode, -#ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, -#endif mtr); if (page == NULL) { @@ -380,7 +379,7 @@ retry_page_get: } #endif ut_ad(0 == ut_dulint_cmp(tree->id, - btr_page_get_index_id(page))); + btr_page_get_index_id(page))); if (height == ULINT_UNDEFINED) { /* We are in the root node */ @@ -515,9 +514,7 @@ btr_cur_open_at_index_side( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, -#ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, -#endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); @@ -604,9 +601,7 @@ btr_cur_open_at_rnd_pos( for (;;) { page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL, BUF_GET, -#ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, -#endif mtr); ut_ad(0 == ut_dulint_cmp(tree->id, btr_page_get_index_id(page))); @@ -1223,6 +1218,57 @@ btr_cur_parse_update_in_place( } /***************************************************************** +Updates a secondary index record when the update causes no size +changes in its fields. The only case when this function is currently +called is that in a char field characters change to others which +are identified in the collation order. */ + +ulint +btr_cur_update_sec_rec_in_place( +/*============================*/ + /* out: DB_SUCCESS or error number */ + btr_cur_t* cursor, /* in: cursor on the record to update; + cursor stays valid and positioned on the + same record */ + upd_t* update, /* in: update vector */ + que_thr_t* thr, /* in: query thread */ + mtr_t* mtr) /* in: mtr */ +{ + dict_index_t* index = cursor->index; + dict_index_t* clust_index; + ulint err; + rec_t* rec; + dulint roll_ptr = ut_dulint_zero; + trx_t* trx = thr_get_trx(thr); + + /* Only secondary index records are updated using this function */ + ut_ad(0 == (index->type & DICT_CLUSTERED)); + + rec = btr_cur_get_rec(cursor); + + err = lock_sec_rec_modify_check_and_lock(0, rec, index, thr); + + if (err != DB_SUCCESS) { + + return(err); + } + + /* Remove possible hash index pointer to this record */ + btr_search_update_hash_on_delete(cursor); + + row_upd_rec_in_place(rec, update); + + clust_index = dict_table_get_first_index(index->table); + + /* Note that roll_ptr is really just a dummy value since + a secondary index record does not contain any sys columns */ + + btr_cur_update_in_place_log(BTR_KEEP_SYS_FLAG, rec, clust_index, + update, trx, roll_ptr, mtr); + return(DB_SUCCESS); +} + +/***************************************************************** Updates a record when the update causes no size changes in its fields. */ ulint @@ -1248,7 +1294,7 @@ btr_cur_update_in_place( ibool was_delete_marked; /* Only clustered index records are updated using this function */ - ut_ad((cursor->index)->type & DICT_CLUSTERED); + ut_ad(cursor->index->type & DICT_CLUSTERED); rec = btr_cur_get_rec(cursor); index = cursor->index; @@ -2477,27 +2523,33 @@ btr_estimate_n_rows_in_range( } /*********************************************************************** -Estimates the number of different key values in a given index. */ +Estimates the number of different key values in a given index, for +each n-column prefix of the index where n <= dict_index_get_n_unique(index). +The estimates are stored in the array index->stat_n_diff_key_vals. */ -ulint +void btr_estimate_number_of_different_key_vals( /*======================================*/ - /* out: estimated number of key values */ dict_index_t* index) /* in: index */ { btr_cur_t cursor; page_t* page; rec_t* rec; - ulint total_n_recs = 0; - ulint n_diff_in_page; - ulint n_diff = 0; + ulint n_cols; ulint matched_fields; ulint matched_bytes; + ulint* n_diff; + ulint not_empty_flag = 0; ulint i; + ulint j; mtr_t mtr; - if (index->type & DICT_UNIQUE) { - return(index->table->stat_n_rows); + n_cols = dict_index_get_n_unique(index); + + n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong)); + + for (j = 0; j <= n_cols; j++) { + n_diff[j] = 0; } /* We sample some pages in the index to get an estimate */ @@ -2507,17 +2559,19 @@ btr_estimate_number_of_different_key_vals( btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr); - /* Count the number of different key values minus one on this - index page: we subtract one because otherwise our algorithm - would give a wrong estimate for an index where there is - just one key value */ + /* Count the number of different key values minus one + for each prefix of the key on this index page: we subtract + one because otherwise our algorithm would give a wrong + estimate for an index where there is just one key value */ page = btr_cur_get_page(&cursor); rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); - n_diff_in_page = 0; + if (rec != page_get_supremum_rec(page)) { + not_empty_flag = 1; + } while (rec != page_get_supremum_rec(page) && page_rec_get_next(rec) @@ -2528,30 +2582,30 @@ btr_estimate_number_of_different_key_vals( cmp_rec_rec_with_match(rec, page_rec_get_next(rec), index, &matched_fields, &matched_bytes); - if (matched_fields < - dict_index_get_n_ordering_defined_by_user( - index)) { - n_diff_in_page++; - } + for (j = matched_fields + 1; j <= n_cols; j++) { + n_diff[j]++; + } + rec = page_rec_get_next(rec); } - - n_diff += n_diff_in_page; - - total_n_recs += page_get_n_recs(page); mtr_commit(&mtr); } - if (n_diff == 0) { - /* We play safe and assume that there are just two different - key values in the index */ - - return(2); + /* If we saw k borders between different key values on + BTR_KEY_VAL_ESTIMATE_N_PAGES leaf pages, we can estimate how many + there will be in index->stat_n_leaf_pages */ + + for (j = 0; j <= n_cols; j++) { + index->stat_n_diff_key_vals[j] = + (n_diff[j] * index->stat_n_leaf_pages + + BTR_KEY_VAL_ESTIMATE_N_PAGES - 1 + + not_empty_flag) + / BTR_KEY_VAL_ESTIMATE_N_PAGES; } - - return(index->table->stat_n_rows / (total_n_recs / n_diff)); + + mem_free(n_diff); } /*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/ diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c index 5e625553929..8ca3d41f7f9 100644 --- a/innobase/btr/btr0pcur.c +++ b/innobase/btr/btr0pcur.c @@ -62,8 +62,10 @@ btr_pcur_free_for_mysql( /****************************************************************** The position of the cursor is stored by taking an initial segment of the record the cursor is positioned on, before, or after, and copying it to the -cursor data structure. NOTE that the page where the cursor is positioned -must not be empty! */ +cursor data structure, or just setting a flag if the cursor id before the +first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the +page where the cursor is positioned must not be empty if the index tree is +not totally empty! */ void btr_pcur_store_position( @@ -93,9 +95,21 @@ btr_pcur_store_position( ut_a(cursor->latch_mode != BTR_NO_LATCHES); if (page_get_n_recs(page) == 0) { + /* It must be an empty index tree */ - /* Cannot store position! */ - btr_pcur_close(cursor); + ut_a(btr_page_get_next(page, mtr) == FIL_NULL + && btr_page_get_prev(page, mtr) == FIL_NULL); + + if (rec == page_get_supremum_rec(page)) { + + cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE; + cursor->old_stored = BTR_PCUR_OLD_STORED; + + return; + } + + cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE; + cursor->old_stored = BTR_PCUR_OLD_STORED; return; } @@ -140,13 +154,15 @@ btr_pcur_copy_stored_position( ut_memcpy((byte*)pcur_receive, (byte*)pcur_donate, sizeof(btr_pcur_t)); - pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); + if (pcur_donate->old_rec_buf) { + + pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); - ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, + ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); - pcur_receive->old_rec = pcur_receive->old_rec_buf + pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); - + } } /****************************************************************** @@ -158,7 +174,9 @@ to the last record LESS OR EQUAL to the stored record; the last record LESS than the user record which was the successor of the page infimum; (3) cursor was positioned on the page supremum: restores to the first record -GREATER than the user record which was the predecessor of the supremum. */ +GREATER than the user record which was the predecessor of the supremum. +(4) cursor was positioned before the first or after the last in an empty tree: +restores to before first or after the last in the tree. */ ibool btr_pcur_restore_position( @@ -177,17 +195,33 @@ btr_pcur_restore_position( dtuple_t* tuple; ulint mode; ulint old_mode; + ibool from_left; mem_heap_t* heap; - ut_a((cursor->pos_state == BTR_PCUR_WAS_POSITIONED) - || (cursor->pos_state == BTR_PCUR_IS_POSITIONED)); + ut_a(cursor->pos_state == BTR_PCUR_WAS_POSITIONED + || cursor->pos_state == BTR_PCUR_IS_POSITIONED); ut_a(cursor->old_stored == BTR_PCUR_OLD_STORED); + + if (cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE + || cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { + + if (cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE) { + from_left = TRUE; + } else { + from_left = FALSE; + } + + btr_cur_open_at_index_side(from_left, + btr_pcur_get_btr_cur(cursor)->index, latch_mode, + btr_pcur_get_btr_cur(cursor), mtr); + return(FALSE); + } + ut_a(cursor->old_rec); page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor)); - if ((latch_mode == BTR_SEARCH_LEAF) - || (latch_mode == BTR_MODIFY_LEAF)) { + if (latch_mode == BTR_SEARCH_LEAF || latch_mode == BTR_MODIFY_LEAF) { /* Try optimistic restoration */ if (buf_page_optimistic_get(latch_mode, page, @@ -242,16 +276,15 @@ btr_pcur_restore_position( /* Restore the old search mode */ cursor->search_mode = old_mode; - if ((cursor->rel_pos == BTR_PCUR_ON) - && btr_pcur_is_on_user_rec(cursor, mtr) - && (0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor)))) { + if (cursor->rel_pos == BTR_PCUR_ON + && btr_pcur_is_on_user_rec(cursor, mtr) + && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) { /* We have to store the NEW value for the modify clock, since the cursor can now be on a different page! */ cursor->modify_clock = buf_frame_get_modify_clock( - buf_frame_align( - btr_pcur_get_rec(cursor))); + buf_frame_align(btr_pcur_get_rec(cursor))); mem_heap_free(heap); return(TRUE); @@ -366,6 +399,7 @@ btr_pcur_move_backward_from_page( latch_mode2 = BTR_MODIFY_PREV; } else { + latch_mode2 = 0; /* To eliminate compiler warning */ ut_error; } diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 616f8911aba..31ef8ce573b 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -680,9 +680,7 @@ btr_search_guess_on_hash( success = buf_page_get_known_nowait(latch_mode, page, BUF_MAKE_YOUNG, -#ifdef UNIV_SYNC_DEBUG IB__FILE__, __LINE__, -#endif mtr); rw_lock_s_unlock(&btr_search_latch); |