diff options
author | heikki@hundin.mysql.fi <> | 2002-10-29 23:16:46 +0200 |
---|---|---|
committer | heikki@hundin.mysql.fi <> | 2002-10-29 23:16:46 +0200 |
commit | 9153d88c6bfbb7b1d9fd5fd1633aade67b48e774 (patch) | |
tree | e57bf300e559932ce45e0f749d7349577e7e0479 /innobase/page | |
parent | 245218284495701846f49d986bc91997b97563d6 (diff) | |
download | mariadb-git-9153d88c6bfbb7b1d9fd5fd1633aade67b48e774.tar.gz |
Many files:
Merge InnoDB-4.0.5: new isolation levels READ COMMITTED and READ UNCOMMITTED now supported, selective deadlock resolution
mysqld.cc:
Change MySQL default isolation level to REPEATABLE READ; note that InnoDB has always had that default, and BDB and MyISAM always run at SERIALIZABLE level anyway
Diffstat (limited to 'innobase/page')
-rw-r--r-- | innobase/page/page0cur.c | 52 | ||||
-rw-r--r-- | innobase/page/page0page.c | 196 |
2 files changed, 238 insertions, 10 deletions
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c index 2909573b14b..bb49e9080ce 100644 --- a/innobase/page/page0cur.c +++ b/innobase/page/page0cur.c @@ -169,7 +169,7 @@ page_cur_search_with_match( ut_ad(dtuple_check_typed(tuple)); ut_ad((mode == PAGE_CUR_L) || (mode == PAGE_CUR_LE) || (mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE) - || (mode == PAGE_CUR_DBG)); + || (mode == PAGE_CUR_LE_OR_EXTENDS) || (mode == PAGE_CUR_DBG)); #ifdef PAGE_CUR_ADAPT if ((page_header_get_field(page, PAGE_LEVEL) == 0) @@ -232,9 +232,26 @@ page_cur_search_with_match( low_matched_bytes = cur_matched_bytes; } else if (cmp == -1) { - up = mid; - up_matched_fields = cur_matched_fields; - up_matched_bytes = cur_matched_bytes; + + if (mode == PAGE_CUR_LE_OR_EXTENDS + && dfield_get_len(dtuple_get_nth_field(tuple, + cur_matched_fields)) + == cur_matched_bytes + && rec_get_nth_field_len(mid_rec, + cur_matched_fields) + != UNIV_SQL_NULL) { + + /* This means current dfield is not SQL + NULL, and the current rec field extends it */ + + low = mid; + low_matched_fields = cur_matched_fields; + low_matched_bytes = cur_matched_bytes; + } else { + up = mid; + up_matched_fields = cur_matched_fields; + up_matched_bytes = cur_matched_bytes; + } } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { low = mid; @@ -252,8 +269,8 @@ page_cur_search_with_match( slot = page_dir_get_nth_slot(page, up); up_rec = page_dir_slot_get_rec(slot); - /* Perform linear search until the upper and lower records - come to distance 1 of each other. */ + /* Perform linear search until the upper and lower records come to + distance 1 of each other. */ while (page_rec_get_next(low_rec) != up_rec) { @@ -272,10 +289,25 @@ page_cur_search_with_match( low_matched_bytes = cur_matched_bytes; } else if (cmp == -1) { - up_rec = mid_rec; - up_matched_fields = cur_matched_fields; - up_matched_bytes = cur_matched_bytes; - + if (mode == PAGE_CUR_LE_OR_EXTENDS + && dfield_get_len(dtuple_get_nth_field(tuple, + cur_matched_fields)) + == cur_matched_bytes + && rec_get_nth_field_len(mid_rec, + cur_matched_fields) + != UNIV_SQL_NULL) { + + /* This means current dfield is not SQL + NULL, and the current rec field extends it */ + + low = mid; + low_matched_fields = cur_matched_fields; + low_matched_bytes = cur_matched_bytes; + } else { + up_rec = mid_rec; + up_matched_fields = cur_matched_fields; + up_matched_bytes = cur_matched_bytes; + } } else if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_LE)) { low_rec = mid_rec; low_matched_fields = cur_matched_fields; diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c index ed74736c8da..7d0d88c6afc 100644 --- a/innobase/page/page0page.c +++ b/innobase/page/page0page.c @@ -1313,6 +1313,194 @@ page_rec_validate( } /******************************************************************* +This function checks the consistency of an index page when we do not +know the index. This is also resilient so that this should never crash +even if the page is total garbage. */ + +ibool +page_simple_validate( +/*=================*/ + /* out: TRUE if ok */ + page_t* page) /* in: index page */ +{ + page_cur_t cur; + page_dir_slot_t* slot; + ulint slot_no; + ulint n_slots; + rec_t* rec; + byte* rec_heap_top; + ulint count; + ulint own_count; + ibool ret = FALSE; + + /* Check first that the record heap and the directory do not + overlap. */ + + n_slots = page_dir_get_n_slots(page); + + if (n_slots > UNIV_PAGE_SIZE / 4) { + fprintf(stderr, + "Nonsensical number %lu of page dir slots\n", n_slots); + + goto func_exit; + } + + rec_heap_top = page_header_get_ptr(page, PAGE_HEAP_TOP); + + if (rec_heap_top > page_dir_get_nth_slot(page, n_slots - 1)) { + + fprintf(stderr, + "Record heap and dir overlap on a page, heap top %lu, dir %lu\n", + (ulint)(page_header_get_ptr(page, PAGE_HEAP_TOP) - page), + (ulint)(page_dir_get_nth_slot(page, n_slots - 1) - page)); + + goto func_exit; + } + + /* Validate the record list in a loop checking also that it is + consistent with the page record directory. */ + + count = 0; + own_count = 1; + slot_no = 0; + slot = page_dir_get_nth_slot(page, slot_no); + + page_cur_set_before_first(page, &cur); + + for (;;) { + rec = (&cur)->rec; + + if (rec > rec_heap_top) { + fprintf(stderr, + "Record %lu is above rec heap top %lu\n", + (ulint)(rec - page), (ulint)(rec_heap_top - page)); + + goto func_exit; + } + + if (rec_get_n_owned(rec) != 0) { + /* This is a record pointed to by a dir slot */ + if (rec_get_n_owned(rec) != own_count) { + + fprintf(stderr, + "Wrong owned count %lu, %lu, rec %lu\n", + rec_get_n_owned(rec), own_count, + (ulint)(rec - page)); + + goto func_exit; + } + + if (page_dir_slot_get_rec(slot) != rec) { + fprintf(stderr, + "Dir slot does not point to right rec %lu\n", + (ulint)(rec - page)); + + goto func_exit; + } + + own_count = 0; + + if (!page_cur_is_after_last(&cur)) { + slot_no++; + slot = page_dir_get_nth_slot(page, slot_no); + } + } + + if (page_cur_is_after_last(&cur)) { + + break; + } + + if (rec_get_next_offs(rec) < FIL_PAGE_DATA + || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) { + fprintf(stderr, + "Next record offset nonsensical %lu for rec %lu\n", + rec_get_next_offs(rec), + (ulint)(rec - page)); + + goto func_exit; + } + + count++; + + if (count > UNIV_PAGE_SIZE) { + fprintf(stderr, + "Page record list appears to be circular %lu\n", + count); + goto func_exit; + } + + page_cur_move_to_next(&cur); + own_count++; + } + + if (rec_get_n_owned(rec) == 0) { + fprintf(stderr, "n owned is zero in a supremum rec\n"); + + goto func_exit; + } + + if (slot_no != n_slots - 1) { + fprintf(stderr, "n slots wrong %lu, %lu\n", + slot_no, n_slots - 1); + goto func_exit; + } + + if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) { + fprintf(stderr, "n recs wrong %lu %lu\n", + page_header_get_field(page, PAGE_N_RECS) + 2, count + 1); + + goto func_exit; + } + + /* Check then the free list */ + rec = page_header_get_ptr(page, PAGE_FREE); + + while (rec != NULL) { + if (rec < page + FIL_PAGE_DATA + || rec >= page + UNIV_PAGE_SIZE) { + fprintf(stderr, + "Free list record has a nonsensical offset %lu\n", + (ulint)(rec - page)); + + goto func_exit; + } + + if (rec > rec_heap_top) { + fprintf(stderr, + "Free list record %lu is above rec heap top %lu\n", + (ulint)(rec - page), (ulint)(rec_heap_top - page)); + + goto func_exit; + } + + count++; + + if (count > UNIV_PAGE_SIZE) { + fprintf(stderr, + "Page free list appears to be circular %lu\n", + count); + goto func_exit; + } + + rec = page_rec_get_next(rec); + } + + if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) { + + fprintf(stderr, "N heap is wrong %lu, %lu\n", + page_header_get_field(page, PAGE_N_HEAP), count + 1); + + goto func_exit; + } + + ret = TRUE; + +func_exit: + return(ret); +} + +/******************************************************************* This function checks the consistency of an index page. */ ibool @@ -1339,6 +1527,14 @@ page_validate( ulint i; char err_buf[1000]; + if (!page_simple_validate(page)) { + buf_page_print(page); + + fprintf(stderr, "Apparent corruption in a page in index %s\n", + index->name); + return(FALSE); + } + heap = mem_heap_create(UNIV_PAGE_SIZE); /* The following buffer is used to check that the |