Commit 4442f001 authored by Marko Mäkelä's avatar Marko Mäkelä

When accessing the 'default row' record, avoid the adaptive hash index

btr_search_move_or_delete_hash_entries(): Remove third parameter.
We will already have buf_block_t::index. In some callers, skip
the call if the index is known to be the spatial index, because
there is no adaptive hash index for spatial indexes.

Also, remove useless check for dict_table_is_locking_disabled()
for ROW_FORMAT=COMPRESSED tables. There will never be temporary
ROW_FORMAT=COMPRESSED tables in InnoDB.

btr_cur_search_to_nth_level(): Do not attempt to use or
update the adaptive hash index for MIN_REC_FLAG records
(either the 'default row' or node pointers).

btr_cur_optimistic_insert(), btr_cur_pessimistic_insert(),
btr_cur_optimistic_update(), btr_cur_pessimistic_update():
Do not attempt to update the adaptive hash index for
the 'default row' record.

btr_cur_update_in_place(): Assert that the 'default row' record
is not being updated so that the ordering fields (PRIMARY KEY)
would change.

btr_cur_optimistic_delete_func(), btr_cur_pessimistic_delete():
For now, assert that the 'default row' record will not be deleted.
(FIXME: It can and must be deleted in rollback.)
parent f14ed95b
......@@ -1966,19 +1966,16 @@ btr_root_raise_and_insert(
root_page_zip, root, index, mtr);
/* Update the lock table and possible hash index. */
if (!dict_table_is_locking_disabled(index->table)) {
lock_move_rec_list_end(new_block, root_block,
page_get_infimum_rec(root));
}
lock_move_rec_list_end(new_block, root_block,
page_get_infimum_rec(root));
/* Move any existing predicate locks */
if (dict_index_is_spatial(index)) {
lock_prdt_rec_move(new_block, root_block);
} else {
btr_search_move_or_delete_hash_entries(
new_block, root_block);
}
btr_search_move_or_delete_hash_entries(new_block, root_block,
index);
}
if (dict_index_is_sec_or_ibuf(index)) {
......@@ -3093,16 +3090,12 @@ btr_page_split_and_insert(
ULINT_UNDEFINED, mtr);
/* Update the lock table and possible hash index. */
if (!dict_table_is_locking_disabled(
cursor->index->table)) {
lock_move_rec_list_start(
new_block, block, move_limit,
new_page + PAGE_NEW_INFIMUM);
}
lock_move_rec_list_start(
new_block, block, move_limit,
new_page + PAGE_NEW_INFIMUM);
btr_search_move_or_delete_hash_entries(
new_block, block, cursor->index);
new_block, block);
/* Delete the records from the source page. */
......@@ -3139,16 +3132,12 @@ btr_page_split_and_insert(
cursor->index, mtr);
/* Update the lock table and possible hash index. */
if (!dict_table_is_locking_disabled(
cursor->index->table)) {
lock_move_rec_list_end(
new_block, block, move_limit);
}
lock_move_rec_list_end(new_block, block, move_limit);
ut_ad(!dict_index_is_spatial(index));
btr_search_move_or_delete_hash_entries(
new_block, block, cursor->index);
new_block, block);
/* Delete the records from the source page. */
......@@ -3570,18 +3559,16 @@ btr_lift_page_up(
/* Update the lock table and possible hash index. */
if (!dict_table_is_locking_disabled(index->table)) {
lock_move_rec_list_end(father_block, block,
page_get_infimum_rec(page));
}
lock_move_rec_list_end(father_block, block,
page_get_infimum_rec(page));
/* Also update the predicate locks */
if (dict_index_is_spatial(index)) {
lock_prdt_rec_move(father_block, block);
} else {
btr_search_move_or_delete_hash_entries(
father_block, block);
}
btr_search_move_or_delete_hash_entries(father_block, block,
index);
}
if (!dict_table_is_locking_disabled(index->table)) {
......
......@@ -1032,6 +1032,7 @@ btr_cur_search_to_nth_level(
will have to check it again. */
&& btr_search_enabled
&& !modify_external
&& !(tuple->info_bits & REC_INFO_MIN_REC_FLAG)
&& rw_lock_get_writer(btr_get_search_latch(index))
== RW_LOCK_NOT_LOCKED
&& btr_search_guess_on_hash(index, info, tuple, mode,
......@@ -2075,11 +2076,12 @@ btr_cur_search_to_nth_level(
will properly check btr_search_enabled again in
btr_search_build_page_hash_index() before building a
page hash index, while holding search latch. */
if (btr_search_enabled
if (!btr_search_enabled) {
# ifdef MYSQL_INDEX_DISABLE_AHI
&& !index->disable_ahi
} else if (index->disable_ahi) {
# endif
) {
} else if (tuple->info_bits & REC_INFO_MIN_REC_FLAG) {
} else {
btr_search_info_update(index, cursor);
}
#endif /* BTR_CUR_HASH_ADAPT */
......@@ -3191,6 +3193,11 @@ btr_cur_optimistic_insert(
# ifdef MYSQL_INDEX_DISABLE_AHI
} else if (index->disable_ahi) {
# endif
} else if (entry->info_bits & REC_INFO_MIN_REC_FLAG) {
ut_ad(entry->info_bits == (REC_STATUS_COLUMNS_ADDED
| REC_INFO_MIN_REC_FLAG));
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert(cursor);
} else {
......@@ -3394,7 +3401,14 @@ btr_cur_pessimistic_insert(
# ifdef MYSQL_INDEX_DISABLE_AHI
if (index->disable_ahi); else
# endif
if (entry->info_bits & REC_INFO_MIN_REC_FLAG) {
ut_ad(entry->info_bits == (REC_STATUS_COLUMNS_ADDED
| REC_INFO_MIN_REC_FLAG));
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else {
btr_search_update_hash_on_insert(cursor);
}
#endif /* BTR_CUR_HASH_ADAPT */
if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) {
......@@ -3746,6 +3760,11 @@ btr_cur_update_in_place(
| BTR_CREATE_FLAG | BTR_KEEP_SYS_FLAG));
ut_ad(fil_page_index_page_check(btr_cur_get_page(cursor)));
ut_ad(btr_page_get_index_id(btr_cur_get_page(cursor)) == index->id);
ut_ad(!(update->info_bits & REC_INFO_MIN_REC_FLAG)
|| update->info_bits == (REC_STATUS_COLUMNS_ADDED
| REC_INFO_MIN_REC_FLAG));
ut_ad(!(update->info_bits & REC_INFO_MIN_REC_FLAG)
|| index->is_instant());
DBUG_LOG("ib_cur",
"update-in-place " << index->name << " (" << index->id
......@@ -3806,7 +3825,7 @@ btr_cur_update_in_place(
if (!dict_index_is_clust(index)
|| row_upd_changes_ord_field_binary(index, update, thr,
NULL, NULL)) {
ut_ad(!(update->info_bits & REC_INFO_MIN_REC_FLAG));
/* Remove possible hash index pointer to this record */
btr_search_update_hash_on_delete(cursor);
}
......@@ -4085,7 +4104,12 @@ btr_cur_optimistic_update(
lock_rec_store_on_page_infimum(block, rec);
}
btr_search_update_hash_on_delete(cursor);
if (new_entry->info_bits & REC_INFO_MIN_REC_FLAG) {
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else {
btr_search_update_hash_on_delete(cursor);
}
page_cur_delete_rec(page_cursor, index, *offsets, mtr);
......@@ -4410,7 +4434,12 @@ btr_cur_pessimistic_update(
lock_rec_store_on_page_infimum(block, rec);
}
btr_search_update_hash_on_delete(cursor);
if (new_entry->info_bits & REC_INFO_MIN_REC_FLAG) {
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else {
btr_search_update_hash_on_delete(cursor);
}
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
......@@ -5069,6 +5098,8 @@ btr_cur_optimistic_delete_func(
|| (flags & BTR_CREATE_FLAG));
rec = btr_cur_get_rec(cursor);
ut_ad(!(rec_get_info_bits(rec, page_rec_is_comp(rec))
& REC_INFO_MIN_REC_FLAG));
offsets = rec_get_offsets(rec, cursor->index, offsets, true,
ULINT_UNDEFINED, &heap);
......@@ -5212,6 +5243,9 @@ btr_cur_pessimistic_delete(
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
ut_ad(!page_is_leaf(page)
|| !(rec_get_info_bits(rec, page_rec_is_comp(rec))
& REC_INFO_MIN_REC_FLAG));
offsets = rec_get_offsets(rec, index, NULL, page_is_leaf(page),
ULINT_UNDEFINED, &heap);
......
......@@ -1552,47 +1552,37 @@ btr_search_build_page_hash_index(
}
}
/** Moves or deletes hash entries for moved records. If new_page is already
hashed, then the hash index for page, if any, is dropped. If new_page is not
hashed, and page is hashed, then a new hash index is built to new_page with the
same parameters as page (this often happens when a page is split).
@param[in,out] new_block records are copied to this page.
@param[in,out] block index page from which record are copied, and the
copied records will be deleted from this page.
@param[in,out] index record descriptor */
/** Move or delete hash entries for moved records, usually in a page split.
If new_block is already hashed, then any hash index for block is dropped.
If new_block is not hashed, and block is hashed, then a new hash index is
built to new_block with the same parameters as block.
@param[in,out] new_block destination page
@param[in,out] block source page (subject to deletion later) */
void
btr_search_move_or_delete_hash_entries(
buf_block_t* new_block,
buf_block_t* block,
dict_index_t* index)
buf_block_t* block)
{
#ifdef MYSQL_INDEX_DISABLE_AHI
if (index->disable_ahi) return;
#endif
if (!btr_search_enabled) {
return;
}
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_X));
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_X));
btr_search_s_lock(index);
if (!btr_search_enabled) {
return;
}
ut_a(!new_block->index || new_block->index == index);
ut_a(!block->index || block->index == index);
ut_a(!(new_block->index || block->index)
|| !dict_index_is_ibuf(index));
assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block);
if (new_block->index) {
btr_search_s_unlock(index);
btr_search_drop_page_hash_index(block);
return;
}
dict_index_t* index = block->index;
if (!index) {
return;
}
btr_search_s_lock(index);
if (block->index) {
ulint n_fields = block->curr_n_fields;
......
......@@ -4367,9 +4367,9 @@ innobase_add_instant_try(
btr_pcur_open(index, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &pcur, &mtr);
/* FIXME: calculate and apply an update vector
with the instantly added columns */
/* FIXME: drop any AHI entries for the modified
leaf pages during the update */
with the instantly added columns (no changes
to key columns!) */
btr_pcur_close(&pcur);
} else if (page_t* root = btr_root_get(index, &mtr)) {
#ifdef UNIV_DEBUG
switch (fil_page_get_type(root)) {
......@@ -4395,8 +4395,6 @@ innobase_add_instant_try(
err = row_ins_clust_index_entry_low(
BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index,
index->n_uniq, entry, 0, ctx->thr, false);
/* FIXME: drop any AHI entries for the modified
leaf pages during the insert */
} else {
err = DB_CORRUPTION;
}
......
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
......@@ -106,19 +107,16 @@ btr_search_guess_on_hash(
ulint has_search_latch,
mtr_t* mtr);
/** Moves or deletes hash entries for moved records. If new_page is already
hashed, then the hash index for page, if any, is dropped. If new_page is not
hashed, and page is hashed, then a new hash index is built to new_page with the
same parameters as page (this often happens when a page is split).
@param[in,out] new_block records are copied to this page.
@param[in,out] block index page from which record are copied, and the
copied records will be deleted from this page.
@param[in,out] index record descriptor */
/** Move or delete hash entries for moved records, usually in a page split.
If new_block is already hashed, then any hash index for block is dropped.
If new_block is not hashed, and block is hashed, then a new hash index is
built to new_block with the same parameters as block.
@param[in,out] new_block destination page
@param[in,out] block source page (subject to deletion later) */
void
btr_search_move_or_delete_hash_entries(
buf_block_t* new_block,
buf_block_t* block,
dict_index_t* index);
buf_block_t* block);
/** Drop any adaptive hash index entries that point to an index page.
@param[in,out] block block containing index page, s- or x-latched, or an
......@@ -252,7 +250,7 @@ btr_get_search_table(const dict_index_t* index);
# define btr_search_x_lock(index)
# define btr_search_x_unlock(index)
# define btr_search_info_update(index, cursor)
# define btr_search_move_or_delete_hash_entries(new_block, block, index)
# define btr_search_move_or_delete_hash_entries(new_block, block)
# define btr_search_update_hash_on_insert(cursor)
# define btr_search_update_hash_on_delete(cursor)
# define btr_search_sys_resize(hash_size)
......
......@@ -769,9 +769,10 @@ page_copy_rec_list_end(
/* Update the lock table and possible hash index */
if (dict_index_is_spatial(index) && rec_move) {
if (dict_table_is_locking_disabled(index->table)) {
} else if (rec_move && dict_index_is_spatial(index)) {
lock_rtr_move_rec_list(new_block, block, rec_move, num_moved);
} else if (!dict_table_is_locking_disabled(index->table)) {
} else {
lock_move_rec_list_end(new_block, block, rec);
}
......@@ -779,7 +780,7 @@ page_copy_rec_list_end(
mem_heap_free(heap);
}
btr_search_move_or_delete_hash_entries(new_block, block, index);
btr_search_move_or_delete_hash_entries(new_block, block);
return(ret);
}
......@@ -929,9 +930,10 @@ page_copy_rec_list_start(
/* Update the lock table and possible hash index */
if (dict_index_is_spatial(index)) {
if (dict_table_is_locking_disabled(index->table)) {
} else if (dict_index_is_spatial(index)) {
lock_rtr_move_rec_list(new_block, block, rec_move, num_moved);
} else if (!dict_table_is_locking_disabled(index->table)) {
} else {
lock_move_rec_list_start(new_block, block, rec, ret);
}
......@@ -939,7 +941,7 @@ page_copy_rec_list_start(
mem_heap_free(heap);
}
btr_search_move_or_delete_hash_entries(new_block, block, index);
btr_search_move_or_delete_hash_entries(new_block, block);
return(ret);
}
......
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