48 UNIV_INTERN
bool btr_search_enabled = TRUE;
49 UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
52 static mutex_t btr_search_enabled_mutex;
55 UNIV_INTERN ulint btr_search_this_is_zero = 0;
57 #ifdef UNIV_SEARCH_PERF_STAT
59 UNIV_INTERN ulint btr_search_n_succ = 0;
61 UNIV_INTERN ulint btr_search_n_hash_fail = 0;
67 UNIV_INTERN byte btr_sea_pad1[64];
81 UNIV_INTERN byte btr_sea_pad2[64];
86 #ifdef UNIV_PFS_RWLOCK
88 UNIV_INTERN mysql_pfs_key_t btr_search_latch_key;
94 #define BTR_SEARCH_PAGE_BUILD_LIMIT 16
98 #define BTR_SEARCH_BUILD_LIMIT 100
107 btr_search_build_page_hash_index(
129 btr_search_check_free_space_in_heap(
void)
135 #ifdef UNIV_SYNC_DEBUG
148 if (heap->free_block == NULL) {
153 if (heap->free_block == NULL) {
154 heap->free_block = block;
167 btr_search_sys_create(
178 mutex_create(btr_search_enabled_mutex_key,
179 &btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
190 btr_search_sys_free(
void)
195 btr_search_latch_temp = NULL;
199 btr_search_sys = NULL;
206 btr_search_disable(
void)
209 mutex_enter(&btr_search_enabled_mutex);
215 btr_search_enabled = FALSE;
219 buf_pool_drop_hash_index();
223 btr_search_fully_disabled = TRUE;
226 ut_ad(!btr_search_enabled);
229 mutex_exit(&btr_search_enabled_mutex);
236 btr_search_enable(
void)
239 mutex_enter(&btr_search_enabled_mutex);
242 btr_search_enabled = TRUE;
243 btr_search_fully_disabled = FALSE;
246 mutex_exit(&btr_search_enabled_mutex);
254 btr_search_info_create(
263 info->magic_n = BTR_SEARCH_MAGIC_N;
274 #ifdef UNIV_SEARCH_PERF_STAT
275 info->n_hash_succ = 0;
276 info->n_hash_fail = 0;
277 info->n_patt_succ = 0;
278 info->n_searches = 0;
296 btr_search_info_get_ref_count(
304 #ifdef UNIV_SYNC_DEBUG
322 btr_search_info_update_hash(
331 #ifdef UNIV_SYNC_DEBUG
336 index = cursor->
index;
365 if (info->
left_side ? cmp <= 0 : cmp > 0) {
373 if (info->
left_side ? cmp <= 0 : cmp > 0) {
375 goto increment_potential;
397 }
else if (cmp > 0) {
443 btr_search_update_block_hash_info(
450 #ifdef UNIV_SYNC_DEBUG
453 ut_ad(rw_lock_own(&block->
lock, RW_LOCK_SHARED)
454 || rw_lock_own(&block->
lock, RW_LOCK_EX));
461 ut_ad(info->magic_n == BTR_SEARCH_MAGIC_N);
489 if (cursor->
index->
table->does_not_fit_in_memory) {
495 / BTR_SEARCH_PAGE_BUILD_LIMIT)
524 btr_search_update_hash_ref(
535 #ifdef UNIV_SYNC_DEBUG
537 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
538 || rw_lock_own(&(block->
lock), RW_LOCK_EX));
541 == buf_block_get_frame(block));
556 ulint offsets_[REC_OFFS_NORMAL_SIZE];
557 rec_offs_init(offsets_);
568 rec_get_offsets(rec, cursor->
index, offsets_,
569 ULINT_UNDEFINED, &heap),
572 if (UNIV_LIKELY_NULL(heap)) {
575 #ifdef UNIV_SYNC_DEBUG
588 btr_search_info_update_slow(
598 #ifdef UNIV_SYNC_DEBUG
610 btr_search_info_update_hash(info, cursor);
612 build_index = btr_search_update_block_hash_info(info, block, cursor);
616 btr_search_check_free_space_in_heap();
622 #ifdef UNIV_SEARCH_PERF_STAT
623 btr_search_n_hash_fail++;
628 btr_search_update_hash_ref(info, block, cursor);
642 params = (ulint *)mem_alloc(3 *
sizeof(ulint));
650 params2 = params + btr_search_this_is_zero;
652 btr_search_build_page_hash_index(cursor->
index,
668 btr_search_check_guess(
671 ibool can_only_compare_to_cursor_rec,
690 ulint offsets_[REC_OFFS_NORMAL_SIZE];
691 ulint* offsets = offsets_;
692 ibool success = FALSE;
693 rec_offs_init(offsets_);
704 offsets = rec_get_offsets(rec, cursor->
index, offsets,
707 offsets, &match, &bytes);
709 if (mode == PAGE_CUR_GE) {
716 if (match >= n_unique) {
720 }
else if (mode == PAGE_CUR_LE) {
727 }
else if (mode == PAGE_CUR_G) {
731 }
else if (mode == PAGE_CUR_L) {
737 if (can_only_compare_to_cursor_rec) {
746 if ((mode == PAGE_CUR_G) || (mode == PAGE_CUR_GE)) {
760 offsets = rec_get_offsets(prev_rec, cursor->
index, offsets,
763 offsets, &match, &bytes);
764 if (mode == PAGE_CUR_GE) {
789 offsets = rec_get_offsets(next_rec, cursor->
index, offsets,
792 offsets, &match, &bytes);
793 if (mode == PAGE_CUR_LE) {
801 if (UNIV_LIKELY_NULL(heap)) {
815 btr_search_guess_on_hash(
828 ulint has_search_latch,
842 ut_ad(index && info && tuple && cursor && mtr);
863 index_id = index->
id;
865 #ifdef UNIV_SEARCH_PERF_STAT
873 if (UNIV_LIKELY(!has_search_latch)) {
876 if (UNIV_UNLIKELY(!btr_search_enabled)) {
886 if (UNIV_UNLIKELY(!rec)) {
890 block = buf_block_align(rec);
892 if (UNIV_LIKELY(!has_search_latch)) {
895 !buf_page_get_known_nowait(latch_mode, block,
904 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
910 if (UNIV_LIKELY(!has_search_latch)) {
930 || !btr_search_check_guess(cursor,
933 if (UNIV_LIKELY(!has_search_latch)) {
952 ut_ad(!has_search_latch);
956 btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
958 if (mode == PAGE_CUR_GE
967 btr_pcur_open_on_user_rec(index, tuple, mode, latch_mode,
980 #ifdef UNIV_SEARCH_PERF_STAT
983 if (UNIV_LIKELY(!has_search_latch)
986 buf_page_make_young(&block->
page);
998 if (UNIV_LIKELY(!has_search_latch)) {
1004 #ifdef UNIV_SEARCH_PERF_STAT
1005 info->n_hash_fail++;
1007 if (info->n_hash_succ > 0) {
1008 info->n_hash_succ--;
1020 btr_search_drop_page_hash_index(
1034 index_id_t index_id;
1043 #ifdef UNIV_SYNC_DEBUG
1050 page = block->
frame;
1061 #ifdef UNIV_SYNC_DEBUG
1062 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
1063 || rw_lock_own(&(block->
lock), RW_LOCK_EX)
1069 index = block->
index;
1078 ut_a(n_fields + n_bytes > 0);
1085 folds = (ulint *)mem_alloc(n_recs *
sizeof(ulint));
1089 rec = page_get_infimum_rec(page);
1094 ut_a(index_id == index->
id);
1102 offsets = rec_get_offsets(rec, index, offsets,
1103 n_fields + (n_bytes > 0), &heap);
1105 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1107 if (fold == prev_fold && prev_fold != 0) {
1115 folds[n_cached] = fold;
1122 if (UNIV_LIKELY_NULL(heap)) {
1148 for (i = 0; i < n_cached; i++) {
1150 ha_remove_all_nodes_to_page(table, folds[i], page);
1157 block->
index = NULL;
1160 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1161 if (UNIV_UNLIKELY(block->n_pointers)) {
1165 " InnoDB: Corruption of adaptive hash index."
1167 "InnoDB: the hash index to a page of %s,"
1168 " still %lu hash nodes remain.\n",
1169 index->
name, (ulong) block->n_pointers);
1172 btr_search_validate();
1188 btr_search_drop_page_hash_when_freed(
1198 if (!buf_page_peek_if_search_hashed(space, page_no)) {
1210 block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
1219 if (UNIV_LIKELY(block != NULL)) {
1221 buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
1223 btr_search_drop_page_hash_index(block);
1236 btr_search_build_page_hash_index(
1251 index_id_t index_id;
1258 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1259 ulint* offsets = offsets_;
1260 rec_offs_init(offsets_);
1266 page = buf_block_get_frame(block);
1268 #ifdef UNIV_SYNC_DEBUG
1270 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_SHARED)
1271 || rw_lock_own(&(block->
lock), RW_LOCK_EX));
1282 btr_search_drop_page_hash_index(block);
1296 if (n_fields + n_bytes == 0) {
1310 folds = (ulint *)mem_alloc(n_recs *
sizeof(ulint));
1311 recs = (rec_t **)mem_alloc(n_recs *
sizeof(rec_t*));
1319 offsets = rec_get_offsets(rec, index, offsets,
1320 n_fields + (n_bytes > 0), &heap);
1330 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1334 folds[n_cached] = fold;
1335 recs[n_cached] = rec;
1346 folds[n_cached] = fold;
1347 recs[n_cached] = rec;
1354 offsets = rec_get_offsets(next_rec, index, offsets,
1355 n_fields + (n_bytes > 0), &heap);
1356 next_fold =
rec_fold(next_rec, offsets, n_fields,
1359 if (fold != next_fold) {
1364 folds[n_cached] = next_fold;
1365 recs[n_cached] = next_rec;
1368 folds[n_cached] = fold;
1369 recs[n_cached] = rec;
1378 btr_search_check_free_space_in_heap();
1382 if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
1407 block->
index = index;
1409 for (i = 0; i < n_cached; i++) {
1419 if (UNIV_LIKELY_NULL(heap)) {
1431 btr_search_move_or_delete_hash_entries(
1445 #ifdef UNIV_SYNC_DEBUG
1446 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1447 ut_ad(rw_lock_own(&(new_block->
lock), RW_LOCK_EX));
1460 btr_search_drop_page_hash_index(block);
1477 ut_a(n_fields + n_bytes > 0);
1479 btr_search_build_page_hash_index(index, new_block, n_fields,
1480 n_bytes, left_side);
1494 btr_search_update_hash_on_delete(
1504 index_id_t index_id;
1505 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1507 rec_offs_init(offsets_);
1513 #ifdef UNIV_SYNC_DEBUG
1514 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1529 fold =
rec_fold(rec, rec_get_offsets(rec, cursor->
index, offsets_,
1530 ULINT_UNDEFINED, &heap),
1532 if (UNIV_LIKELY_NULL(heap)) {
1546 btr_search_update_hash_node_on_insert(
1561 #ifdef UNIV_SYNC_DEBUG
1562 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1589 btr_search_update_hash_on_insert(cursor);
1597 btr_search_update_hash_on_insert(
1609 index_id_t index_id;
1612 ulint next_fold = 0;
1616 ibool locked = FALSE;
1618 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1619 ulint* offsets = offsets_;
1620 rec_offs_init(offsets_);
1624 btr_search_check_free_space_in_heap();
1630 #ifdef UNIV_SYNC_DEBUG
1631 ut_ad(rw_lock_own(&(block->
lock), RW_LOCK_EX));
1651 offsets = rec_get_offsets(ins_rec, cursor->
index, offsets,
1652 ULINT_UNDEFINED, &heap);
1653 ins_fold =
rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
1656 offsets = rec_get_offsets(next_rec, cursor->
index, offsets,
1657 n_fields + (n_bytes > 0), &heap);
1658 next_fold =
rec_fold(next_rec, offsets, n_fields,
1663 offsets = rec_get_offsets(rec, cursor->
index, offsets,
1664 n_fields + (n_bytes > 0), &heap);
1665 fold =
rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1676 goto check_next_rec;
1679 if (fold != ins_fold) {
1712 if (ins_fold != next_fold) {
1735 if (UNIV_LIKELY_NULL(heap)) {
1743 #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1749 btr_search_validate(
void)
1753 ulint n_page_dumps = 0;
1758 ulint offsets_[REC_OFFS_NORMAL_SIZE];
1759 ulint* offsets = offsets_;
1763 ulint chunk_size = 10000;
1765 rec_offs_init(offsets_);
1772 for (i = 0; i < cell_count; i++) {
1775 if ((i != 0) && ((i % chunk_size) == 0)) {
1785 for (; node != NULL; node = node->
next) {
1787 = buf_block_align(node->
data);
1790 index_id_t page_index_id;
1811 ut_a(hash_block == block);
1829 offsets = rec_get_offsets((
const rec_t*) node->
data,
1830 block->
index, offsets,
1850 " InnoDB: Error in an adaptive hash"
1851 " index pointer to page %lu\n"
1852 "InnoDB: ptr mem address %p"
1854 " node fold %lu, rec fold %lu\n",
1857 (ullint) page_index_id,
1865 fputs(
"InnoDB: Record ", stderr);
1868 fprintf(stderr,
"\nInnoDB: on that page."
1869 " Page mem address %p, is hashed %lu,"
1870 " n fields %lu, n bytes %lu\n"
1871 "InnoDB: side %lu\n",
1877 if (n_page_dumps < 20) {
1878 buf_page_print(page, 0);
1885 for (i = 0; i < cell_count; i += chunk_size) {
1886 ulint end_index =
ut_min(i + chunk_size - 1, cell_count - 1);
1898 if (!ha_validate(btr_search_sys->
hash_index, i, end_index)) {
1905 if (UNIV_LIKELY_NULL(heap)) {