46
46
/** Flag: has the search system been enabled?
47
Protected by btr_search_latch and btr_search_enabled_mutex. */
47
Protected by btr_search_latch. */
48
48
UNIV_INTERN char btr_search_enabled = TRUE;
49
UNIV_INTERN ibool btr_search_fully_disabled = FALSE;
51
/** Mutex protecting btr_search_enabled */
52
static mutex_t btr_search_enabled_mutex;
54
50
#ifdef UNIV_PFS_MUTEX
55
51
/* Key to register btr_search_enabled_mutex with performance schema */
181
177
rw_lock_create(btr_search_latch_key, &btr_search_latch,
182
178
SYNC_SEARCH_SYS);
183
mutex_create(btr_search_enabled_mutex_key,
184
&btr_search_enabled_mutex, SYNC_SEARCH_SYS_CONF);
186
180
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
211
205
btr_search_disable(void)
212
206
/*====================*/
214
mutex_enter(&btr_search_enabled_mutex);
210
mutex_enter(&dict_sys->mutex);
215
211
rw_lock_x_lock(&btr_search_latch);
217
/* Disable access to hash index, also tell ha_insert_for_fold()
218
stop adding new nodes to hash index, but still allow updating
220
213
btr_search_enabled = FALSE;
222
/* Clear all block->is_hashed flags and remove all entries
223
from btr_search_sys->hash_index. */
224
buf_pool_drop_hash_index();
226
/* hash index has been cleaned up, disallow any operation to
228
btr_search_fully_disabled = TRUE;
230
/* btr_search_enabled_mutex should guarantee this. */
231
ut_ad(!btr_search_enabled);
215
/* Clear the index->search_info->ref_count of every index in
216
the data dictionary cache. */
217
for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
218
table = UT_LIST_GET_NEXT(table_LRU, table)) {
222
for (index = dict_table_get_first_index(table); index;
223
index = dict_table_get_next_index(index)) {
225
index->search_info->ref_count = 0;
229
mutex_exit(&dict_sys->mutex);
231
/* Set all block->index = NULL. */
232
buf_pool_clear_hash_index();
234
/* Clear the adaptive hash index. */
235
hash_table_clear(btr_search_sys->hash_index);
236
mem_heap_empty(btr_search_sys->hash_index->heap);
233
238
rw_lock_x_unlock(&btr_search_latch);
234
mutex_exit(&btr_search_enabled_mutex);
237
241
/********************************************************************//**
241
245
btr_search_enable(void)
242
246
/*====================*/
244
mutex_enter(&btr_search_enabled_mutex);
245
248
rw_lock_x_lock(&btr_search_latch);
247
250
btr_search_enabled = TRUE;
248
btr_search_fully_disabled = FALSE;
250
252
rw_lock_x_unlock(&btr_search_latch);
251
mutex_exit(&btr_search_enabled_mutex);
254
255
/*****************************************************************//**
471
472
&& (block->n_bytes == info->n_bytes)
472
473
&& (block->left_side == info->left_side)) {
474
if ((block->is_hashed)
475
476
&& (block->curr_n_fields == info->n_fields)
476
477
&& (block->curr_n_bytes == info->n_bytes)
477
478
&& (block->curr_left_side == info->left_side)) {
545
546
ut_ad(page_align(btr_cur_get_rec(cursor))
546
547
== buf_block_get_frame(block));
548
if (!block->is_hashed) {
549
index = block->index;
553
ut_a(block->index == cursor->index);
554
ut_a(!dict_index_is_ibuf(cursor->index));
556
ut_a(index == cursor->index);
557
ut_a(!dict_index_is_ibuf(index));
556
559
if ((info->n_hash_potential > 0)
557
560
&& (block->curr_n_fields == info->n_fields)
571
index_id = cursor->index->id;
572
574
fold = rec_fold(rec,
573
rec_get_offsets(rec, cursor->index, offsets_,
575
rec_get_offsets(rec, index, offsets_,
574
576
ULINT_UNDEFINED, &heap),
575
577
block->curr_n_fields,
576
block->curr_n_bytes, index_id);
578
block->curr_n_bytes, index->id);
577
579
if (UNIV_LIKELY_NULL(heap)) {
578
580
mem_heap_free(heap);
924
926
ut_ad(page_rec_is_user_rec(rec));
926
btr_cur_position(index, rec, block, cursor);
928
btr_cur_position(index, (rec_t*) rec, block, cursor);
928
930
/* Check the validity of the guess within the page */
1055
1057
rw_lock_s_lock(&btr_search_latch);
1056
page = block->frame;
1058
index = block->index;
1058
if (UNIV_LIKELY(!block->is_hashed)) {
1060
if (UNIV_LIKELY(!index)) {
1060
1062
rw_lock_s_unlock(&btr_search_latch);
1067
ut_a(!dict_index_is_ibuf(index));
1065
1068
table = btr_search_sys->hash_index;
1067
1070
#ifdef UNIV_SYNC_DEBUG
1073
1076
n_fields = block->curr_n_fields;
1074
1077
n_bytes = block->curr_n_bytes;
1075
index = block->index;
1076
ut_a(!dict_index_is_ibuf(index));
1078
1079
/* NOTE: The fields of block must not be accessed after
1079
1080
releasing btr_search_latch, as the index page might only
1159
1161
ut_a(index->search_info->ref_count > 0);
1160
1162
index->search_info->ref_count--;
1162
block->is_hashed = FALSE;
1163
1164
block->index = NULL;
1166
1167
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1167
1168
if (UNIV_UNLIKELY(block->n_pointers)) {
1189
1190
/********************************************************************//**
1190
Drops a page hash index when a page is freed from a fseg to the file system.
1191
Drops possible hash index if the page happens to be in the buffer pool. */
1191
Drops a possible page hash index when a page is evicted from the buffer pool
1192
or freed in a file segment. */
1194
1195
btr_search_drop_page_hash_when_freed(
1201
1202
buf_block_t* block;
1204
if (!buf_page_peek_if_search_hashed(space, page_no)) {
1209
1205
mtr_start(&mtr);
1211
/* We assume that if the caller has a latch on the page, then the
1212
caller has already dropped the hash index for the page, and we never
1213
get here. Therefore we can acquire the s-latch to the page without
1214
having to fear a deadlock. */
1207
/* If the caller has a latch on the page, then the caller must
1208
have a x-latch on the page and it must have already dropped
1209
the hash index for the page. Because of the x-latch that we
1210
are possibly holding, we cannot s-latch the page, but must
1211
(recursively) x-latch it, even though we are only reading. */
1216
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH, NULL,
1213
block = buf_page_get_gen(space, zip_size, page_no, RW_X_LATCH, NULL,
1217
1214
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
1219
/* Because the buffer pool mutex was released by
1220
buf_page_peek_if_search_hashed(), it is possible that the
1221
block was removed from the buffer pool by another thread
1222
before buf_page_get_gen() got a chance to acquire the buffer
1223
pool mutex again. Thus, we must check for a NULL return. */
1225
if (UNIV_LIKELY(block != NULL)) {
1217
if (block && block->index) {
1227
1219
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
1269
1260
ut_a(!dict_index_is_ibuf(index));
1262
#ifdef UNIV_SYNC_DEBUG
1263
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1264
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1265
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
1266
#endif /* UNIV_SYNC_DEBUG */
1268
rw_lock_s_lock(&btr_search_latch);
1270
if (!btr_search_enabled) {
1271
rw_lock_s_unlock(&btr_search_latch);
1271
1275
table = btr_search_sys->hash_index;
1272
1276
page = buf_block_get_frame(block);
1274
#ifdef UNIV_SYNC_DEBUG
1275
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1276
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
1277
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
1278
#endif /* UNIV_SYNC_DEBUG */
1280
rw_lock_s_lock(&btr_search_latch);
1282
if (block->is_hashed && ((block->curr_n_fields != n_fields)
1283
|| (block->curr_n_bytes != n_bytes)
1284
|| (block->curr_left_side != left_side))) {
1278
if (block->index && ((block->curr_n_fields != n_fields)
1279
|| (block->curr_n_bytes != n_bytes)
1280
|| (block->curr_left_side != left_side))) {
1286
1282
rw_lock_s_unlock(&btr_search_latch);
1336
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1332
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
1338
1334
if (left_side) {
1360
1356
offsets = rec_get_offsets(next_rec, index, offsets,
1361
1357
n_fields + (n_bytes > 0), &heap);
1362
1358
next_fold = rec_fold(next_rec, offsets, n_fields,
1359
n_bytes, index->id);
1365
1361
if (fold != next_fold) {
1366
1362
/* Insert an entry into the hash index */
1386
1382
rw_lock_x_lock(&btr_search_latch);
1388
if (UNIV_UNLIKELY(btr_search_fully_disabled)) {
1384
if (UNIV_UNLIKELY(!btr_search_enabled)) {
1389
1385
goto exit_func;
1392
if (block->is_hashed && ((block->curr_n_fields != n_fields)
1393
|| (block->curr_n_bytes != n_bytes)
1394
|| (block->curr_left_side != left_side))) {
1388
if (block->index && ((block->curr_n_fields != n_fields)
1389
|| (block->curr_n_bytes != n_bytes)
1390
|| (block->curr_left_side != left_side))) {
1395
1391
goto exit_func;
1400
1396
rebuild hash index for a page that is already hashed, we
1401
1397
have to take care not to increment the counter in that
1403
if (!block->is_hashed) {
1399
if (!block->index) {
1404
1400
index->search_info->ref_count++;
1407
block->is_hashed = TRUE;
1408
1403
block->n_hash_helps = 0;
1410
1405
block->curr_n_fields = n_fields;
1452
1447
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1453
1448
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
1454
1449
#endif /* UNIV_SYNC_DEBUG */
1455
ut_a(!new_block->is_hashed || new_block->index == index);
1456
ut_a(!block->is_hashed || block->index == index);
1457
ut_a(!(new_block->is_hashed || block->is_hashed)
1451
rw_lock_s_lock(&btr_search_latch);
1453
ut_a(!new_block->index || new_block->index == index);
1454
ut_a(!block->index || block->index == index);
1455
ut_a(!(new_block->index || block->index)
1458
1456
|| !dict_index_is_ibuf(index));
1460
rw_lock_s_lock(&btr_search_latch);
1462
if (new_block->is_hashed) {
1458
if (new_block->index) {
1464
1460
rw_lock_s_unlock(&btr_search_latch);
1506
1502
hash_table_t* table;
1507
1503
buf_block_t* block;
1510
index_id_t index_id;
1506
dict_index_t* index;
1511
1507
ulint offsets_[REC_OFFS_NORMAL_SIZE];
1512
1508
mem_heap_t* heap = NULL;
1513
1509
rec_offs_init(offsets_);
1515
rec = btr_cur_get_rec(cursor);
1517
1511
block = btr_cur_get_block(cursor);
1519
1513
#ifdef UNIV_SYNC_DEBUG
1520
1514
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1521
1515
#endif /* UNIV_SYNC_DEBUG */
1523
if (!block->is_hashed) {
1517
index = block->index;
1528
ut_a(block->index == cursor->index);
1524
ut_a(index == cursor->index);
1529
1525
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
1530
ut_a(!dict_index_is_ibuf(cursor->index));
1526
ut_a(!dict_index_is_ibuf(index));
1532
1528
table = btr_search_sys->hash_index;
1534
index_id = cursor->index->id;
1535
fold = rec_fold(rec, rec_get_offsets(rec, cursor->index, offsets_,
1530
rec = btr_cur_get_rec(cursor);
1532
fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_,
1536
1533
ULINT_UNDEFINED, &heap),
1537
block->curr_n_fields, block->curr_n_bytes, index_id);
1534
block->curr_n_fields, block->curr_n_bytes, index->id);
1538
1535
if (UNIV_LIKELY_NULL(heap)) {
1539
1536
mem_heap_free(heap);
1541
1539
rw_lock_x_lock(&btr_search_latch);
1543
ha_search_and_delete_if_found(table, fold, rec);
1542
ut_a(block->index == index);
1544
ha_search_and_delete_if_found(table, fold, rec);
1545
1547
rw_lock_x_unlock(&btr_search_latch);
1568
1571
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1569
1572
#endif /* UNIV_SYNC_DEBUG */
1571
if (!block->is_hashed) {
1574
index = block->index;
1576
ut_a(block->index == cursor->index);
1577
ut_a(!dict_index_is_ibuf(cursor->index));
1581
ut_a(cursor->index == index);
1582
ut_a(!dict_index_is_ibuf(index));
1579
1584
rw_lock_x_lock(&btr_search_latch);
1586
if (!block->index) {
1591
ut_a(block->index == index);
1581
1593
if ((cursor->flag == BTR_CUR_HASH)
1582
1594
&& (cursor->n_fields == block->curr_n_fields)
1583
1595
&& (cursor->n_bytes == block->curr_n_bytes)
1588
1600
ha_search_and_update_if_found(table, cursor->fold, rec,
1589
1601
block, page_rec_get_next(rec));
1591
1604
rw_lock_x_unlock(&btr_search_latch);
1593
1606
rw_lock_x_unlock(&btr_search_latch);
1637
1650
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
1638
1651
#endif /* UNIV_SYNC_DEBUG */
1640
if (!block->is_hashed) {
1653
index = block->index;
1645
ut_a(block->index == cursor->index);
1646
ut_a(!dict_index_is_ibuf(cursor->index));
1648
index_id = cursor->index->id;
1660
ut_a(index == cursor->index);
1661
ut_a(!dict_index_is_ibuf(index));
1650
1663
n_fields = block->curr_n_fields;
1651
1664
n_bytes = block->curr_n_bytes;
1654
1667
ins_rec = page_rec_get_next(rec);
1655
1668
next_rec = page_rec_get_next(ins_rec);
1657
offsets = rec_get_offsets(ins_rec, cursor->index, offsets,
1670
offsets = rec_get_offsets(ins_rec, index, offsets,
1658
1671
ULINT_UNDEFINED, &heap);
1659
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index_id);
1672
ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, index->id);
1661
1674
if (!page_rec_is_supremum(next_rec)) {
1662
offsets = rec_get_offsets(next_rec, cursor->index, offsets,
1675
offsets = rec_get_offsets(next_rec, index, offsets,
1663
1676
n_fields + (n_bytes > 0), &heap);
1664
1677
next_fold = rec_fold(next_rec, offsets, n_fields,
1678
n_bytes, index->id);
1668
1681
if (!page_rec_is_infimum(rec)) {
1669
offsets = rec_get_offsets(rec, cursor->index, offsets,
1682
offsets = rec_get_offsets(rec, index, offsets,
1670
1683
n_fields + (n_bytes > 0), &heap);
1671
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
1684
fold = rec_fold(rec, offsets, n_fields, n_bytes, index->id);
1673
1686
if (left_side) {
1707
1728
rw_lock_x_lock(&btr_search_latch);
1732
if (!btr_search_enabled) {
1712
1737
ha_insert_for_fold(table, ins_fold, block, ins_rec);
1729
1758
ha_insert_for_fold(table, ins_fold, block, ins_rec);
1731
1760
fputs("Hash insert for ", stderr);
1732
dict_index_name_print(stderr, cursor->index);
1761
dict_index_name_print(stderr, index);
1733
1762
fprintf(stderr, " fold %lu\n", ins_fold);
1833
1862
ut_a(!dict_index_is_ibuf(block->index));
1835
offsets = rec_get_offsets((const rec_t*) node->data,
1864
page_index_id = btr_page_get_index_id(block->frame);
1866
offsets = rec_get_offsets(node->data,
1836
1867
block->index, offsets,
1837
1868
block->curr_n_fields
1838
1869
+ (block->curr_n_bytes > 0),
1841
page_index_id = btr_page_get_index_id(block->frame);
1844
(!block->is_hashed || node->fold
1845
!= rec_fold((rec_t*)(node->data),
1847
block->curr_n_fields,
1848
block->curr_n_bytes,
1872
if (!block->index || node->fold
1873
!= rec_fold(node->data,
1875
block->curr_n_fields,
1876
block->curr_n_bytes,
1850
1878
const page_t* page = block->frame;
1863
1891
(ullint) page_index_id,
1864
1892
(ulong) node->fold,
1865
(ulong) rec_fold((rec_t*)(node->data),
1893
(ulong) rec_fold(node->data,
1867
1895
block->curr_n_fields,
1868
1896
block->curr_n_bytes,
1869
1897
page_index_id));
1871
1899
fputs("InnoDB: Record ", stderr);
1872
rec_print_new(stderr, (rec_t*)node->data,
1900
rec_print_new(stderr, node->data, offsets);
1874
1901
fprintf(stderr, "\nInnoDB: on that page."
1875
" Page mem address %p, is hashed %lu,"
1902
" Page mem address %p, is hashed %p,"
1876
1903
" n fields %lu, n bytes %lu\n"
1877
1904
"InnoDB: side %lu\n",
1878
(void*) page, (ulong) block->is_hashed,
1905
(void*) page, (void*) block->index,
1879
1906
(ulong) block->curr_n_fields,
1880
1907
(ulong) block->curr_n_bytes,
1881
1908
(ulong) block->curr_left_side);