Commit 086fe412 authored by heikki@donna.mysql.fi's avatar heikki@donna.mysql.fi

btr0cur.c, btr0btr.c, dict0dict.h, dict0dict.c:

  Fix a bug in insert buffer B-tree upper levels; probably caused the crash by B.Fitzpatrick
buf0flu.c:
  Fix a bug in previous change
  A small optimization for LRU flushes to avoid losing hot pages from the buffer pool
parent 3ed8188b
...@@ -21,7 +21,7 @@ Created 6/2/1994 Heikki Tuuri ...@@ -21,7 +21,7 @@ Created 6/2/1994 Heikki Tuuri
#include "lock0lock.h" #include "lock0lock.h"
#include "ibuf0ibuf.h" #include "ibuf0ibuf.h"
/** /*
Node pointers Node pointers
------------- -------------
Leaf pages of a B-tree contain the index records stored in the Leaf pages of a B-tree contain the index records stored in the
...@@ -550,14 +550,15 @@ btr_page_get_father_for_rec( ...@@ -550,14 +550,15 @@ btr_page_get_father_for_rec(
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(user_rec != page_get_supremum_rec(page)); ut_a(user_rec != page_get_supremum_rec(page));
ut_ad(user_rec != page_get_infimum_rec(page)); ut_a(user_rec != page_get_infimum_rec(page));
ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page)); ut_ad(dict_tree_get_page(tree) != buf_frame_get_page_no(page));
heap = mem_heap_create(100); heap = mem_heap_create(100);
tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap); tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
btr_page_get_level(page, mtr));
/* In the following, we choose just any index from the tree as the /* In the following, we choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */ first parameter for btr_cur_search_to_nth_level. */
...@@ -569,7 +570,7 @@ btr_page_get_father_for_rec( ...@@ -569,7 +570,7 @@ btr_page_get_father_for_rec(
node_ptr = btr_cur_get_rec(&cursor); node_ptr = btr_cur_get_rec(&cursor);
ut_ad(btr_node_ptr_get_child_page_no(node_ptr) == ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
buf_frame_get_page_no(page)); buf_frame_get_page_no(page));
mem_heap_free(heap); mem_heap_free(heap);
...@@ -949,8 +950,8 @@ btr_root_raise_and_insert( ...@@ -949,8 +950,8 @@ btr_root_raise_and_insert(
/* Build the node pointer (= node key and page address) for the /* Build the node pointer (= node key and page address) for the
child */ child */
node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap); node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap,
level);
/* Reorganize the root to get free space */ /* Reorganize the root to get free space */
btr_page_reorganize(root, mtr); btr_page_reorganize(root, mtr);
...@@ -1365,7 +1366,7 @@ btr_attach_half_pages( ...@@ -1365,7 +1366,7 @@ btr_attach_half_pages(
half */ half */
node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec, node_ptr_upper = dict_tree_build_node_ptr(tree, split_rec,
upper_page_no, heap); upper_page_no, heap, level);
/* Insert it next to the pointer to the lower half. Note that this /* Insert it next to the pointer to the lower half. Note that this
may generate recursion leading to a split on the higher level. */ may generate recursion leading to a split on the higher level. */
...@@ -2230,7 +2231,7 @@ btr_check_node_ptr( ...@@ -2230,7 +2231,7 @@ btr_check_node_ptr(
node_ptr_tuple = dict_tree_build_node_ptr( node_ptr_tuple = dict_tree_build_node_ptr(
tree, tree,
page_rec_get_next(page_get_infimum_rec(page)), page_rec_get_next(page_get_infimum_rec(page)),
0, heap); 0, heap, btr_page_get_level(page, mtr));
ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr) == 0); ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr) == 0);
...@@ -2488,7 +2489,8 @@ loop: ...@@ -2488,7 +2489,8 @@ loop:
tree, tree,
page_rec_get_next( page_rec_get_next(
page_get_infimum_rec(page)), page_get_infimum_rec(page)),
0, heap); 0, heap,
btr_page_get_level(page, &mtr));
if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) { if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
......
...@@ -2347,7 +2347,7 @@ btr_cur_pessimistic_delete( ...@@ -2347,7 +2347,7 @@ btr_cur_pessimistic_delete(
node_ptr = dict_tree_build_node_ptr( node_ptr = dict_tree_build_node_ptr(
tree, page_rec_get_next(rec), tree, page_rec_get_next(rec),
buf_frame_get_page_no(page), buf_frame_get_page_no(page),
heap); heap, btr_page_get_level(page, mtr));
btr_insert_on_non_leaf_level(tree, btr_insert_on_non_leaf_level(tree,
btr_page_get_level(page, mtr) + 1, btr_page_get_level(page, mtr) + 1,
......
...@@ -556,6 +556,15 @@ buf_flush_try_neighbors( ...@@ -556,6 +556,15 @@ buf_flush_try_neighbors(
block = buf_page_hash_get(space, i); block = buf_page_hash_get(space, i);
if (block && flush_type == BUF_FLUSH_LRU && i != offset
&& !block->old) {
/* We avoid flushing 'non-old' blocks in an LRU flush,
because the flushed blocks are soon freed */
continue;
}
if (block && buf_flush_ready_for_flush(block, flush_type)) { if (block && buf_flush_ready_for_flush(block, flush_type)) {
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
......
...@@ -2411,7 +2411,9 @@ dict_tree_build_node_ptr( ...@@ -2411,7 +2411,9 @@ dict_tree_build_node_ptr(
dict_tree_t* tree, /* in: index tree */ dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build node pointer */ rec_t* rec, /* in: record for which to build node pointer */
ulint page_no,/* in: page number to put in node pointer */ ulint page_no,/* in: page number to put in node pointer */
mem_heap_t* heap) /* in: memory heap where pointer created */ mem_heap_t* heap, /* in: memory heap where pointer created */
ibool level) /* in: level of rec in tree: 0 means leaf
level */
{ {
dtuple_t* tuple; dtuple_t* tuple;
dict_index_t* ind; dict_index_t* ind;
...@@ -2423,9 +2425,16 @@ dict_tree_build_node_ptr( ...@@ -2423,9 +2425,16 @@ dict_tree_build_node_ptr(
if (tree->type & DICT_UNIVERSAL) { if (tree->type & DICT_UNIVERSAL) {
/* In a universal index tree, we take the whole record as /* In a universal index tree, we take the whole record as
the node pointer */ the node pointer if the reord is on the leaf level,
on non-leaf levels we remove the last field, which
contains the page number of the child page */
n_unique = rec_get_n_fields(rec); n_unique = rec_get_n_fields(rec);
if (level > 0) {
ut_a(n_unique > 1);
n_unique--;
}
} else { } else {
n_unique = dict_index_get_n_unique_in_tree(ind); n_unique = dict_index_get_n_unique_in_tree(ind);
} }
......
...@@ -622,7 +622,9 @@ dict_tree_build_node_ptr( ...@@ -622,7 +622,9 @@ dict_tree_build_node_ptr(
dict_tree_t* tree, /* in: index tree */ dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build node pointer */ rec_t* rec, /* in: record for which to build node pointer */
ulint page_no,/* in: page number to put in node pointer */ ulint page_no,/* in: page number to put in node pointer */
mem_heap_t* heap); /* in: memory heap where pointer created */ mem_heap_t* heap, /* in: memory heap where pointer created */
ibool level); /* in: level of rec in tree: 0 means leaf
level */
/************************************************************************** /**************************************************************************
Copies an initial segment of a physical record, long enough to specify an Copies an initial segment of a physical record, long enough to specify an
index entry uniquely. */ index entry uniquely. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment