summaryrefslogtreecommitdiff
path: root/innobase/btr
diff options
context:
space:
mode:
authormonty@mashka.mysql.fi <>2002-07-25 22:46:28 +0300
committermonty@mashka.mysql.fi <>2002-07-25 22:46:28 +0300
commitbc035c71f1d94649253e4dac5fb8e5c981c7d834 (patch)
treef38c137c73206e3d059517b2bcab6a4a43c957f9 /innobase/btr
parentb126501bf3888b09fad83dbd2894709c45f009fc (diff)
parent3c9f1a9ae47e4fcbede526430b0171e8ba17d948 (diff)
downloadmariadb-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.c30
-rw-r--r--innobase/btr/btr0cur.c93
-rw-r--r--innobase/btr/btr0sea.c164
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);
}