diff options
author | monty@mashka.mysql.fi <> | 2002-07-25 22:46:28 +0300 |
---|---|---|
committer | monty@mashka.mysql.fi <> | 2002-07-25 22:46:28 +0300 |
commit | bc035c71f1d94649253e4dac5fb8e5c981c7d834 (patch) | |
tree | f38c137c73206e3d059517b2bcab6a4a43c957f9 /innobase/btr | |
parent | b126501bf3888b09fad83dbd2894709c45f009fc (diff) | |
parent | 3c9f1a9ae47e4fcbede526430b0171e8ba17d948 (diff) | |
download | mariadb-git-bc035c71f1d94649253e4dac5fb8e5c981c7d834.tar.gz |
Merge with 3.23.51
Fixed wrong usage of sprintf() in ha_innodb.cc
Diffstat (limited to 'innobase/btr')
-rw-r--r-- | innobase/btr/btr0btr.c | 30 | ||||
-rw-r--r-- | innobase/btr/btr0cur.c | 93 | ||||
-rw-r--r-- | innobase/btr/btr0sea.c | 164 |
3 files changed, 245 insertions, 42 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c index 0263996a429..38d97785832 100644 --- a/innobase/btr/btr0btr.c +++ b/innobase/btr/btr0btr.c @@ -572,6 +572,13 @@ btr_page_get_father_for_rec( if (btr_node_ptr_get_child_page_no(node_ptr) != buf_frame_get_page_no(page)) { + fprintf(stderr, +"InnoDB: Dump of the child page:\n"); + buf_page_print(buf_frame_align(page)); + fprintf(stderr, +"InnoDB: Dump of the parent page:\n"); + buf_page_print(buf_frame_align(node_ptr)); + fprintf(stderr, "InnoDB: Corruption of an index tree: table %s, index %s,\n" "InnoDB: father ptr page no %lu, child page no %lu\n", @@ -581,6 +588,12 @@ btr_page_get_father_for_rec( buf_frame_get_page_no(page)); page_rec_print(page_rec_get_next(page_get_infimum_rec(page))); page_rec_print(node_ptr); + + fprintf(stderr, +"InnoDB: You should dump + drop + reimport the table to fix the\n" +"InnoDB: corruption. If the crash happens at the database startup, see\n" +"InnoDB: section 6.1 of http://www.innodb.com/ibman.html about forcing\n" +"InnoDB: recovery. Then dump + drop + reimport.\n"); } ut_a(btr_node_ptr_get_child_page_no(node_ptr) == @@ -780,12 +793,14 @@ top_loop: /***************************************************************** Reorganizes an index page. */ - +static void btr_page_reorganize_low( /*====================*/ - ibool low, /* in: TRUE if locks should not be updated, i.e., - there cannot exist locks on the page */ + ibool recovery,/* in: TRUE if called in recovery: locks should not + be updated, i.e., there cannot exist locks on the + page, and a hash index should not be dropped: it + cannot exist */ page_t* page, /* in: page to be reorganized */ mtr_t* mtr) /* in: mtr */ { @@ -805,7 +820,9 @@ btr_page_reorganize_low( /* Copy the old page to temporary space */ buf_frame_copy(new_page, page); - btr_search_drop_page_hash_index(page); + if (!recovery) { + btr_search_drop_page_hash_index(page); + } /* Recreate the page: note that global data on page (possible segment headers, next page-field, etc.) is preserved intact */ @@ -820,7 +837,7 @@ btr_page_reorganize_low( /* Copy max trx id to recreated page */ page_set_max_trx_id(page, page_get_max_trx_id(new_page)); - if (!low) { + if (!recovery) { /* Update the record lock bitmaps */ lock_move_reorganize_page(page, new_page); } @@ -2059,8 +2076,7 @@ btr_discard_page( btr_search_drop_page_hash_index(page); - if ((left_page_no == FIL_NULL) - && (btr_page_get_level(page, mtr) > 0)) { + if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) { /* We have to mark the leftmost node pointer on the right side page as the predefined minimum record */ diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 1274719cf7d..1fe322be81e 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -36,9 +36,16 @@ Created 10/16/1994 Heikki Tuuri #include "ibuf0ibuf.h" #include "lock0lock.h" +/* If the following is set to TRUE, this module prints a lot of +trace information of individual record operations */ +ibool btr_cur_print_record_ops = FALSE; + ulint btr_cur_rnd = 0; ulint btr_cur_n_non_sea = 0; +ulint btr_cur_n_sea = 0; +ulint btr_cur_n_non_sea_old = 0; +ulint btr_cur_n_sea_old = 0; /* In the optimistic insert, if the insert does not fit, but this much space can be released by page reorganize, then it is reorganized */ @@ -187,11 +194,7 @@ btr_cur_search_to_nth_level( tuple must be set so that it cannot get compared to the node ptr page number field! */ ulint mode, /* in: PAGE_CUR_L, ...; - NOTE that if the search is made using a unique - prefix of a record, mode should be - PAGE_CUR_LE, not PAGE_CUR_GE, as the latter - may end up on the previous page relative to the - record! Inserts should always be made using + Inserts should always be made using PAGE_CUR_LE to search the position! */ ulint latch_mode, /* in: BTR_SEARCH_LEAF, ..., ORed with BTR_INSERT and BTR_ESTIMATE; @@ -268,7 +271,7 @@ btr_cur_search_to_nth_level( #ifdef UNIV_SEARCH_PERF_STAT info->n_searches++; #endif - if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED + 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, @@ -283,14 +286,14 @@ btr_cur_search_to_nth_level( || mode != PAGE_CUR_LE); ut_ad(cursor->low_match != ULINT_UNDEFINED || mode != PAGE_CUR_LE); + btr_cur_n_sea++; + return; } #endif #endif - -#ifdef UNIV_SEARCH_PERF_STAT btr_cur_n_non_sea++; -#endif + /* If the hash search did not succeed, do binary search down the tree */ @@ -796,15 +799,28 @@ btr_cur_optimistic_insert( ulint data_size; ulint extra_size; ulint type; - ulint err; - - ut_ad(dtuple_check_typed(entry)); + ulint err; *big_rec = NULL; page = btr_cur_get_page(cursor); index = cursor->index; + if (!dtuple_check_typed_no_assert(entry)) { + fprintf(stderr, +"InnoDB: Error in a tuple to insert into table %lu index %lu\n", + index->table_name, index->name); + } + + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to insert to table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + index->table_name, index->name); + dtuple_print(entry); + } + ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); max_size = page_get_max_insert_size_after_reorganize(page, 1); @@ -928,7 +944,7 @@ calculate_sizes_again: buf_frame_get_page_no(page), max_size, rec_size + PAGE_DIR_SLOT_SIZE, type); */ - if (!(type & (DICT_CLUSTERED | DICT_UNIQUE))) { + if (!(type & DICT_CLUSTERED)) { /* We have added a record to page: update its free bits */ ibuf_update_free_bits_if_full(cursor->index, page, max_size, rec_size + PAGE_DIR_SLOT_SIZE); @@ -1258,6 +1274,15 @@ btr_cur_update_sec_rec_in_place( rec = btr_cur_get_rec(cursor); + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to update table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + index->table_name, index->name); + rec_print(rec); + } + err = lock_sec_rec_modify_check_and_lock(0, rec, index, thr); if (err != DB_SUCCESS) { @@ -1312,6 +1337,15 @@ btr_cur_update_in_place( index = cursor->index; trx = thr_get_trx(thr); + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to update table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + index->table_name, index->name); + rec_print(rec); + } + /* Do lock checking and undo logging */ err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, thr, &roll_ptr); @@ -1323,6 +1357,12 @@ btr_cur_update_in_place( block = buf_block_align(rec); if (block->is_hashed) { + if (row_upd_changes_ord_field_binary(NULL, index, update)) { + + /* Remove possible hash index pointer to this record */ + btr_search_update_hash_on_delete(cursor); + } + rw_lock_x_lock(&btr_search_latch); } @@ -1398,6 +1438,15 @@ btr_cur_optimistic_update( rec = btr_cur_get_rec(cursor); index = cursor->index; + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to update table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + index->table_name, index->name); + rec_print(rec); + } + ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); if (!row_upd_changes_field_size(rec, index, update)) { @@ -1973,6 +2022,15 @@ btr_cur_del_mark_set_clust_rec( rec = btr_cur_get_rec(cursor); index = cursor->index; + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to del mark table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + index->table_name, index->name); + rec_print(rec); + } + ut_ad(index->type & DICT_CLUSTERED); ut_ad(rec_get_deleted_flag(rec) == FALSE); @@ -2102,6 +2160,15 @@ btr_cur_del_mark_set_sec_rec( rec = btr_cur_get_rec(cursor); + if (btr_cur_print_record_ops && thr) { + printf( + "Trx with id %lu %lu going to del mark table %s index %s\n", + ut_dulint_get_high(thr_get_trx(thr)->id), + ut_dulint_get_low(thr_get_trx(thr)->id), + cursor->index->table_name, cursor->index->name); + rec_print(rec); + } + err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index, thr); if (err != DB_SUCCESS) { diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 8a54d9de9c0..cfdfefebd1a 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -15,6 +15,7 @@ Created 2/17/1996 Heikki Tuuri #include "page0page.h" #include "page0cur.h" #include "btr0cur.h" +#include "btr0pcur.h" #include "btr0btr.h" ulint btr_search_n_succ = 0; @@ -145,6 +146,8 @@ btr_search_info_create( info = mem_heap_alloc(heap, sizeof(btr_search_t)); + info->magic_n = BTR_SEARCH_MAGIC_N; + info->last_search = NULL; info->n_direction = 0; info->root_guess = NULL; @@ -159,6 +162,12 @@ btr_search_info_create( info->n_patt_succ = 0; info->n_searches = 0; + /* Set some sensible values */ + info->n_fields = 1; + info->n_bytes = 0; + + info->side = BTR_SEARCH_LEFT_SIDE; + return(info); } @@ -197,7 +206,7 @@ btr_search_info_update_hash( /* Test if the search would have succeeded using the recommended hash prefix */ - if ((info->n_fields >= n_unique) && (cursor->up_match >= n_unique)) { + if (info->n_fields >= n_unique && cursor->up_match >= n_unique) { info->n_hash_potential++; @@ -207,8 +216,8 @@ btr_search_info_update_hash( cmp = ut_pair_cmp(info->n_fields, info->n_bytes, cursor->low_match, cursor->low_bytes); - if (((info->side == BTR_SEARCH_LEFT_SIDE) && (cmp <= 0)) - || ((info->side == BTR_SEARCH_RIGHT_SIDE) && (cmp > 0))) { + if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp <= 0) + || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp > 0)) { goto set_new_recomm; } @@ -216,8 +225,8 @@ btr_search_info_update_hash( cmp = ut_pair_cmp(info->n_fields, info->n_bytes, cursor->up_match, cursor->up_bytes); - if (((info->side == BTR_SEARCH_LEFT_SIDE) && (cmp > 0)) - || ((info->side == BTR_SEARCH_RIGHT_SIDE) && (cmp <= 0))) { + if ((info->side == BTR_SEARCH_LEFT_SIDE && cmp > 0) + || (info->side == BTR_SEARCH_RIGHT_SIDE && cmp <= 0)) { goto set_new_recomm; } @@ -233,19 +242,18 @@ set_new_recomm: info->hash_analysis = 0; - if ((cursor->up_match >= n_unique) - || (cursor->low_match >= n_unique)) { - info->n_fields = n_unique; - info->n_bytes = 0; - - info->side = BTR_SEARCH_LEFT_SIDE; - } - cmp = ut_pair_cmp(cursor->up_match, cursor->up_bytes, cursor->low_match, cursor->low_bytes); if (cmp == 0) { info->n_hash_potential = 0; + /* For extra safety, we set some sensible values here */ + + info->n_fields = 1; + info->n_bytes = 0; + + info->side = BTR_SEARCH_LEFT_SIDE; + } else if (cmp > 0) { info->n_hash_potential = 1; @@ -305,6 +313,9 @@ btr_search_update_block_hash_info( info->last_hash_succ = FALSE; + ut_a(block->magic_n == BUF_BLOCK_MAGIC_N); + ut_a(info->magic_n == BTR_SEARCH_MAGIC_N); + if ((block->n_hash_helps > 0) && (info->n_hash_potential > 0) && (block->n_fields == info->n_fields) @@ -440,7 +451,9 @@ btr_search_info_update_slow( rw_lock_x_unlock(&btr_search_latch); } - if (build_index) { + if (build_index) { + ut_a(block->n_fields + block->n_bytes > 0); + btr_search_build_page_hash_index(block->frame, block->n_fields, block->n_bytes, @@ -622,6 +635,7 @@ btr_search_guess_on_hash( dulint tree_id; #ifdef notdefined btr_cur_t cursor2; + btr_pcur_t pcur; #endif ut_ad(index && info && tuple && cursor && mtr); ut_ad((latch_mode == BTR_SEARCH_LEAF) @@ -664,6 +678,9 @@ btr_search_guess_on_hash( rw_lock_s_lock(&btr_search_latch); } + ut_a(btr_search_latch.writer != RW_LOCK_EX); + ut_a(btr_search_latch.reader_count > 0); + rec = ha_search_and_get_data(btr_search_sys->hash_index, fold); if (!rec) { @@ -754,7 +771,26 @@ btr_search_guess_on_hash( btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode, &cursor2, 0, mtr); - ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); + if (mode == PAGE_CUR_GE + && btr_cur_get_rec(&cursor2) == page_get_supremum_rec( + buf_frame_align(btr_cur_get_rec(&cursor2)))) { + + /* If mode is PAGE_CUR_GE, then the binary search + in the index tree may actually take us to the supremum + of the previous page */ + + info->last_hash_succ = FALSE; + + btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode, + &pcur, mtr); + ut_a(btr_pcur_get_rec(&pcur) == btr_cur_get_rec(cursor)); + } else { + ut_a(btr_cur_get_rec(&cursor2) == btr_cur_get_rec(cursor)); + } + + /* NOTE that it is theoretically possible that the above assertions + fail if the page of the cursor gets removed from the buffer pool + meanwhile! Thus it might not be a bug. */ info->last_hash_succ = TRUE; #endif @@ -835,6 +871,8 @@ btr_search_drop_page_hash_index( n_fields = block->curr_n_fields; n_bytes = block->curr_n_bytes; + ut_a(n_fields + n_bytes > 0); + rw_lock_s_unlock(&btr_search_latch); n_recs = page_get_n_recs(page); @@ -851,6 +889,14 @@ btr_search_drop_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); + if (rec != sup) { + ut_a(n_fields <= rec_get_n_fields(rec)); + + if (n_bytes > 0) { + ut_a(n_fields < rec_get_n_fields(rec)); + } + } + tree_id = btr_page_get_index_id(page); prev_fold = 0; @@ -861,7 +907,7 @@ btr_search_drop_page_hash_index( fold = rec_fold(rec, n_fields, n_bytes, tree_id); - if ((fold == prev_fold) && (prev_fold != 0)) { + if (fold == prev_fold && prev_fold != 0) { goto next_rec; } @@ -873,6 +919,7 @@ btr_search_drop_page_hash_index( n_cached++; next_rec: rec = page_rec_get_next(rec); + prev_fold = fold; } rw_lock_x_lock(&btr_search_latch); @@ -913,7 +960,7 @@ btr_search_drop_page_hash_when_freed( mtr_start(&mtr); /* We assume that if the caller has a latch on the page, - then the caller has already drooped the hash index for the page, + then the caller has already dropped the hash index for the page, and we never get here. Therefore we can acquire the s-latch to the page without fearing a deadlock. */ @@ -980,6 +1027,8 @@ btr_search_build_page_hash_index( return; } + ut_a(n_fields + n_bytes > 0); + /* Calculate and cache fold values and corresponding records into an array for fast insertion to the hash index */ @@ -995,6 +1044,14 @@ btr_search_build_page_hash_index( rec = page_get_infimum_rec(page); rec = page_rec_get_next(rec); + if (rec != sup) { + ut_a(n_fields <= rec_get_n_fields(rec)); + + if (n_bytes > 0) { + ut_a(n_fields < rec_get_n_fields(rec)); + } + } + /* FIXME: in a mixed tree, all records may not have enough ordering fields: */ @@ -1126,6 +1183,8 @@ btr_search_move_or_delete_hash_entries( rw_lock_s_unlock(&btr_search_latch); + ut_a(n_fields + n_bytes > 0); + btr_search_build_page_hash_index(new_page, n_fields, n_bytes, side); ut_a(n_fields == block->curr_n_fields); @@ -1166,9 +1225,11 @@ btr_search_update_hash_on_delete( return; } + ut_a(block->curr_n_fields + block->curr_n_bytes > 0); + table = btr_search_sys->hash_index; - tree_id = ((cursor->index)->tree)->id; + tree_id = cursor->index->tree->id; fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes, tree_id); @@ -1285,7 +1346,6 @@ btr_search_update_hash_on_insert( if (rec != page_get_infimum_rec(page)) { fold = rec_fold(rec, n_fields, n_bytes, tree_id); - } else { if (side == BTR_SEARCH_LEFT_SIDE) { @@ -1370,7 +1430,7 @@ btr_search_print_info(void) rw_lock_x_lock(&btr_search_latch); - ha_print_info(btr_search_sys->hash_index); +/* ha_print_info(btr_search_sys->hash_index); */ rw_lock_x_unlock(&btr_search_latch); } @@ -1436,11 +1496,71 @@ btr_search_validate(void) /*=====================*/ /* out: TRUE if ok */ { + buf_block_t* block; + page_t* page; + ha_node_t* node; + ulint n_page_dumps = 0; + ibool ok = TRUE; + ulint i; + char rec_str[500]; + rw_lock_x_lock(&btr_search_latch); + + for (i = 0; i < hash_get_n_cells(btr_search_sys->hash_index); i++) { + node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node; + + while (node != NULL) { + block = buf_block_align(node->data); + page = buf_frame_align(node->data); + + if (!block->is_hashed + || node->fold != rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))) { + ok = FALSE; + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error in an adaptive hash index pointer to page %lu\n" +"ptr mem address %lu index id %lu %lu, node fold %lu, rec fold %lu\n", + buf_frame_get_page_no(page), + (ulint)(node->data), + ut_dulint_get_high(btr_page_get_index_id(page)), + ut_dulint_get_low(btr_page_get_index_id(page)), + node->fold, rec_fold((rec_t*)(node->data), + block->curr_n_fields, + block->curr_n_bytes, + btr_page_get_index_id(page))); + + rec_sprintf(rec_str, 450, (rec_t*)(node->data)); + + fprintf(stderr, + "InnoDB: Record %s\n" + "InnoDB: on that page.", rec_str); + + fprintf(stderr, +"Page mem address %lu, is hashed %lu, n fields %lu, n bytes %lu\n" +"side %lu\n", + (ulint)page, block->is_hashed, block->curr_n_fields, + block->curr_n_bytes, block->curr_side); + + if (n_page_dumps < 20) { + buf_page_print(page); + n_page_dumps++; + } + } + + node = node->next; + } + } - ut_a(ha_validate(btr_search_sys->hash_index)); + if (!ha_validate(btr_search_sys->hash_index)) { + + ok = FALSE; + } rw_lock_x_unlock(&btr_search_latch); - return(TRUE); + return(ok); } |