Browse Source

Percona-Server-5.5.34-rel32.0.tar.gz

pull/47/merge
Sergei Golubchik 12 years ago
parent
commit
667f381aa9
  1. 51
      btr/btr0cur.c
  2. 252
      btr/btr0sea.c
  3. 52
      buf/buf0buf.c
  4. 8
      dict/dict0boot.c
  5. 4
      dict/dict0dict.c
  6. 2
      dict/dict0load.c
  7. 5
      fil/fil0fil.c
  8. 160
      handler/ha_innodb.cc
  9. 8
      handler/handler0alter.cc
  10. 2
      handler/i_s.cc
  11. 5
      ibuf/ibuf0ibuf.c
  12. 49
      include/btr0sea.h
  13. 76
      include/btr0sea.ic
  14. 13
      include/btr0types.h
  15. 1
      include/buf0buf.h
  16. 4
      include/dict0mem.h
  17. 12
      include/trx0trx.h
  18. 13
      include/trx0trx.ic
  19. 12
      lock/lock0lock.c
  20. 41
      log/log0online.c
  21. 3
      log/log0recv.c
  22. 2
      que/que0que.c
  23. 19
      row/row0ins.c
  24. 19
      row/row0merge.c
  25. 28
      row/row0mysql.c
  26. 136
      row/row0sel.c
  27. 15
      row/row0uins.c
  28. 46
      row/row0umod.c
  29. 24
      row/row0upd.c
  30. 106
      srv/srv0srv.c
  31. 27
      trx/trx0trx.c

51
btr/btr0cur.c

@ -520,7 +520,8 @@ btr_cur_search_to_nth_level(
#ifdef UNIV_SEARCH_PERF_STAT
info->n_searches++;
#endif
if (rw_lock_get_writer(btr_search_get_latch(cursor->index->id)) == RW_LOCK_NOT_LOCKED
if (rw_lock_get_writer(btr_search_get_latch(cursor->index)) ==
RW_LOCK_NOT_LOCKED
&& latch_mode <= BTR_MODIFY_LEAF
&& info->last_hash_succ
&& !estimate
@ -556,7 +557,7 @@ btr_cur_search_to_nth_level(
if (has_search_latch) {
/* Release possible search latch to obey latching order */
rw_lock_s_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_s_unlock(btr_search_get_latch(cursor->index));
}
/* Store the position of the tree latch we push to mtr so that we
@ -871,7 +872,7 @@ func_exit:
if (has_search_latch) {
rw_lock_s_lock(btr_search_get_latch(cursor->index->id));
rw_lock_s_lock(btr_search_get_latch(cursor->index));
}
}
@ -1189,7 +1190,7 @@ btr_cur_ins_lock_and_undo(
rec_t* rec;
roll_ptr_t roll_ptr;
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip LOCK, UNDO */
return(DB_SUCCESS);
}
@ -1427,7 +1428,7 @@ fail_err:
goto fail_err;
}
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip CHANGE, LOG */
*big_rec = big_rec_vec;
return(err); /* == DB_SUCCESS */
@ -1641,7 +1642,7 @@ btr_cur_pessimistic_insert(
}
}
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip CHANGE, LOG */
if (n_extents > 0) {
fil_space_release_free_extents(index->space,
@ -1707,7 +1708,7 @@ btr_cur_upd_lock_and_undo(
ut_ad(cursor && update && thr && roll_ptr);
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
/* skip LOCK, UNDO */
return(DB_SUCCESS);
}
@ -1914,7 +1915,7 @@ btr_cur_update_alloc_zip(
return(FALSE);
}
if (trx && trx->fake_changes) {
if (UNIV_UNLIKELY(trx && trx->fake_changes)) {
/* Don't call page_zip_compress_write_log_no_data as that has
assert which would fail. Assume there won't be a compression
failure. */
@ -2021,7 +2022,7 @@ btr_cur_update_in_place(
return(err);
}
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
/* skip CHANGE, LOG */
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@ -2056,13 +2057,13 @@ btr_cur_update_in_place(
btr_search_update_hash_on_delete(cursor);
}
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
rw_lock_x_lock(btr_search_get_latch(cursor->index));
}
row_upd_rec_in_place(rec, index, offsets, update, page_zip);
if (is_hashed) {
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
}
if (page_zip && !dict_index_is_clust(index)
@ -2256,7 +2257,7 @@ any_extern:
goto err_exit;
}
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip CHANGE, LOG */
goto err_exit; /* == DB_SUCCESS */
}
@ -2494,7 +2495,7 @@ btr_cur_pessimistic_update(
itself. Thus the following call is safe. */
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
FALSE, *heap);
if (!(flags & BTR_KEEP_SYS_FLAG) && !trx->fake_changes) {
if (!(flags & BTR_KEEP_SYS_FLAG) && UNIV_LIKELY(!trx->fake_changes)) {
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
roll_ptr);
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
@ -2552,7 +2553,7 @@ make_external:
ut_ad(flags & BTR_KEEP_POS_FLAG);
}
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
/* skip CHANGE, LOG */
err = DB_SUCCESS;
goto return_after_reservations;
@ -2888,7 +2889,7 @@ btr_cur_del_mark_set_clust_rec(
ut_ad(dict_index_is_clust(index));
ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets)));
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip LOCK, UNDO, CHANGE, LOG */
return(DB_SUCCESS);
}
@ -3027,7 +3028,7 @@ btr_cur_del_mark_set_sec_rec(
rec_t* rec;
ulint err;
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr && thr_get_trx(thr)->fake_changes)) {
/* skip LOCK, CHANGE, LOG */
return(DB_SUCCESS);
}
@ -4785,6 +4786,10 @@ next_zip_page:
}
}
}
DBUG_EXECUTE_IF("btr_store_big_rec_extern",
error = DB_OUT_OF_FILE_SPACE;
goto func_exit;);
}
func_exit:
@ -4817,9 +4822,11 @@ func_exit:
field_ref = btr_rec_get_field_ref(rec, offsets, i);
/* The pointer must not be zero. */
/* The pointer must not be zero if the operation
succeeded. */
ut_a(0 != memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE));
BTR_EXTERN_FIELD_REF_SIZE)
|| error != DB_SUCCESS);
/* The column must not be disowned by this record. */
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
}
@ -4915,10 +4922,10 @@ btr_free_externally_stored_field(
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) {
/* In the rollback of uncommitted transactions, we may
encounter a clustered index record whose BLOBs have
not been written. There is nothing to free then. */
ut_a(rb_ctx == RB_RECOVERY || rb_ctx == RB_RECOVERY_PURGE_REC);
/* In the rollback, we may encounter a clustered index
record with some unwritten off-page columns. There is
nothing to free then. */
ut_a(rb_ctx != RB_NONE);
return;
}

252
btr/btr0sea.c

@ -69,17 +69,14 @@ hotspots from residing on the same memory
cache line as btr_search_latch */
UNIV_INTERN byte btr_sea_pad1[64];
/** The latch protecting the adaptive search system: this latch protects the
(1) positions of records on those pages where a hash index has been built.
NOTE: It does not protect values of non-ordering fields within a record from
/** Array of latches protecting individual AHI partitions. The latches
protect: (1) positions of records on those pages where a hash index from the
corresponding AHI partition has been built.
NOTE: They do not protect values of non-ordering fields within a record from
being updated in-place! We can use fact (1) to perform unique searches to
indexes. */
/* We will allocate the latch from dynamic memory to get it to the
same DRAM page as other hotspot semaphores */
//UNIV_INTERN rw_lock_t* btr_search_latch_temp;
UNIV_INTERN rw_lock_t** btr_search_latch_part;
UNIV_INTERN rw_lock_t* btr_search_latch_arr;
/** padding to prevent other memory update hotspots from residing on
the same memory cache line */
@ -133,17 +130,17 @@ static
void
btr_search_check_free_space_in_heap(
/*=====================================*/
index_id_t key)
dict_index_t* index)
{
hash_table_t* table;
mem_heap_t* heap;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
table = btr_search_get_hash_index(key);
table = btr_search_get_hash_table(index);
heap = table->heap;
@ -154,7 +151,7 @@ btr_search_check_free_space_in_heap(
if (heap->free_block == NULL) {
buf_block_t* block = buf_block_alloc(NULL);
rw_lock_x_lock(btr_search_get_latch(key));
rw_lock_x_lock(btr_search_get_latch(index));
if (heap->free_block == NULL) {
heap->free_block = block;
@ -162,7 +159,7 @@ btr_search_check_free_space_in_heap(
buf_block_free(block);
}
rw_lock_x_unlock(btr_search_get_latch(key));
rw_lock_x_unlock(btr_search_get_latch(index));
}
}
@ -194,16 +191,19 @@ btr_search_sys_create(
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
/* btr_search_index_num should be <= 32. (bits of trx->has_search_latch) */
btr_search_latch_part = mem_alloc(sizeof(rw_lock_t*) * btr_search_index_num);
btr_search_sys->hash_index = mem_alloc(sizeof(hash_table_t*) * btr_search_index_num);
/* btr_search_index_num is constrained to machine word size for
historical reasons. This limitation can be easily removed later. */
btr_search_latch_arr = mem_alloc(sizeof(rw_lock_t) *
btr_search_index_num);
btr_search_sys->hash_tables = mem_alloc(sizeof(hash_table_t *) *
btr_search_index_num);
for (i = 0; i < btr_search_index_num; i++) {
btr_search_latch_part[i] = mem_alloc(sizeof(rw_lock_t));
rw_lock_create(btr_search_latch_key,
btr_search_latch_part[i], SYNC_SEARCH_SYS);
&btr_search_latch_arr[i], SYNC_SEARCH_SYS);
btr_search_sys->hash_index[i] = ha_create(hash_size, 0, 0);
btr_search_sys->hash_tables[i] = ha_create(hash_size, 0, 0);
}
}
@ -217,15 +217,13 @@ btr_search_sys_free(void)
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
mem_heap_free(btr_search_sys->hash_index[i]->heap);
hash_table_free(btr_search_sys->hash_index[i]);
rw_lock_free(btr_search_latch_part[i]);
mem_heap_free(btr_search_sys->hash_tables[i]->heap);
hash_table_free(btr_search_sys->hash_tables[i]);
mem_free(btr_search_latch_part[i]);
rw_lock_free(&btr_search_latch_arr[i]);
}
mem_free(btr_search_sys->hash_index);
mem_free(btr_search_latch_part);
mem_free(btr_search_sys->hash_tables);
mem_free(btr_search_latch_arr);
//rw_lock_free(&btr_search_latch);
//mem_free(btr_search_latch_temp);
@ -270,8 +268,8 @@ btr_search_disable(void)
/* Clear the adaptive hash index. */
for (i = 0; i < btr_search_index_num; i++) {
hash_table_clear(btr_search_sys->hash_index[i]);
mem_heap_empty(btr_search_sys->hash_index[i]->heap);
hash_table_clear(btr_search_sys->hash_tables[i]);
mem_heap_empty(btr_search_sys->hash_tables[i]->heap);
}
btr_search_x_unlock_all();
@ -334,27 +332,27 @@ btr_search_info_create(
/*****************************************************************//**
Returns the value of ref_count. The value is protected by
btr_search_latch.
the latch of the AHI partition corresponding to this index.
@return ref_count value. */
UNIV_INTERN
ulint
btr_search_info_get_ref_count(
/*==========================*/
btr_search_t* info, /*!< in: search info. */
index_id_t key)
dict_index_t* index) /*!< in: index */
{
ulint ret;
ut_ad(info);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(key), RW_LOCK_EX));
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(btr_search_get_latch(key));
rw_lock_s_lock(btr_search_get_latch(index));
ret = info->ref_count;
rw_lock_s_unlock(btr_search_get_latch(key));
rw_lock_s_unlock(btr_search_get_latch(index));
return(ret);
}
@ -375,8 +373,8 @@ btr_search_info_update_hash(
int cmp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
index = cursor->index;
@ -494,8 +492,8 @@ btr_search_update_block_hash_info(
/*!< in: cursor */
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
ut_ad(rw_lock_own(&block->lock, RW_LOCK_SHARED)
|| rw_lock_own(&block->lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@ -579,7 +577,7 @@ btr_search_update_hash_ref(
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@ -620,11 +618,12 @@ btr_search_update_hash_ref(
mem_heap_free(heap);
}
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
ut_ad(rw_lock_own(btr_search_get_latch(cursor->index),
RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
ha_insert_for_fold(btr_search_get_hash_index(cursor->index->id), fold,
block, rec);
ha_insert_for_fold(btr_search_get_hash_table(cursor->index),
fold, block, rec);
}
}
@ -643,8 +642,8 @@ btr_search_info_update_slow(
ulint* params2;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index->id), RW_LOCK_EX));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_SHARED));
ut_ad(!rw_lock_own(btr_search_get_latch(cursor->index), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
block = btr_cur_get_block(cursor);
@ -662,7 +661,7 @@ btr_search_info_update_slow(
if (build_index || (cursor->flag == BTR_CUR_HASH_FAIL)) {
btr_search_check_free_space_in_heap(cursor->index->id);
btr_search_check_free_space_in_heap(cursor->index);
}
if (cursor->flag == BTR_CUR_HASH_FAIL) {
@ -672,11 +671,11 @@ btr_search_info_update_slow(
btr_search_n_hash_fail++;
#endif /* UNIV_SEARCH_PERF_STAT */
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
rw_lock_x_lock(btr_search_get_latch(cursor->index));
btr_search_update_hash_ref(info, block, cursor);
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
}
if (build_index) {
@ -921,17 +920,17 @@ btr_search_guess_on_hash(
cursor->flag = BTR_CUR_HASH;
if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_lock(btr_search_get_latch(index_id));
rw_lock_s_lock(btr_search_get_latch(index));
if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto failure_unlock;
}
}
ut_ad(rw_lock_get_writer(btr_search_get_latch(index_id)) != RW_LOCK_EX);
ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index_id)) > 0);
ut_ad(rw_lock_get_writer(btr_search_get_latch(index)) != RW_LOCK_EX);
ut_ad(rw_lock_get_reader_count(btr_search_get_latch(index)) > 0);
rec = ha_search_and_get_data(btr_search_get_hash_index(index_id), fold);
rec = ha_search_and_get_data(btr_search_get_hash_table(index), fold);
if (UNIV_UNLIKELY(!rec)) {
goto failure_unlock;
@ -949,7 +948,7 @@ btr_search_guess_on_hash(
goto failure_unlock;
}
rw_lock_s_unlock(btr_search_get_latch(index_id));
rw_lock_s_unlock(btr_search_get_latch(index));
buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH);
}
@ -1046,7 +1045,7 @@ btr_search_guess_on_hash(
/*-------------------------------------------*/
failure_unlock:
if (UNIV_LIKELY(!has_search_latch)) {
rw_lock_s_unlock(btr_search_get_latch(index_id));
rw_lock_s_unlock(btr_search_get_latch(index));
}
failure:
cursor->flag = BTR_CUR_HASH_FAIL;
@ -1091,48 +1090,26 @@ btr_search_drop_page_hash_index(
ulint* offsets;
retry:
if (btr_search_index_num > 1) {
rw_lock_t* btr_search_latch;
/* FIXME: This may be optimistic implementation still. */
btr_search_latch = (rw_lock_t*)(block->btr_search_latch);
if (UNIV_LIKELY(!btr_search_latch)) {
if (block->index) {
goto retry;
}
return;
}
rw_lock_s_lock(btr_search_latch);
if (UNIV_LIKELY(btr_search_latch != block->btr_search_latch)) {
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch);
goto retry;
}
index = block->index;
ut_a(btr_search_latch == btr_search_get_latch(index->id));
} else {
/* btr_search_index_num == 1 */
/* btr_search_latch is only one and able to obtain
before evaluating block->index. */
rw_lock_s_lock(btr_search_latch_part[0]);
if (UNIV_LIKELY(!block->index)) {
rw_lock_s_unlock(btr_search_latch_part[0]);
return;
}
index = block->index;
/* Do a dirty check on block->index, return if the block is not in the
adaptive hash index. This is to avoid acquiring an AHI latch for
performance considerations. */
index = block->index;
if (!index) {
return;
}
if (UNIV_LIKELY(!index)) {
rw_lock_s_lock(btr_search_get_latch(index));
rw_lock_s_unlock(btr_search_get_latch(index->id));
if (UNIV_UNLIKELY(index != block->index)) {
return;
rw_lock_s_unlock(btr_search_get_latch(index));
goto retry;
}
table = btr_search_get_hash_index(index->id);
table = btr_search_get_hash_table(index);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
@ -1149,7 +1126,7 @@ retry:
releasing btr_search_latch, as the index page might only
be s-latched! */
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
ut_a(n_fields + n_bytes > 0);
@ -1200,7 +1177,7 @@ next_rec:
mem_heap_free(heap);
}
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
if (UNIV_UNLIKELY(!block->index)) {
/* Someone else has meanwhile dropped the hash index */
@ -1216,7 +1193,7 @@ next_rec:
/* Someone else has meanwhile built a new hash index on the
page, with different parameters */
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
mem_free(folds);
goto retry;
@ -1231,7 +1208,6 @@ next_rec:
index->search_info->ref_count--;
block->index = NULL;
block->btr_search_latch = NULL;
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
@ -1244,14 +1220,14 @@ cleanup:
"InnoDB: the hash index to a page of %s,"
" still %lu hash nodes remain.\n",
index->name, (ulong) block->n_pointers);
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
ut_ad(btr_search_validate());
} else {
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
}
#else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
mem_free(folds);
@ -1283,9 +1259,9 @@ btr_search_drop_page_hash_index_on_index(
ulint* offsets;
ibool released_search_latch;
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(btr_search_get_latch(index));
table = btr_search_get_hash_index(index->id);
table = btr_search_get_hash_table(index);
for (j = 0; j < srv_buf_pool_instances; j++) {
buf_pool_t* buf_pool;
@ -1319,7 +1295,8 @@ retry:
/* keeping latch order */
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(
btr_search_get_latch(index));
released_search_latch = TRUE;
rw_lock_x_lock(&block->lock);
@ -1371,7 +1348,8 @@ next_rec:
mem_heap_empty(heap);
}
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(
btr_search_get_latch(index));
if (UNIV_UNLIKELY(!block->index)) {
goto cleanup;
@ -1381,12 +1359,14 @@ next_rec:
if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
|| UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(
btr_search_get_latch(index));
rw_lock_x_unlock(&block->lock);
mem_free(folds);
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(
btr_search_get_latch(index));
goto retry;
}
@ -1399,7 +1379,6 @@ next_rec:
index->search_info->ref_count--;
block->index = NULL;
block->btr_search_latch = NULL;
cleanup:
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
@ -1412,18 +1391,20 @@ cleanup:
index->name, (ulong) block->n_pointers);
}
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(
btr_search_get_latch(index));
rw_lock_x_unlock(&block->lock);
mem_free(folds);
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(
btr_search_get_latch(index));
}
}
} while (released_search_latch);
}
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@ -1502,7 +1483,7 @@ btr_search_build_page_hash_index(
ut_ad(index);
ut_a(!dict_index_is_ibuf(index));
table = btr_search_get_hash_index(index->id);
table = btr_search_get_hash_table(index);
page = buf_block_get_frame(block);
#ifdef UNIV_SYNC_DEBUG
@ -1511,17 +1492,17 @@ btr_search_build_page_hash_index(
|| rw_lock_own(&(block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(btr_search_get_latch(index));
if (block->index && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_left_side != left_side))) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
btr_search_drop_page_hash_index(block);
} else {
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
}
n_recs = page_get_n_recs(page);
@ -1615,9 +1596,9 @@ btr_search_build_page_hash_index(
fold = next_fold;
}
btr_search_check_free_space_in_heap(index->id);
btr_search_check_free_space_in_heap(index);
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
if (UNIV_UNLIKELY(!btr_search_enabled)) {
goto exit_func;
@ -1644,7 +1625,6 @@ btr_search_build_page_hash_index(
block->curr_n_bytes = n_bytes;
block->curr_left_side = left_side;
block->index = index;
block->btr_search_latch = btr_search_get_latch(index->id);
for (i = 0; i < n_cached; i++) {
@ -1652,7 +1632,7 @@ btr_search_build_page_hash_index(
}
exit_func:
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
mem_free(folds);
mem_free(recs);
@ -1687,7 +1667,7 @@ btr_search_move_or_delete_hash_entries(
ut_ad(rw_lock_own(&(new_block->lock), RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(btr_search_get_latch(index));
ut_a(!new_block->index || new_block->index == index);
ut_a(!block->index || block->index == index);
@ -1696,7 +1676,7 @@ btr_search_move_or_delete_hash_entries(
if (new_block->index) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
btr_search_drop_page_hash_index(block);
@ -1713,7 +1693,7 @@ btr_search_move_or_delete_hash_entries(
new_block->n_bytes = block->curr_n_bytes;
new_block->left_side = left_side;
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
ut_a(n_fields + n_bytes > 0);
@ -1725,7 +1705,7 @@ btr_search_move_or_delete_hash_entries(
return;
}
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
}
/********************************************************************//**
@ -1764,7 +1744,7 @@ btr_search_update_hash_on_delete(
ut_a(block->curr_n_fields + block->curr_n_bytes > 0);
ut_a(!dict_index_is_ibuf(index));
table = btr_search_get_hash_index(cursor->index->id);
table = btr_search_get_hash_table(cursor->index);
rec = btr_cur_get_rec(cursor);
@ -1775,7 +1755,7 @@ btr_search_update_hash_on_delete(
mem_heap_free(heap);
}
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
rw_lock_x_lock(btr_search_get_latch(cursor->index));
if (block->index) {
ut_a(block->index == index);
@ -1783,7 +1763,7 @@ btr_search_update_hash_on_delete(
ha_search_and_delete_if_found(table, fold, rec);
}
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
}
/********************************************************************//**
@ -1820,7 +1800,7 @@ btr_search_update_hash_node_on_insert(
ut_a(cursor->index == index);
ut_a(!dict_index_is_ibuf(index));
rw_lock_x_lock(btr_search_get_latch(cursor->index->id));
rw_lock_x_lock(btr_search_get_latch(cursor->index));
if (!block->index) {
@ -1834,15 +1814,15 @@ btr_search_update_hash_node_on_insert(
&& (cursor->n_bytes == block->curr_n_bytes)
&& !block->curr_left_side) {
table = btr_search_get_hash_index(cursor->index->id);
table = btr_search_get_hash_table(cursor->index);
ha_search_and_update_if_found(table, cursor->fold, rec,
block, page_rec_get_next(rec));
func_exit:
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
} else {
rw_lock_x_unlock(btr_search_get_latch(cursor->index->id));
rw_lock_x_unlock(btr_search_get_latch(cursor->index));
btr_search_update_hash_on_insert(cursor);
}
@ -1877,9 +1857,9 @@ btr_search_update_hash_on_insert(
ulint* offsets = offsets_;
rec_offs_init(offsets_);
table = btr_search_get_hash_index(cursor->index->id);
table = btr_search_get_hash_table(cursor->index);
btr_search_check_free_space_in_heap(cursor->index->id);
btr_search_check_free_space_in_heap(cursor->index);
rec = btr_cur_get_rec(cursor);
@ -1924,7 +1904,7 @@ btr_search_update_hash_on_insert(
} else {
if (left_side) {
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
locked = TRUE;
@ -1942,7 +1922,7 @@ btr_search_update_hash_on_insert(
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
locked = TRUE;
@ -1964,7 +1944,7 @@ check_next_rec:
if (!left_side) {
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
locked = TRUE;
@ -1983,7 +1963,7 @@ check_next_rec:
if (!locked) {
rw_lock_x_lock(btr_search_get_latch(index->id));
rw_lock_x_lock(btr_search_get_latch(index));
locked = TRUE;
@ -2010,7 +1990,7 @@ function_exit:
mem_heap_free(heap);
}
if (locked) {
rw_lock_x_unlock(btr_search_get_latch(index->id));
rw_lock_x_unlock(btr_search_get_latch(index));
}
}
@ -2043,7 +2023,7 @@ btr_search_validate(void)
for (j = 0; j < btr_search_index_num; j++) {
cell_count = hash_get_n_cells(btr_search_sys->hash_index[j]);
cell_count = hash_get_n_cells(btr_search_sys->hash_tables[j]);
for (i = 0; i < cell_count; i++) {
/* We release btr_search_latch every once in a while to
@ -2056,7 +2036,7 @@ btr_search_validate(void)
buf_pool_page_hash_x_lock_all();
}
node = hash_get_nth_cell(btr_search_sys->hash_index[j], i)->node;
node = hash_get_nth_cell(btr_search_sys->hash_tables[j], i)->node;
for (; node != NULL; node = node->next) {
const buf_block_t* block
@ -2171,7 +2151,7 @@ btr_search_validate(void)
buf_pool_page_hash_x_lock_all();
}
if (!ha_validate(btr_search_sys->hash_index[j], i, end_index)) {
if (!ha_validate(btr_search_sys->hash_tables[j], i, end_index)) {
ok = FALSE;
}
}

52
buf/buf0buf.c

@ -989,7 +989,6 @@ buf_block_init(
block->check_index_page_at_flush = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
#ifdef UNIV_DEBUG
block->page.in_page_hash = FALSE;
@ -1468,7 +1467,7 @@ buf_pool_clear_hash_index(void)
ulint j;
for (j = 0; j < btr_search_index_num; j++) {
ut_ad(rw_lock_own(btr_search_latch_part[j], RW_LOCK_EX));
ut_ad(rw_lock_own(&btr_search_latch_arr[j], RW_LOCK_EX));
}
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!btr_search_enabled);
@ -2147,7 +2146,6 @@ buf_block_init_low(
{
block->check_index_page_at_flush = FALSE;
block->index = NULL;
block->btr_search_latch = NULL;
block->n_hash_helps = 0;
block->n_fields = 1;
@ -2656,6 +2654,11 @@ wait_until_unfixed:
goto loop;
}
/* Buffer-fix the block so that it cannot be evicted
or relocated while we are attempting to allocate an
uncompressed page. */
bpage->buf_fix_count++;
/* Allocate an uncompressed page. */
//buf_pool_mutex_exit(buf_pool);
//mutex_exit(&buf_pool->zip_mutex);
@ -2665,47 +2668,24 @@ wait_until_unfixed:
ut_a(block);
block_mutex = &block->mutex;
//buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->LRU_list_mutex);
rw_lock_x_lock(&buf_pool->page_hash_latch);
mutex_enter(block_mutex);
{
buf_page_t* hash_bpage;
hash_bpage = buf_page_hash_get_low(
buf_pool, space, offset, fold);
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
/* The buf_pool->page_hash was modified
while buf_pool->mutex was released.
Free the block that was allocated. */
buf_LRU_block_free_non_file_page(block, TRUE);
mutex_exit(block_mutex);
block = (buf_block_t*) hash_bpage;
if (block) {
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
ut_a(block_mutex);
}
rw_lock_x_unlock(&buf_pool->page_hash_latch);
mutex_exit(&buf_pool->LRU_list_mutex);
goto loop2;
}
}
mutex_enter(&block->mutex);
mutex_enter(&buf_pool->zip_mutex);
/* Buffer-fixing prevents the page_hash from changing. */
ut_ad(bpage == buf_page_hash_get_low(buf_pool,
space, offset, fold));
if (UNIV_UNLIKELY
(bpage->buf_fix_count
(--bpage->buf_fix_count
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
mutex_exit(&buf_pool->zip_mutex);
/* The block was buffer-fixed or I/O-fixed
while buf_pool->mutex was not held by this thread.
Free the block that was allocated and try again.
This should be extremely unlikely. */
/* The block was buffer-fixed or I/O-fixed while
buf_pool->mutex was not held by this thread.
Free the block that was allocated and retry.
This should be extremely unlikely, for example,
if buf_page_get_zip() was invoked. */
buf_LRU_block_free_non_file_page(block, TRUE);
//mutex_exit(&block->mutex);

8
dict/dict0boot.c

@ -31,6 +31,7 @@ Created 4/18/1996 Heikki Tuuri
#include "dict0crea.h"
#include "btr0btr.h"
#include "btr0sea.h"
#include "dict0load.h"
#include "dict0load.h"
#include "trx0trx.h"
@ -346,6 +347,7 @@ dict_add_to_cache_xtradb_sys_stats(
dict_mem_index_add_field(index, "KEY_COLS", 0);
index->id = DICT_STATS_ID;
btr_search_index_init(index);
root_page_id = mtr_read_ulint(dict_hdr + DICT_HDR_STATS, MLOG_4BYTES,
mtr);
@ -481,6 +483,7 @@ dict_boot(void)
dict_mem_index_add_field(index, "NAME", 0);
index->id = DICT_TABLES_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
@ -495,6 +498,8 @@ dict_boot(void)
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_TABLE_IDS_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
+ DICT_HDR_TABLE_IDS,
@ -528,6 +533,7 @@ dict_boot(void)
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_COLUMNS_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
+ DICT_HDR_COLUMNS,
@ -574,6 +580,7 @@ dict_boot(void)
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_INDEXES_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
+ DICT_HDR_INDEXES,
@ -602,6 +609,7 @@ dict_boot(void)
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_FIELDS_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
mtr_read_ulint(dict_hdr
+ DICT_HDR_FIELDS,

4
dict/dict0dict.c

@ -1972,7 +1972,7 @@ dict_index_remove_from_cache(
zero. */
for (;;) {
ulint ref_count = btr_search_info_get_ref_count(info, index->id);
ulint ref_count = btr_search_info_get_ref_count(info, index);
if (ref_count == 0) {
break;
}
@ -2224,6 +2224,7 @@ dict_index_build_internal_clust(
new_index->n_user_defined_cols = index->n_fields;
new_index->id = index->id;
btr_search_index_init(new_index);
/* Copy the fields of index */
dict_index_copy(new_index, index, table, 0, index->n_fields);
@ -2394,6 +2395,7 @@ dict_index_build_internal_non_clust(
new_index->n_user_defined_cols = index->n_fields;
new_index->id = index->id;
btr_search_index_init(new_index);
/* Copy fields from index to new_index */
dict_index_copy(new_index, index, table, 0, index->n_fields);

2
dict/dict0load.c

@ -33,6 +33,7 @@ Created 4/24/1996 Heikki Tuuri
#include "btr0pcur.h"
#include "btr0btr.h"
#include "btr0sea.h"
#include "page0page.h"
#include "mach0data.h"
#include "dict0dict.h"
@ -1432,6 +1433,7 @@ err_len:
(*index)->id = id;
(*index)->page = mach_read_from_4(field);
btr_search_index_init(*index);
ut_ad((*index)->page);
return(NULL);

5
fil/fil0fil.c

@ -2266,6 +2266,11 @@ fil_op_log_parse_or_replay(
if (!space_id) {
return(ptr);
} else {
/* Only replay file ops during recovery. This is a
release-build assert to minimize any data loss risk by a
misapplied file operation. */
ut_a(recv_recovery_is_on());
}
/* Let us try to perform the file operation, if sensible. Note that

160
handler/ha_innodb.cc

@ -99,6 +99,9 @@ extern "C" {
#include "ha_prototypes.h"
#include "ut0mem.h"
#include "ibuf0ibuf.h"
enum_tx_isolation thd_get_trx_isolation(const THD* thd);
}
#include "ha_innodb.h"
@ -472,6 +475,15 @@ innobase_is_fake_change(
whom the transaction is being committed */
/******************************************************************//**
Maps a MySQL trx isolation level code to the InnoDB isolation level code
@return InnoDB isolation level */
static inline
ulint
innobase_map_isolation_level(
/*=========================*/
enum_tx_isolation iso); /*!< in: MySQL isolation level code */
static const char innobase_hton_name[]= "InnoDB";
/*************************************************************//**
@ -1097,7 +1109,7 @@ my_bool
ha_innobase::is_fake_change_enabled(THD* thd)
{
trx_t* trx = thd_to_trx(thd);
return(trx && trx->fake_changes);
return(trx && UNIV_UNLIKELY(trx->fake_changes));
}
/********************************************************************//**
@ -1124,6 +1136,8 @@ innobase_release_temporary_latches(
trx = thd_to_trx(thd);
if (trx != NULL) {
/* No-op in XtraDB */
trx_search_latch_release_if_reserved(trx);
}
@ -1166,7 +1180,7 @@ convert_error_code_to_mysql(
case DB_INTERRUPTED:
my_error(ER_QUERY_INTERRUPTED, MYF(0));
/* fall through */
return(-1);
case DB_FOREIGN_EXCEED_MAX_CASCADE:
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@ -1438,7 +1452,8 @@ innobase_convert_from_id(
}
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
Converts an identifier from my_charset_filename to UTF-8 charset.
@return result string length, as returned by strconvert() */
extern "C"
uint
innobase_convert_to_system_charset(
@ -3372,7 +3387,7 @@ innobase_is_fake_change(
whom the transaction is being committed */
{
trx_t* trx = check_trx_exists(thd);
return trx->fake_changes;
return UNIV_UNLIKELY(trx->fake_changes);
}
@ -3456,9 +3471,22 @@ innobase_start_trx_and_assign_read_view(
trx_start_if_not_started(trx);
/* Assign a read view if the transaction does not have it yet */
/* Assign a read view if the transaction does not have it yet.
Do this only if transaction is using REPEATABLE READ isolation
level. */
trx->isolation_level = innobase_map_isolation_level(
thd_get_trx_isolation(thd));
trx_assign_read_view(trx);
if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
trx_assign_read_view(trx);
} else {
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED,
"InnoDB: WITH CONSISTENT SNAPSHOT "
"was ignored because this phrase "
"can only be used with "
"REPEATABLE READ isolation level.");
}
/* Set the MySQL flag to mark that there is an active transaction */
@ -3564,9 +3592,8 @@ innobase_commit_ordered(
/* Since we will reserve the kernel mutex, we have to release
the search system latch first to obey the latching order. */
if (trx->has_search_latch) {
trx_search_latch_release_if_reserved(trx);
}
/* No-op in XtraDB */
trx_search_latch_release_if_reserved(trx);
if (!trx_is_registered_for_2pc(trx) && trx_is_started(trx)) {
/* We cannot throw error here; instead we will catch this error
@ -3612,11 +3639,13 @@ innobase_commit(
/* Since we will reserve the kernel mutex, we have to release
the search system latch first to obey the latching order. */
if (trx->has_search_latch) {
trx_search_latch_release_if_reserved(trx);
}
/* No-op in XtraDB */
trx_search_latch_release_if_reserved(trx);
if (UNIV_UNLIKELY(trx->fake_changes
&& (all || (!thd_test_options(thd,
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))))) {
if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
innobase_rollback(hton, thd, all); /* rollback implicitly */
thd->stmt_da->reset_diagnostics_area(); /* because debug assertion code complains, if something left */
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
@ -8195,7 +8224,7 @@ ha_innobase::create(
trx = innobase_trx_allocate(thd);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
innobase_commit_low(trx);
trx_free_for_mysql(trx);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
@ -8422,7 +8451,7 @@ ha_innobase::truncate(void)
DBUG_RETURN(HA_ERR_CRASHED);
}
if (prebuilt->trx->fake_changes) {
if (UNIV_UNLIKELY(prebuilt->trx->fake_changes)) {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@ -8487,7 +8516,7 @@ ha_innobase::delete_table(
trx = innobase_trx_allocate(thd);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
innobase_commit_low(trx);
trx_free_for_mysql(trx);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
@ -8579,13 +8608,13 @@ innobase_drop_database(
trx->mysql_thd = NULL;
#else
trx = innobase_trx_allocate(thd);
if (trx->fake_changes) {
#endif
if (UNIV_UNLIKELY(trx->fake_changes)) {
my_free(namebuf);
innobase_commit_low(trx);
trx_free_for_mysql(trx);
return; /* ignore */
}
#endif
row_drop_database_for_mysql(namebuf, trx);
my_free(namebuf);
@ -8698,7 +8727,7 @@ ha_innobase::rename_table(
trx_search_latch_release_if_reserved(parent_trx);
trx = innobase_trx_allocate(thd);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
innobase_commit_low(trx);
trx_free_for_mysql(trx);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
@ -12560,6 +12589,63 @@ innobase_thd_get_thread_id(
return(thd_get_thread_id((const THD*) thd));
}
#ifdef UNIV_DEBUG
static my_bool innodb_log_checkpoint_now = TRUE;
/****************************************************************//**
Force innodb to checkpoint. */
static
void
checkpoint_now_set(
/*===============*/
THD* thd /*!< in: thread handle */
__attribute__((unused)),
struct st_mysql_sys_var* var /*!< in: pointer to system
variable */
__attribute__((unused)),
void* var_ptr /*!< out: where the formal
string goes */
__attribute__((unused)),
const void* save) /*!< in: immediate result from
check function */
{
if (*(my_bool*) save) {
while (log_sys->last_checkpoint_lsn < log_sys->lsn) {
log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
fil_flush_file_spaces(FIL_LOG);
}
fil_write_flushed_lsn_to_data_files(log_sys->lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE);
}
}
static my_bool innodb_track_redo_log_now = TRUE;
/****************************************************************//**
Force log tracker to track the log synchronously. */
static
void
track_redo_log_now_set(
/*===================*/
THD* thd /*!< in: thread handle */
__attribute__((unused)),
struct st_mysql_sys_var* var /*!< in: pointer to system
variable */
__attribute__((unused)),
void* var_ptr /*!< out: where the formal
string goes */
__attribute__((unused)),
const void* save) /*!< in: immediate result from
check function */
{
if (*(my_bool*) save && srv_track_changed_pages) {
log_online_follow_redo_log();
}
}
#endif /* UNIV_DEBUG */
static SHOW_VAR innodb_status_variables_export[]= {
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
@ -12820,6 +12906,8 @@ static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
"Disable with --skip-innodb-adaptive-hash-index.",
NULL, innodb_adaptive_hash_index_update, TRUE);
/* btr_search_index_num is constrained to machine word size for historical
reasons. This limitation can be easily removed later. */
static MYSQL_SYSVAR_ULONG(adaptive_hash_index_partitions, btr_search_index_num,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of InnoDB adaptive hash index partitions (default 1: disable partitioning)",
@ -13027,9 +13115,15 @@ static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
static MYSQL_SYSVAR_BOOL(track_changed_pages, srv_track_changed_pages,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Track the redo log for changed pages and output a changed page bitmap",
NULL, NULL, FALSE);
PLUGIN_VAR_NOCMDARG
#ifndef UNIV_DEBUG
/* Make this variable dynamic for debug builds to
provide a testcase sync facility */
| PLUGIN_VAR_READONLY
#endif
,
"Track the redo log for changed pages and output a changed page bitmap",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_ULONGLONG(max_bitmap_file_size, srv_max_bitmap_file_size,
PLUGIN_VAR_RQCMDARG,
@ -13249,6 +13343,21 @@ static MYSQL_SYSVAR_ULONG(lazy_drop_table, srv_lazy_drop_table,
"[Deprecated option] no effect",
NULL, NULL, 0, 0, 1, 0);
#ifdef UNIV_DEBUG
static MYSQL_SYSVAR_BOOL(log_checkpoint_now, innodb_log_checkpoint_now,
PLUGIN_VAR_OPCMDARG,
"Force checkpoint now",
NULL, checkpoint_now_set, FALSE);
static MYSQL_SYSVAR_BOOL(track_redo_log_now,
innodb_track_redo_log_now,
PLUGIN_VAR_OPCMDARG,
"Force log tracker to catch up with checkpoint now",
NULL, track_redo_log_now_set, FALSE);
#endif /* UNIV_DEBUG */
static MYSQL_SYSVAR_BOOL(locking_fake_changes, srv_fake_changes_locks,
PLUGIN_VAR_NOCMDARG,
"###EXPERIMENTAL### if enabled, transactions will get S row locks instead "
@ -13380,6 +13489,10 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(locking_fake_changes),
MYSQL_SYSVAR(merge_sort_block_size),
MYSQL_SYSVAR(print_all_deadlocks),
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(log_checkpoint_now),
MYSQL_SYSVAR(track_redo_log_now),
#endif /* UNIV_DEBUG */
NULL
};
@ -13568,7 +13681,8 @@ test_innobase_convert_name()
#endif /* UNIV_COMPILE_TEST_FUNCS */
/**********************************************************************
Converts an identifier from my_charset_filename to UTF-8 charset. */
Converts an identifier from my_charset_filename to UTF-8 charset.
@return result string length, as returned by strconvert() */
extern "C"
uint
innobase_convert_to_filename_charset(

8
handler/handler0alter.cc

@ -697,7 +697,7 @@ ha_innobase::add_index(
possible adaptive hash latch to avoid deadlocks of threads. */
trx_search_latch_release_if_reserved(prebuilt->trx);
if (prebuilt->trx->fake_changes) {
if (UNIV_UNLIKELY(prebuilt->trx->fake_changes)) {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@ -743,7 +743,7 @@ ha_innobase::add_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = innobase_trx_allocate(user_thd);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
mem_heap_free(heap);
trx_general_rollback_for_mysql(trx, NULL);
trx_free_for_mysql(trx);
@ -1117,7 +1117,7 @@ ha_innobase::prepare_drop_index(
trx_search_latch_release_if_reserved(prebuilt->trx);
trx = prebuilt->trx;
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@ -1329,7 +1329,7 @@ ha_innobase::final_drop_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = innobase_trx_allocate(user_thd);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
trx_general_rollback_for_mysql(trx, NULL);
trx_free_for_mysql(trx);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);

2
handler/i_s.cc

@ -7509,6 +7509,7 @@ i_s_innodb_changed_pages_fill(
}
if (!log_online_bitmap_iterator_init(&i, min_lsn, max_lsn)) {
my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0));
DBUG_RETURN(1);
}
@ -7572,6 +7573,7 @@ i_s_innodb_changed_pages_fill(
if (schema_table_store_record(thd, table))
{
log_online_bitmap_iterator_release(&i);
my_error(ER_CANT_FIND_SYSTEM_REC, MYF(0));
DBUG_RETURN(1);
}

5
ibuf/ibuf0ibuf.c

@ -48,6 +48,7 @@ Created 7/19/1997 Heikki Tuuri
#include "btr0cur.h"
#include "btr0pcur.h"
#include "btr0btr.h"
#include "btr0sea.h"
#include "row0upd.h"
#include "sync0sync.h"
#include "dict0boot.h"
@ -631,6 +632,7 @@ ibuf_init_at_db_start(void)
dict_mem_index_add_field(index, "DUMMY_COLUMN", 0);
index->id = DICT_IBUF_ID_MIN + IBUF_SPACE_ID;
btr_search_index_init(index);
error = dict_index_add_to_cache(table, index,
FSP_IBUF_TREE_ROOT_PAGE_NO, FALSE);
@ -4421,7 +4423,6 @@ ibuf_delete_rec(
BTR_MODIFY_TREE, pcur, mtr)) {
mutex_exit(&ibuf_mutex);
ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
goto func_exit;
}
@ -4442,7 +4443,6 @@ ibuf_delete_rec(
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
func_exit:
ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
btr_pcur_close(pcur);
@ -4779,7 +4779,6 @@ loop:
BTR_MODIFY_LEAF,
&pcur, &mtr)) {
ut_ad(!ibuf_inside(&mtr));
ut_ad(mtr.state == MTR_COMMITTED);
mops[op]++;
ibuf_dummy_index_free(dummy_index);

49
include/btr0sea.h

@ -79,14 +79,14 @@ btr_search_info_create(
mem_heap_t* heap); /*!< in: heap where created */
/*****************************************************************//**
Returns the value of ref_count. The value is protected by
btr_search_latch.
the latch of the AHI partition corresponding to this index.
@return ref_count value. */
UNIV_INTERN
ulint
btr_search_info_get_ref_count(
/*==========================*/
btr_search_t* info, /*!< in: search info. */
index_id_t key);
dict_index_t* index); /*!< in: index */
/*********************************************************************//**
Updates the search info. */
UNIV_INLINE
@ -204,36 +204,57 @@ btr_search_validate(void);
New functions to control split btr_search_index */
UNIV_INLINE
hash_table_t*
btr_search_get_hash_index(
btr_search_get_hash_table(
/*======================*/
index_id_t key);
const dict_index_t* index) /*!< in: index */
__attribute__((nonnull,pure,warn_unused_result));
UNIV_INLINE
rw_lock_t*
btr_search_get_latch(
/*=================*/
index_id_t key);
const dict_index_t* index) /*!< in: index */
__attribute__((nonnull,pure,warn_unused_result));
/*********************************************************************//**
Returns the AHI partition number corresponding to a given index ID. */
UNIV_INLINE
void
btr_search_x_lock_all(void);
/*========================*/
ulint
btr_search_get_key(
/*===============*/
index_id_t index_id) /*!< in: index ID */
__attribute__((pure,warn_unused_result));
/*********************************************************************//**
Initializes AHI-related fields in a newly created index. */
UNIV_INLINE
void
btr_search_x_unlock_all(void);
/*==========================*/
btr_search_index_init(
/*===============*/
dict_index_t* index) /*!< in: index */
__attribute__((nonnull));
UNIV_INLINE
void
btr_search_s_lock_all(void);
btr_search_x_lock_all(void);
/*========================*/
UNIV_INLINE
void
btr_search_s_unlock_all(void);
btr_search_x_unlock_all(void);
/*==========================*/
#ifdef UNIV_SYNC_DEBUG
/********************************************************************//**
Checks if the thread owns any adaptive hash latches in either S or X mode.
@return TRUE if the thread owns at least one latch in any mode. */
UNIV_INLINE
ibool
btr_search_own_any(void)
/*=====================*/
__attribute__((warn_unused_result));
#endif
/** The search info struct in an index */
struct btr_search_struct{
ulint ref_count; /*!< Number of blocks in this index tree
@ -294,8 +315,8 @@ typedef struct btr_search_sys_struct btr_search_sys_t;
/** The hash index system */
struct btr_search_sys_struct{
hash_table_t** hash_index; /*!< the adaptive hash index,
mapping dtuple_fold values
hash_table_t** hash_tables; /*!< the array of adaptive hash index,
tables mapping dtuple_fold values
to rec_t pointers on index pages */
};

76
include/btr0sea.ic

@ -87,67 +87,99 @@ btr_search_info_update(
New functions to control split btr_search_index */
UNIV_INLINE
hash_table_t*
btr_search_get_hash_index(
btr_search_get_hash_table(
/*======================*/
index_id_t key)
const dict_index_t* index) /*!< in: index */
{
return(btr_search_sys->hash_index[key % btr_search_index_num]);
ut_ad(index);
ut_ad(index->search_table);
return(index->search_table);
}
UNIV_INLINE
rw_lock_t*
btr_search_get_latch(
/*=================*/
index_id_t key)
const dict_index_t* index) /*!< in: index */
{
return(btr_search_latch_part[key % btr_search_index_num]);
ut_ad(index);
ut_ad(index->search_latch >= btr_search_latch_arr &&
index->search_latch < btr_search_latch_arr +
btr_search_index_num);
return(index->search_latch);
}
/*********************************************************************//**
Returns the AHI partition number corresponding to a given index ID. */
UNIV_INLINE
ulint
btr_search_get_key(
/*===============*/
index_id_t index_id) /*!< in: index ID */
{
return(index_id % btr_search_index_num);
}
/*********************************************************************//**
Initializes AHI-related fields in a newly created index. */
UNIV_INLINE
void
btr_search_x_lock_all(void)
/*=======================*/
btr_search_index_init(
/*===============*/
dict_index_t* index) /*!< in: index */
{
ulint i;
ut_ad(index);
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_x_lock(btr_search_latch_part[i]);
}
index->search_latch =
&btr_search_latch_arr[btr_search_get_key(index->id)];
index->search_table =
btr_search_sys->hash_tables[btr_search_get_key(index->id)];
}
UNIV_INLINE
void
btr_search_x_unlock_all(void)
/*==========================*/
btr_search_x_lock_all(void)
/*=======================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_x_unlock(btr_search_latch_part[i]);
rw_lock_x_lock(&btr_search_latch_arr[i]);
}
}
UNIV_INLINE
void
btr_search_s_lock_all(void)
/*=======================*/
btr_search_x_unlock_all(void)
/*==========================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_s_lock(btr_search_latch_part[i]);
rw_lock_x_unlock(&btr_search_latch_arr[i]);
}
}
#ifdef UNIV_SYNC_DEBUG
/********************************************************************//**
Checks if the thread owns any adaptive hash latches in either S or X mode.
@return TRUE if the thread owns at least one latch in any mode. */
UNIV_INLINE
void
btr_search_s_unlock_all(void)
/*=========================*/
ibool
btr_search_own_any(void)
/*====================*/
{
ulint i;
for (i = 0; i < btr_search_index_num; i++) {
rw_lock_s_unlock(btr_search_latch_part[i]);
if (rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_SHARED) ||
rw_lock_own(&btr_search_latch_arr[i], RW_LOCK_EX)) {
return(TRUE);
}
}
}
return(FALSE);
}
#endif

13
include/btr0types.h

@ -41,22 +41,21 @@ typedef struct btr_search_struct btr_search_t;
#ifndef UNIV_HOTBACKUP
/** @brief The latch protecting the adaptive search system
/** @brief The array of latches protecting the adaptive search partitions
This latch protects the
(1) hash index;
These latches protect the
(1) hash index from the corresponding AHI partition;
(2) columns of a record to which we have a pointer in the hash index;
but does NOT protect:
but do NOT protect:
(3) next record offset field in a record;
(4) next or previous records on the same page.
Bear in mind (3) and (4) when using the hash index.
Bear in mind (3) and (4) when using the hash indexes.
*/
//extern rw_lock_t* btr_search_latch_temp;
extern rw_lock_t** btr_search_latch_part;
extern rw_lock_t* btr_search_latch_arr;
#endif /* UNIV_HOTBACKUP */

1
include/buf0buf.h

@ -1714,7 +1714,6 @@ struct buf_block_struct{
complete, though: there may
have been hash collisions,
record deletions, etc. */
volatile rw_lock_t* btr_search_latch;
/* @} */
# ifdef UNIV_SYNC_DEBUG
/** @name Debug fields */

4
include/dict0mem.h

@ -365,6 +365,10 @@ struct dict_field_struct{
initialized to 0, NULL or FALSE in dict_mem_index_create(). */
struct dict_index_struct{
index_id_t id; /*!< id of the index */
rw_lock_t* search_latch; /*!< latch protecting the AHI partition
corresponding to this index */
hash_table_t* search_table; /*!< hash table protected by
search_latch */
mem_heap_t* heap; /*!< memory heap */
const char* name; /*!< index name */
const char* table_name;/*!< table name */

12
include/trx0trx.h

@ -49,12 +49,14 @@ the kernel mutex */
extern ulint trx_n_prepared;
/********************************************************************//**
Releases the search latch if trx has reserved it. */
UNIV_INTERN
In XtraDB it is impossible for a transaction to own a search latch outside of
InnoDB code, so there is nothing to release on demand. We keep this function to
simplify maintenance.*/
UNIV_INLINE
void
trx_search_latch_release_if_reserved(
/*=================================*/
trx_t* trx); /*!< in: transaction */
trx_t* trx __attribute__((unused))); /*!< in: transaction */
/******************************************************************//**
Set detailed error message for the transaction. */
UNIV_INTERN
@ -555,8 +557,8 @@ struct trx_struct{
in that case we must flush the log
in trx_commit_complete_for_mysql() */
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
ulint has_search_latch;
/* TRUE if this trx has latched the
ibool has_search_latch;
/* TRUE if this trx has latched any
search system latch in S-mode */
ulint deadlock_mark; /*!< a mark field used in deadlock
checking algorithm. */

13
include/trx0trx.ic

@ -23,6 +23,19 @@ The transaction
Created 3/26/1996 Heikki Tuuri
*******************************************************/
/********************************************************************//**
In XtraDB it is impossible for a transaction to own a search latch outside of
InnoDB code, so there is nothing to release on demand. We keep this function to
simplify maintenance.*/
UNIV_INLINE
void
trx_search_latch_release_if_reserved(
/*=================================*/
trx_t* trx __attribute__((unused))) /*!< in: transaction */
{
ut_ad(!trx->has_search_latch);
}
/*************************************************************//**
Starts the transaction if it is not yet started. */
UNIV_INLINE

12
lock/lock0lock.c

@ -4019,7 +4019,7 @@ lock_table(
trx = thr_get_trx(thr);
if (trx->fake_changes && mode == LOCK_IX) {
if (UNIV_UNLIKELY(trx->fake_changes && mode == LOCK_IX)) {
mode = LOCK_IS;
}
@ -5268,7 +5268,7 @@ lock_rec_insert_check_and_lock(
trx = thr_get_trx(thr);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
return(DB_SUCCESS);
}
@ -5453,7 +5453,7 @@ lock_clust_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
return(DB_SUCCESS);
}
@ -5515,7 +5515,7 @@ lock_sec_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
if (thr && thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
return(DB_SUCCESS);
}
@ -5606,7 +5606,7 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
if (!srv_fake_changes_locks) {
return(DB_SUCCESS);
}
@ -5691,7 +5691,7 @@ lock_clust_rec_read_check_and_lock(
return(DB_SUCCESS);
}
if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
if (!srv_fake_changes_locks) {
return(DB_SUCCESS);
}

41
log/log0online.c

@ -34,6 +34,14 @@ Online database log parsing for changed page tracking
#include "trx0sys.h"
#include "ut0rbt.h"
#ifdef __WIN__
/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
# define DEBUG_SYNC_C(dummy) ((void) 0)
#else
# include "m_string.h" /* for my_sys.h */
# include "my_sys.h" /* DEBUG_SYNC_C */
#endif
enum { FOLLOW_SCAN_SIZE = 4 * (UNIV_PAGE_SIZE_MAX) };
#ifdef UNIV_PFS_MUTEX
@ -1254,6 +1262,24 @@ log_online_follow_redo_log(void)
return result;
}
/*********************************************************************//**
Diagnose a bitmap file range setup failure and free the partially-initialized
bitmap file range. */
static
void
log_online_diagnose_inconsistent_dir(
/*=================================*/
log_online_bitmap_file_range_t *bitmap_files) /*!<in/out: bitmap file
range */
{
fprintf(stderr,
"InnoDB: Warning: inconsistent bitmap file "
"directory for a "
"INFORMATION_SCHEMA.INNODB_CHANGED_PAGES query"
"\n");
free(bitmap_files->files);
}
/*********************************************************************//**
List the bitmap files in srv_data_home and setup their range that contains the
specified LSN interval. This range, if non-empty, will start with a file that
@ -1355,6 +1381,8 @@ log_online_setup_bitmap_file_range(
bitmap_files->count = last_file_seq_num - first_file_seq_num + 1;
DEBUG_SYNC_C("setup_bitmap_range_middle");
/* 2nd pass: get the file names in the file_seq_num order */
bitmap_dir = os_file_opendir(srv_data_home, FALSE);
@ -1390,12 +1418,7 @@ log_online_setup_bitmap_file_range(
array_pos = file_seq_num - first_file_seq_num;
if (UNIV_UNLIKELY(array_pos >= bitmap_files->count)) {
fprintf(stderr,
"InnoDB: Error: inconsistent bitmap file "
"directory for a "
"INFORMATION_SCHEMA.INNODB_CHANGED_PAGES query"
"\n");
free(bitmap_files->files);
log_online_diagnose_inconsistent_dir(bitmap_files);
return FALSE;
}
@ -1422,8 +1445,12 @@ log_online_setup_bitmap_file_range(
}
#ifdef UNIV_DEBUG
if (!bitmap_files->files[0].seq_num) {
log_online_diagnose_inconsistent_dir(bitmap_files);
return FALSE;
}
ut_ad(bitmap_files->files[0].seq_num == first_file_seq_num);
ut_ad(bitmap_files->files[0].start_lsn == first_file_start_lsn);
{
size_t i;
for (i = 1; i < bitmap_files->count; i++) {

3
log/log0recv.c

@ -1266,7 +1266,8 @@ recv_parse_or_apply_log_rec_body(
break;
case MLOG_FILE_RENAME:
ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type,
space_id, 0);
(recv_recovery_is_on()
? space_id : 0), 0);
break;
case MLOG_FILE_CREATE:
case MLOG_FILE_DELETE:

2
que/que0que.c

@ -1417,7 +1417,7 @@ que_eval_sql(
ut_a(trx->error_state == DB_SUCCESS);
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
/* fake_changes should not access to system tables */
fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n");
return(DB_ERROR);

19
row/row0ins.c

@ -1512,7 +1512,7 @@ exit_func:
mem_heap_free(heap);
}
if (trx->fake_changes) {
if (UNIV_UNLIKELY(trx->fake_changes)) {
err = DB_SUCCESS;
}
@ -2093,11 +2093,11 @@ row_ins_index_entry_low(
transaction. Let us now reposition the cursor and
continue the insertion. */
btr_cur_search_to_nth_level(index, 0, entry,
PAGE_CUR_LE,
thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT),
&cursor, 0,
__FILE__, __LINE__, &mtr);
btr_cur_search_to_nth_level(
index, 0, entry, PAGE_CUR_LE,
(UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)
? BTR_SEARCH_LEAF : (mode | BTR_INSERT)),
&cursor, 0, __FILE__, __LINE__, &mtr);
}
}
@ -2122,6 +2122,11 @@ row_ins_index_entry_low(
if (big_rec) {
ut_a(err == DB_SUCCESS);
if (UNIV_UNLIKELY(thr_get_trx(thr)->
fake_changes)) {
goto stored_big_rec;
}
/* Write out the externally stored
columns while still x-latching
index->lock and block->lock. Allocate
@ -2215,7 +2220,7 @@ function_exit:
rec_t* rec;
ulint* offsets;
if (thr_get_trx(thr)->fake_changes) {
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
/* skip store extern */
if (modify) {
dtuple_big_rec_free(big_rec);

19
row/row0merge.c

@ -63,6 +63,14 @@ Completed by Sunny Bains and Marko Makela
# define posix_fadvise(fd, offset, len, advice) /* nothing */
#endif /* __WIN__ */
#ifdef __WIN__
/* error LNK2001: unresolved external symbol _debug_sync_C_callback_ptr */
# define DEBUG_SYNC_C(dummy) ((void) 0)
#else
# include "m_string.h" /* for my_sys.h */
# include "my_sys.h" /* DEBUG_SYNC_C */
#endif
#ifdef UNIV_DEBUG
/** Set these in order ot enable debug printout. */
/* @{ */
@ -2593,8 +2601,15 @@ row_merge_rename_tables(
/* The following calls will also rename the .ibd data files if
the tables are stored in a single-table tablespace */
if (!dict_table_rename_in_cache(old_table, tmp_name, FALSE)
|| !dict_table_rename_in_cache(new_table, old_name, FALSE)) {
if (!dict_table_rename_in_cache(old_table, tmp_name, FALSE)) {
err = DB_ERROR;
goto err_exit;
}
DEBUG_SYNC_C("row_merge_rename_tables_between_renames");
if (!dict_table_rename_in_cache(new_table, old_name, FALSE)) {
err = DB_ERROR;
goto err_exit;

28
row/row0mysql.c

@ -2664,7 +2664,9 @@ row_discard_tablespace_for_mysql(
/* check adaptive hash entries */
index = dict_table_get_first_index(table);
while (index) {
ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
ulint ref_count =
btr_search_info_get_ref_count(
index->search_info, index);
if (ref_count) {
fprintf(stderr, "InnoDB: Warning:"
" hash index ref_count (%lu) is not zero"
@ -3025,7 +3027,9 @@ row_truncate_table_for_mysql(
table->space = space;
index = dict_table_get_first_index(table);
do {
ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id);
ulint ref_count =
btr_search_info_get_ref_count(
index->search_info, index);
/* check adaptive hash entries */
if (ref_count) {
fprintf(stderr, "InnoDB: Warning:"
@ -4093,12 +4097,28 @@ row_rename_table_for_mysql(
} else if (!new_is_tmp) {
/* Rename all constraints. */
char new_table_name[MAX_TABLE_NAME_LEN] = "";
char old_table_utf8[MAX_TABLE_NAME_LEN] = "";
uint errors = 0;
strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
innobase_convert_to_system_charset(
strchr(old_table_utf8, '/') + 1,
strchr(old_name, '/') +1,
MAX_TABLE_NAME_LEN, &errors);
if (errors) {
/* Table name could not be converted from charset
my_charset_filename to UTF-8. This means that the
table name is already in UTF-8 (#mysql#50). */
strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
}
info = pars_info_create();
pars_info_add_str_literal(info, "new_table_name", new_name);
pars_info_add_str_literal(info, "old_table_name", old_name);
pars_info_add_str_literal(info, "old_table_name_utf8",
old_table_utf8);
strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
innobase_convert_to_system_charset(
@ -4135,6 +4155,8 @@ row_rename_table_for_mysql(
"new_db_name := SUBSTR(:new_table_name, 0,\n"
" new_db_name_len);\n"
"old_t_name_len := LENGTH(:old_table_name);\n"
"gen_constr_prefix := CONCAT(:old_table_name_utf8,\n"
" '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
@ -4151,7 +4173,7 @@ row_rename_table_for_mysql(
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
" '_ibfk_') > 0)\n"
" gen_constr_prefix) > 0)\n"
" THEN\n"
" offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
" new_foreign_id :=\n"

136
row/row0sel.c

@ -217,7 +217,8 @@ row_sel_sec_rec_is_for_clust_rec(
len = clust_len;
if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL) {
if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL
&& sec_len != UNIV_SQL_NULL) {
if (rec_offs_nth_extern(clust_offs, clust_pos)) {
len -= BTR_EXTERN_FIELD_REF_SIZE;
@ -1224,7 +1225,7 @@ row_sel_try_search_shortcut(
ut_ad(plan->unique_search);
ut_ad(!plan->must_get_clust);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_SHARED));
ut_ad(rw_lock_own(btr_search_get_latch(index), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
row_sel_open_pcur(plan, TRUE, mtr);
@ -1395,10 +1396,11 @@ table_loop:
&& !plan->must_get_clust
&& !plan->table->big_rows) {
if (!search_latch_locked) {
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_lock(btr_search_get_latch(index));
search_latch_locked = TRUE;
} else if (rw_lock_get_writer(btr_search_get_latch(index->id)) == RW_LOCK_WAIT_EX) {
} else if (rw_lock_get_writer(btr_search_get_latch(index))
== RW_LOCK_WAIT_EX) {
/* There is an x-latch request waiting: release the
s-latch for a moment; as an s-latch here is often
@ -1407,8 +1409,8 @@ table_loop:
from acquiring an s-latch for a long time, lowering
performance significantly in multiprocessors. */
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_lock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
rw_lock_s_lock(btr_search_get_latch(index));
}
found_flag = row_sel_try_search_shortcut(node, plan, &mtr);
@ -1431,7 +1433,7 @@ table_loop:
}
if (search_latch_locked) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
search_latch_locked = FALSE;
}
@ -2007,7 +2009,7 @@ lock_wait_or_error:
func_exit:
if (search_latch_locked) {
rw_lock_s_unlock(btr_search_get_latch(index->id));
rw_lock_s_unlock(btr_search_get_latch(index));
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@ -2744,6 +2746,9 @@ row_sel_store_mysql_rec(
heap */
ut_a(!prebuilt->trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
#endif
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
if (prebuilt->blob_heap == NULL) {
@ -3320,6 +3325,8 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(!prebuilt->templ_contains_blob);
#ifndef UNIV_SEARCH_DEBUG
ut_ad(trx->has_search_latch);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur,
RW_S_LATCH,
@ -3420,8 +3427,6 @@ row_search_for_mysql(
/* if the returned record was locked and we did a semi-consistent
read (fetch the newest committed version), then this is set to
TRUE */
ulint i;
ulint should_release;
#ifdef UNIV_SEARCH_DEBUG
ulint cnt = 0;
#endif /* UNIV_SEARCH_DEBUG */
@ -3438,6 +3443,12 @@ row_search_for_mysql(
ut_ad(index && pcur && search_tuple);
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
if (UNIV_UNLIKELY(prebuilt->table->ibd_file_missing)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error:\n"
@ -3453,24 +3464,15 @@ row_search_for_mysql(
"InnoDB: how you can resolve the problem.\n",
prebuilt->table->name);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_ERROR);
}
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_MISSING_HISTORY);
}
if (dict_index_is_corrupted(index)) {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_CORRUPTION);
}
@ -3515,38 +3517,6 @@ row_search_for_mysql(
fprintf(stderr, "N tables locked %lu\n",
(ulong) trx->mysql_n_tables_locked);
#endif
/*-------------------------------------------------------------*/
/* PHASE 0: Release a possible s-latch we are holding on the
adaptive hash index latch if there is someone waiting behind */
should_release = 0;
for (i = 0; i < btr_search_index_num; i++) {
/* we should check all latches (fix Bug#791030) */
if (UNIV_UNLIKELY(rw_lock_get_writer(btr_search_latch_part[i])
!= RW_LOCK_NOT_LOCKED)) {
should_release |= ((ulint)1 << i);
}
}
if (UNIV_UNLIKELY(should_release)) {
/* There is an x-latch request on the adaptive hash index:
release the s-latch to reduce starvation and wait for
BTR_SEA_TIMEOUT rounds before trying to keep it again over
calls from MySQL */
for (i = 0; i < btr_search_index_num; i++) {
/* we should release all s-latches (fix Bug#791030) */
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_unlock(btr_search_latch_part[i]);
trx->has_search_latch &= (~((ulint)1 << i));
}
}
if (!trx->has_search_latch) {
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
}
}
/* Reset the new record lock info if srv_locks_unsafe_for_binlog
is set or session is using a READ COMMITED isolation level. Then
@ -3696,29 +3666,9 @@ row_search_for_mysql(
hash index semaphore! */
#ifndef UNIV_SEARCH_DEBUG
if (!(trx->has_search_latch
& ((ulint)1 << (index->id % btr_search_index_num)))) {
if (trx->has_search_latch
< ((ulint)1 << (index->id % btr_search_index_num))) {
rw_lock_s_lock(btr_search_get_latch(index->id));
trx->has_search_latch |=
((ulint)1 << (index->id % btr_search_index_num));
} else {
/* should re-lock to obay latch-order */
for (i = 0; i < btr_search_index_num; i++) {
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_unlock(btr_search_latch_part[i]);
}
}
trx->has_search_latch |=
((ulint)1 << (index->id % btr_search_index_num));
for (i = 0; i < btr_search_index_num; i++) {
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_lock(btr_search_latch_part[i]);
}
}
}
}
ut_ad(!trx->has_search_latch);
rw_lock_s_lock(btr_search_get_latch(index));
trx->has_search_latch = TRUE;
#endif
switch (row_sel_try_search_shortcut_for_mysql(
&rec, prebuilt, &offsets, &heap,
@ -3763,7 +3713,7 @@ row_search_for_mysql(
srv_n_rows_read++;
err = DB_SUCCESS;
goto release_search_latch_if_needed;
goto release_search_latch;
case SEL_EXHAUSTED:
mtr_commit(&mtr);
@ -3772,19 +3722,10 @@ row_search_for_mysql(
fputs(" record not found 2\n", stderr); */
err = DB_RECORD_NOT_FOUND;
release_search_latch_if_needed:
if (trx->search_latch_timeout > 0
&& trx->has_search_latch) {
trx->search_latch_timeout--;
for (i = 0; i < btr_search_index_num; i++) {
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_unlock(btr_search_latch_part[i]);
}
}
trx->has_search_latch = FALSE;
}
release_search_latch:
rw_lock_s_unlock(
btr_search_get_latch(index));
trx->has_search_latch = FALSE;
/* NOTE that we do NOT store the cursor
position */
@ -3799,22 +3740,19 @@ release_search_latch_if_needed:
mtr_commit(&mtr);
mtr_start(&mtr);
rw_lock_s_unlock(btr_search_get_latch(index));
trx->has_search_latch = FALSE;
}
}
/*-------------------------------------------------------------*/
/* PHASE 3: Open or restore index cursor position */
if (trx->has_search_latch) {
for (i = 0; i < btr_search_index_num; i++) {
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_unlock(btr_search_latch_part[i]);
}
}
trx->has_search_latch = FALSE;
}
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
#endif
ut_ad(prebuilt->sql_stat_start || trx->state == TRX_ACTIVE);
ut_ad(trx->state == TRX_NOT_STARTED
|| trx->state == TRX_ACTIVE);
@ -4851,7 +4789,9 @@ func_exit:
}
}
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(err);

15
row/row0uins.c

@ -340,13 +340,14 @@ row_undo_ins(
/* The database must have crashed after
inserting a clustered index record but before
writing all the externally stored columns of
that record. Because secondary index entries
are inserted after the clustered index record,
we may assume that the secondary index record
does not exist. However, this situation may
only occur during the rollback of incomplete
transactions. */
ut_a(trx_is_recv(node->trx));
that record, or a statement is being rolled
back because an error occurred while storing
off-page columns.
Because secondary index entries are inserted
after the clustered index record, we may
assume that the secondary index record does
not exist. */
} else {
log_free_check();
err = row_undo_ins_remove_sec(node->index, entry);

46
row/row0umod.c

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
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
@ -128,11 +128,10 @@ row_undo_mod_clust_low(
}
/***********************************************************//**
Removes a clustered index record after undo if possible.
Purges a clustered index record after undo if possible.
This is attempted when the record was inserted by updating a
delete-marked record and there no longer exist transactions
that would see the delete-marked record. In other words, we
roll back the insert by purging the record.
that would see the delete-marked record.
@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
static
ulint
@ -140,11 +139,12 @@ row_undo_mod_remove_clust_low(
/*==========================*/
undo_node_t* node, /*!< in: row undo node */
que_thr_t* thr, /*!< in: query thread */
mtr_t* mtr, /*!< in: mtr */
mtr_t* mtr, /*!< in/out: mini-transaction */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
btr_cur_t* btr_cur;
ulint err;
ulint trx_id_offset;
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
@ -159,6 +159,42 @@ row_undo_mod_remove_clust_low(
btr_cur = btr_pcur_get_btr_cur(&node->pcur);
trx_id_offset = btr_cur_get_index(btr_cur)->trx_id_offset;
if (!trx_id_offset) {
mem_heap_t* heap = NULL;
ulint trx_id_col;
ulint* offsets;
ulint len;
trx_id_col = dict_index_get_sys_col_pos(
btr_cur_get_index(btr_cur), DATA_TRX_ID);
ut_ad(trx_id_col > 0);
ut_ad(trx_id_col != ULINT_UNDEFINED);
offsets = rec_get_offsets(
btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur),
NULL, trx_id_col + 1, &heap);
trx_id_offset = rec_get_nth_field_offs(
offsets, trx_id_col, &len);
ut_ad(len == DATA_TRX_ID_LEN);
mem_heap_free(heap);
}
if (trx_read_trx_id(btr_cur_get_rec(btr_cur) + trx_id_offset)
!= node->new_trx_id) {
/* The record must have been purged and then replaced
with a different one. */
return(DB_SUCCESS);
}
/* We are about to remove an old, delete-marked version of the
record that may have been delete-marked by a different transaction
than the rolling-back one. */
ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur),
dict_table_is_comp(node->table)));
if (mode == BTR_MODIFY_LEAF) {
err = btr_cur_optimistic_delete(btr_cur, mtr)
? DB_SUCCESS

24
row/row0upd.c

@ -1607,7 +1607,8 @@ row_upd_sec_index_entry(
}
search_result = row_search_index_entry(index, entry,
trx->fake_changes ? BTR_SEARCH_LEAF : mode,
UNIV_UNLIKELY(trx->fake_changes)
? BTR_SEARCH_LEAF : mode,
&pcur, &mtr);
btr_cur = btr_pcur_get_btr_cur(&pcur);
@ -1855,7 +1856,7 @@ row_upd_clust_rec_by_insert(
the previous invocation of this function. Mark the
off-page columns in the entry inherited. */
if (!(trx->fake_changes)) {
if (UNIV_LIKELY(!trx->fake_changes)) {
change_ownership = row_upd_clust_rec_by_insert_inherit(
NULL, NULL, entry, node->update);
ut_a(change_ownership);
@ -1889,7 +1890,8 @@ err_exit:
delete-marked old record, mark them disowned by the
old record and owned by the new entry. */
if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) {
if (rec_offs_any_extern(offsets)
&& UNIV_LIKELY(!(trx->fake_changes))) {
change_ownership = row_upd_clust_rec_by_insert_inherit(
rec, offsets, entry, node->update);
@ -2019,9 +2021,10 @@ row_upd_clust_rec(
the same transaction do not modify the record in the meantime.
Therefore we can assert that the restoration of the cursor succeeds. */
ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes
? BTR_SEARCH_TREE : BTR_MODIFY_TREE,
pcur, mtr));
ut_a(btr_pcur_restore_position(
(UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)
? BTR_SEARCH_TREE : BTR_MODIFY_TREE),
pcur, mtr));
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
dict_table_is_comp(index->table)));
@ -2032,7 +2035,8 @@ row_upd_clust_rec(
node->cmpl_info, thr, mtr);
/* skip store extern for fake_changes */
if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) {
if (err == DB_SUCCESS && big_rec
&& UNIV_LIKELY(!(thr_get_trx(thr)->fake_changes))) {
ulint offsets_[REC_OFFS_NORMAL_SIZE];
rec_t* rec;
rec_offs_init(offsets_);
@ -2192,8 +2196,10 @@ row_upd_clust_step(
ut_a(pcur->rel_pos == BTR_PCUR_ON);
success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF,
pcur, mtr);
success = btr_pcur_restore_position(
(UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)
? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF),
pcur, mtr);
if (!success) {
err = DB_RECORD_NOT_FOUND;

106
srv/srv0srv.c

@ -1275,8 +1275,10 @@ retry:
os_thread_yield();
goto retry;
}
if (trx->has_search_latch
|| NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
ut_ad(!trx->has_search_latch);
if (NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
enter_innodb_with_tickets(trx);
@ -1319,7 +1321,9 @@ srv_conc_enter_innodb(
ulint sec;
ulint ms;
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
@ -1379,7 +1383,9 @@ retry:
/* If the transaction is not holding resources, let it sleep
for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
if (!has_slept && !trx->has_search_latch
ut_ad(!trx->has_search_latch);
if (!has_slept
&& NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
has_slept = TRUE; /* We let it sleep only once to avoid
@ -1434,10 +1440,8 @@ retry:
return;
}
/* Release possible search system latch this thread has */
if (trx->has_search_latch) {
trx_search_latch_release_if_reserved(trx);
}
/* No-op for XtraDB. */
trx_search_latch_release_if_reserved(trx);
/* Add to the queue */
slot->reserved = TRUE;
@ -1456,6 +1460,7 @@ retry:
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
@ -1507,7 +1512,9 @@ srv_conc_force_enter_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
@ -1598,7 +1605,9 @@ srv_conc_force_exit_innodb(
os_event_set(slot->event);
}
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
}
@ -1612,7 +1621,9 @@ srv_conc_exit_innodb(
trx_t* trx) /*!< in: transaction object associated with the
thread */
{
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
@ -1885,7 +1896,9 @@ srv_suspend_mysql_thread(
os_event_wait(event);
thd_wait_end(trx->mysql_thd);
ut_ad(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
@ -2047,7 +2060,8 @@ srv_printf_innodb_monitor(
ulint n_reserved;
ibool ret;
ulint btr_search_sys_subtotal;
ulong btr_search_sys_constant;
ulong btr_search_sys_variable;
ulint lock_sys_subtotal;
ulint recv_sys_subtotal;
@ -2113,7 +2127,7 @@ srv_printf_innodb_monitor(
ibuf_print(file);
for (i = 0; i < btr_search_index_num; i++) {
ha_print_info(file, btr_search_get_hash_index((index_id_t)i));
ha_print_info(file, btr_search_sys->hash_tables[i]);
}
fprintf(file,
@ -2141,16 +2155,28 @@ srv_printf_innodb_monitor(
fprintf(file,
"Total memory allocated by read views " ULINTPF "\n",
srv_read_views_memory);
/* Calcurate reserved memories */
if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
btr_search_sys_subtotal = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
} else {
btr_search_sys_subtotal = 0;
for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
btr_search_sys_subtotal += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
}
/* Calculate AHI constant and variable memory allocations */
btr_search_sys_constant = 0;
btr_search_sys_variable = 0;
ut_ad(btr_search_sys->hash_tables);
for (i = 0; i < btr_search_index_num; i++) {
hash_table_t* ht = btr_search_sys->hash_tables[i];
ut_ad(ht);
ut_ad(ht->heap);
/* Multiple mutexes/heaps are currently never used for adaptive
hash index tables. */
ut_ad(!ht->n_mutexes);
ut_ad(!ht->heaps);
btr_search_sys_variable += mem_heap_get_size(ht->heap);
btr_search_sys_constant += ht->n_cells * sizeof(hash_cell_t);
}
btr_search_sys_subtotal *= btr_search_index_num;
lock_sys_subtotal = 0;
if (trx_sys) {
@ -2175,12 +2201,9 @@ srv_printf_innodb_monitor(
" Lock system %lu \t(%lu + %lu)\n"
" Recovery system %lu \t(%lu + %lu)\n",
(ulong) (btr_search_sys
? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0)
+ btr_search_sys_subtotal,
(ulong) (btr_search_sys
? (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t)) : 0),
(ulong) btr_search_sys_subtotal,
btr_search_sys_constant + btr_search_sys_variable,
btr_search_sys_constant,
btr_search_sys_variable,
(ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
@ -2342,17 +2365,22 @@ srv_export_innodb_status(void)
buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
buf_get_total_list_size_in_bytes(&buf_pools_list_size);
if (btr_search_sys && btr_search_sys->hash_index[0]->heap) {
mem_adaptive_hash = mem_heap_get_size(btr_search_sys->hash_index[0]->heap);
} else {
mem_adaptive_hash = 0;
for (i=0; i < btr_search_sys->hash_index[0]->n_mutexes; i++) {
mem_adaptive_hash += mem_heap_get_size(btr_search_sys->hash_index[0]->heaps[i]);
}
}
mem_adaptive_hash *= btr_search_index_num;
if (btr_search_sys) {
mem_adaptive_hash += (btr_search_sys->hash_index[0]->n_cells * btr_search_index_num * sizeof(hash_cell_t));
mem_adaptive_hash = 0;
ut_ad(btr_search_sys->hash_tables);
for (i = 0; i < btr_search_index_num; i++) {
hash_table_t* ht = btr_search_sys->hash_tables[i];
ut_ad(ht);
ut_ad(ht->heap);
/* Multiple mutexes/heaps are currently never used for adaptive
hash index tables. */
ut_ad(!ht->n_mutexes);
ut_ad(!ht->heaps);
mem_adaptive_hash += mem_heap_get_size(ht->heap);
mem_adaptive_hash += ht->n_cells * sizeof(hash_cell_t);
}
mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
@ -2365,7 +2393,7 @@ srv_export_innodb_status(void)
export_vars.innodb_adaptive_hash_cells = 0;
export_vars.innodb_adaptive_hash_heap_buffers = 0;
for (i = 0; i < btr_search_index_num; i++) {
hash_table_t* table = btr_search_get_hash_index((index_id_t)i);
hash_table_t* table = btr_search_sys->hash_tables[i];
export_vars.innodb_adaptive_hash_cells
+= hash_get_n_cells(table);
@ -3156,6 +3184,12 @@ srv_redo_log_follow_thread(
os_event_wait(srv_checkpoint_completed_event);
os_event_reset(srv_checkpoint_completed_event);
#ifdef UNIV_DEBUG
if (!srv_track_changed_pages) {
continue;
}
#endif
if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
if (!log_online_follow_redo_log()) {
/* TODO: sync with I_S log tracking status? */

27
trx/trx0trx.c

@ -385,27 +385,6 @@ trx_allocate_for_background(void)
return(trx);
}
/********************************************************************//**
Releases the search latch if trx has reserved it. */
UNIV_INTERN
void
trx_search_latch_release_if_reserved(
/*=================================*/
trx_t* trx) /*!< in: transaction */
{
ulint i;
if (trx->has_search_latch) {
for (i = 0; i < btr_search_index_num; i++) {
if (trx->has_search_latch & ((ulint)1 << i)) {
rw_lock_s_unlock(btr_search_latch_part[i]);
}
}
trx->has_search_latch = FALSE;
}
}
/********************************************************************//**
Frees a transaction object. */
UNIV_INTERN
@ -468,6 +447,9 @@ trx_free(
ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
ut_a(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
#endif
ut_a(trx->dict_operation_lock_mode == 0);
@ -527,6 +509,9 @@ trx_free_prepared(
ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0);
ut_a(!trx->has_search_latch);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!btr_search_own_any());
#endif
ut_a(trx->dict_operation_lock_mode == 0);

Loading…
Cancel
Save