Percona-Server-5.5.30-rel30.2.tar.gz
This commit is contained in:
parent
086b54c281
commit
bcfa90b471
@ -688,7 +688,7 @@ btr_root_fseg_validate(
|
||||
{
|
||||
ulint offset = mach_read_from_2(seg_header + FSEG_HDR_OFFSET);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table)) {
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table != 0)) {
|
||||
return (mach_read_from_4(seg_header + FSEG_HDR_SPACE) == space)
|
||||
&& (offset >= FIL_PAGE_DATA)
|
||||
&& (offset <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
|
||||
@ -723,17 +723,14 @@ btr_root_block_get(
|
||||
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
|
||||
index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
btr_assert_not_corrupted(block, index);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
if (!dict_index_is_ibuf(index)) {
|
||||
const page_t* root = buf_block_get_frame(block);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table)) {
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table != 0)) {
|
||||
if (!btr_root_fseg_validate(FIL_PAGE_DATA
|
||||
+ PAGE_BTR_SEG_LEAF
|
||||
+ root, space))
|
||||
@ -1063,11 +1060,11 @@ btr_get_size(
|
||||
|
||||
root = btr_root_get(index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !root) {
|
||||
SRV_CORRUPT_TABLE_CHECK(root,
|
||||
{
|
||||
mtr_commit(mtr);
|
||||
return(0);
|
||||
}
|
||||
ut_a(root);
|
||||
});
|
||||
|
||||
if (flag == BTR_N_LEAF_PAGES) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
@ -1525,11 +1522,11 @@ leaf_loop:
|
||||
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
|
||||
NULL, &mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !root) {
|
||||
SRV_CORRUPT_TABLE_CHECK(root,
|
||||
{
|
||||
mtr_commit(&mtr);
|
||||
return;
|
||||
}
|
||||
ut_a(root);
|
||||
});
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
|
||||
@ -1555,11 +1552,12 @@ top_loop:
|
||||
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
|
||||
NULL, &mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !root) {
|
||||
SRV_CORRUPT_TABLE_CHECK(root,
|
||||
{
|
||||
mtr_commit(&mtr);
|
||||
return;
|
||||
}
|
||||
ut_a(root);
|
||||
});
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
|
||||
+ root, space));
|
||||
@ -1593,10 +1591,7 @@ btr_free_root(
|
||||
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
|
||||
NULL, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return;
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return;);
|
||||
|
||||
btr_search_drop_page_hash_index(block);
|
||||
|
||||
@ -4565,10 +4560,11 @@ btr_validate_index(
|
||||
|
||||
root = btr_root_get(index, &mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table && !root)) {
|
||||
SRV_CORRUPT_TABLE_CHECK(root,
|
||||
{
|
||||
mtr_commit(&mtr);
|
||||
return(FALSE);
|
||||
}
|
||||
});
|
||||
|
||||
n = btr_page_get_level(root, &mtr);
|
||||
|
||||
|
111
btr/btr0cur.c
111
btr/btr0cur.c
@ -258,10 +258,8 @@ btr_cur_latch_leaves(
|
||||
get_block = btr_block_get(
|
||||
space, zip_size, page_no, mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
@ -283,10 +281,8 @@ btr_cur_latch_leaves(
|
||||
space, zip_size, left_page_no,
|
||||
sibling_mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(page));
|
||||
@ -309,10 +305,8 @@ btr_cur_latch_leaves(
|
||||
space, zip_size, page_no,
|
||||
mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
@ -325,10 +319,8 @@ btr_cur_latch_leaves(
|
||||
space, zip_size, right_page_no,
|
||||
sibling_mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(page));
|
||||
@ -357,10 +349,8 @@ btr_cur_latch_leaves(
|
||||
left_page_no, mode, cursor->index, mtr);
|
||||
cursor->left_block = get_block;
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame)
|
||||
== page_is_comp(page));
|
||||
@ -373,10 +363,8 @@ btr_cur_latch_leaves(
|
||||
get_block = btr_block_get(
|
||||
space, zip_size, page_no, mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
}
|
||||
ut_a(get_block);
|
||||
SRV_CORRUPT_TABLE_CHECK(get_block, return;);
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
@ -652,18 +640,19 @@ retry_page_get:
|
||||
file, line, mtr);
|
||||
|
||||
if (block == NULL) {
|
||||
if (srv_pass_corrupt_table
|
||||
&& buf_mode != BUF_GET_IF_IN_POOL
|
||||
&& buf_mode != BUF_GET_IF_IN_POOL_OR_WATCH) {
|
||||
page_cursor->block = 0;
|
||||
page_cursor->rec = 0;
|
||||
if (estimate) {
|
||||
cursor->path_arr->nth_rec = ULINT_UNDEFINED;
|
||||
}
|
||||
goto func_exit;
|
||||
}
|
||||
ut_a(buf_mode == BUF_GET_IF_IN_POOL
|
||||
|| buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH);
|
||||
SRV_CORRUPT_TABLE_CHECK(buf_mode == BUF_GET_IF_IN_POOL ||
|
||||
buf_mode == BUF_GET_IF_IN_POOL_OR_WATCH,
|
||||
{
|
||||
page_cursor->block = 0;
|
||||
page_cursor->rec = 0;
|
||||
if (estimate) {
|
||||
|
||||
cursor->path_arr->nth_rec =
|
||||
ULINT_UNDEFINED;
|
||||
}
|
||||
|
||||
goto func_exit;
|
||||
});
|
||||
|
||||
/* This must be a search to perform an insert/delete
|
||||
mark/ delete; try using the insert/delete buffer */
|
||||
@ -739,15 +728,18 @@ retry_page_get:
|
||||
block->check_index_page_at_flush = TRUE;
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
SRV_CORRUPT_TABLE_CHECK(page,
|
||||
{
|
||||
page_cursor->block = 0;
|
||||
page_cursor->rec = 0;
|
||||
|
||||
if (estimate) {
|
||||
|
||||
cursor->path_arr->nth_rec = ULINT_UNDEFINED;
|
||||
}
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
ut_a(page);
|
||||
});
|
||||
|
||||
if (rw_latch != RW_NO_LATCH) {
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
@ -943,15 +935,19 @@ btr_cur_open_at_index_side_func(
|
||||
file, line, mtr);
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
SRV_CORRUPT_TABLE_CHECK(page,
|
||||
{
|
||||
page_cursor->block = 0;
|
||||
page_cursor->rec = 0;
|
||||
|
||||
if (estimate) {
|
||||
cursor->path_arr->nth_rec = ULINT_UNDEFINED;
|
||||
|
||||
cursor->path_arr->nth_rec =
|
||||
ULINT_UNDEFINED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ut_a(page);
|
||||
/* Can't use break with the macro */
|
||||
goto exit_loop;
|
||||
});
|
||||
|
||||
ut_ad(index->id == btr_page_get_index_id(page));
|
||||
|
||||
@ -1021,6 +1017,7 @@ btr_cur_open_at_index_side_func(
|
||||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
@ -1074,12 +1071,13 @@ btr_cur_open_at_rnd_pos_func(
|
||||
file, line, mtr);
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
SRV_CORRUPT_TABLE_CHECK(page,
|
||||
{
|
||||
page_cursor->block = 0;
|
||||
page_cursor->rec = 0;
|
||||
break;
|
||||
}
|
||||
ut_a(page);
|
||||
|
||||
goto exit_loop;
|
||||
});
|
||||
|
||||
ut_ad(index->id == btr_page_get_index_id(page));
|
||||
|
||||
@ -1112,6 +1110,7 @@ btr_cur_open_at_rnd_pos_func(
|
||||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
@ -1300,10 +1299,7 @@ btr_cur_optimistic_insert(
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(DB_CORRUPTION););
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
index = cursor->index;
|
||||
@ -3149,10 +3145,7 @@ btr_cur_optimistic_delete(
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(DB_CORRUPTION);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(DB_CORRUPTION););
|
||||
|
||||
ut_ad(page_is_leaf(buf_block_get_frame(block)));
|
||||
|
||||
@ -3868,10 +3861,7 @@ btr_estimate_number_of_different_key_vals(
|
||||
|
||||
page = btr_cur_get_page(&cursor);
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
break;
|
||||
}
|
||||
ut_a(page);
|
||||
SRV_CORRUPT_TABLE_CHECK(page, goto exit_loop;);
|
||||
|
||||
rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
|
||||
@ -3957,6 +3947,7 @@ btr_estimate_number_of_different_key_vals(
|
||||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
exit_loop:
|
||||
/* If we saw k borders between different key values on
|
||||
n_sample_pages leaf pages, we can estimate how many
|
||||
there will be in index->stat_n_leaf_pages */
|
||||
|
@ -116,10 +116,7 @@ btr_pcur_store_position(
|
||||
|
||||
block = btr_pcur_get_block(cursor);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return;
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return;);
|
||||
|
||||
index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
|
||||
|
||||
@ -439,14 +436,16 @@ btr_pcur_move_to_next_page(
|
||||
btr_pcur_get_btr_cur(cursor)->index, mtr);
|
||||
next_page = buf_block_get_frame(next_block);
|
||||
|
||||
if (srv_pass_corrupt_table && !next_page) {
|
||||
SRV_CORRUPT_TABLE_CHECK(next_page,
|
||||
{
|
||||
btr_leaf_page_release(btr_pcur_get_block(cursor),
|
||||
cursor->latch_mode, mtr);
|
||||
btr_pcur_get_page_cur(cursor)->block = 0;
|
||||
btr_pcur_get_page_cur(cursor)->rec = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
ut_a(next_page);
|
||||
});
|
||||
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(next_page) == page_is_comp(page));
|
||||
ut_a(btr_page_get_prev(next_page, mtr)
|
||||
|
@ -649,10 +649,7 @@ btr_search_info_update_slow(
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return;
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return;);
|
||||
|
||||
/* NOTE that the following two function calls do NOT protect
|
||||
info or block->n_fields etc. with any semaphore, to save CPU time!
|
||||
|
121
buf/buf0buf.c
121
buf/buf0buf.c
@ -2002,27 +2002,6 @@ lookup:
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(bpage->space_was_being_deleted)) {
|
||||
/* This page is obsoleted, should discard and retry */
|
||||
rw_lock_s_unlock(&buf_pool->page_hash_latch);
|
||||
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
block_mutex = buf_page_get_mutex_enter(bpage);
|
||||
|
||||
if (UNIV_UNLIKELY(!block_mutex)) {
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
goto lookup;
|
||||
}
|
||||
|
||||
buf_LRU_free_block(bpage, TRUE, TRUE);
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
block_mutex = NULL;
|
||||
|
||||
goto lookup;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(!bpage->zip.data)) {
|
||||
/* There is no compressed page. */
|
||||
err_exit:
|
||||
@ -2031,11 +2010,11 @@ err_exit:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table <= 1) {
|
||||
if (bpage->is_corrupt) {
|
||||
rw_lock_s_unlock(&buf_pool->page_hash_latch);
|
||||
return(NULL);
|
||||
}
|
||||
if (UNIV_UNLIKELY(bpage->is_corrupt && srv_pass_corrupt_table <= 1)) {
|
||||
|
||||
rw_lock_s_unlock(&buf_pool->page_hash_latch);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
block_mutex = buf_page_get_mutex_enter(bpage);
|
||||
@ -2533,26 +2512,6 @@ loop:
|
||||
block = (buf_block_t*) buf_page_hash_get_low(
|
||||
buf_pool, space, offset, fold);
|
||||
if (block) {
|
||||
if (UNIV_UNLIKELY(block->page.space_was_being_deleted)) {
|
||||
/* This page is obsoleted, should discard and retry */
|
||||
rw_lock_s_unlock(&buf_pool->page_hash_latch);
|
||||
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
|
||||
|
||||
if (UNIV_UNLIKELY(!block_mutex)) {
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
block_mutex = NULL;
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
|
||||
ut_a(block_mutex);
|
||||
@ -2640,11 +2599,12 @@ got_block:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table <= 1) {
|
||||
if (block->page.is_corrupt) {
|
||||
mutex_exit(block_mutex);
|
||||
return(NULL);
|
||||
}
|
||||
if (UNIV_UNLIKELY(block->page.is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
switch (buf_block_get_state(block)) {
|
||||
@ -3487,28 +3447,12 @@ buf_page_init_for_read(
|
||||
|
||||
fold = buf_page_address_fold(space, offset);
|
||||
|
||||
retry:
|
||||
//buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(&buf_pool->page_hash_latch);
|
||||
|
||||
watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
|
||||
|
||||
if (UNIV_UNLIKELY(watch_page && watch_page->space_was_being_deleted)) {
|
||||
mutex_t* block_mutex = buf_page_get_mutex_enter(watch_page);
|
||||
|
||||
/* This page is obsoleted, should discard and retry */
|
||||
rw_lock_x_unlock(&buf_pool->page_hash_latch);
|
||||
ut_a(block_mutex);
|
||||
|
||||
buf_LRU_free_block(watch_page, TRUE, TRUE);
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
|
||||
/* The page is already in the buffer pool. */
|
||||
watch_page = NULL;
|
||||
@ -3637,7 +3581,6 @@ err_exit:
|
||||
bpage->state = BUF_BLOCK_ZIP_PAGE;
|
||||
bpage->space = space;
|
||||
bpage->offset = offset;
|
||||
bpage->space_was_being_deleted = FALSE;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
bpage->in_page_hash = FALSE;
|
||||
@ -3722,7 +3665,6 @@ buf_page_create(
|
||||
|
||||
fold = buf_page_address_fold(space, offset);
|
||||
|
||||
retry:
|
||||
//buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(&buf_pool->page_hash_latch);
|
||||
@ -3730,21 +3672,6 @@ retry:
|
||||
block = (buf_block_t*) buf_page_hash_get_low(
|
||||
buf_pool, space, offset, fold);
|
||||
|
||||
if (UNIV_UNLIKELY(block && block->page.space_was_being_deleted)) {
|
||||
mutex_t* block_mutex = buf_page_get_mutex_enter((buf_page_t*)block);
|
||||
|
||||
/* This page is obsoleted, should discard and retry */
|
||||
rw_lock_x_unlock(&buf_pool->page_hash_latch);
|
||||
ut_a(block_mutex);
|
||||
|
||||
buf_LRU_free_block((buf_page_t*)block, TRUE, TRUE);
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (block
|
||||
&& buf_page_in_file(&block->page)
|
||||
&& !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
|
||||
@ -4001,7 +3928,8 @@ buf_page_io_complete(
|
||||
(ulong) bpage->offset);
|
||||
}
|
||||
|
||||
if (!srv_pass_corrupt_table || !bpage->is_corrupt) {
|
||||
if (UNIV_LIKELY(!bpage->is_corrupt ||
|
||||
!srv_pass_corrupt_table)) {
|
||||
/* From version 3.23.38 up we store the page checksum
|
||||
to the 4 first bytes of the page end lsn field */
|
||||
|
||||
@ -4086,13 +4014,26 @@ corrupt:
|
||||
}
|
||||
|
||||
if (uncompressed && !recv_no_ibuf_operations) {
|
||||
|
||||
buf_block_t* block;
|
||||
ibool update_ibuf_bitmap;
|
||||
|
||||
if (UNIV_UNLIKELY(bpage->is_corrupt &&
|
||||
srv_pass_corrupt_table)) {
|
||||
|
||||
block = NULL;
|
||||
update_ibuf_bitmap = FALSE;
|
||||
|
||||
} else {
|
||||
|
||||
block = (buf_block_t *) bpage;
|
||||
update_ibuf_bitmap = TRUE;
|
||||
}
|
||||
|
||||
ibuf_merge_or_delete_for_page(
|
||||
/* Delete possible entries, if bpage is_corrupt */
|
||||
(srv_pass_corrupt_table && bpage->is_corrupt) ? NULL :
|
||||
(buf_block_t*) bpage, bpage->space,
|
||||
block, bpage->space,
|
||||
bpage->offset, buf_page_get_zip_size(bpage),
|
||||
(srv_pass_corrupt_table && bpage->is_corrupt) ? FALSE :
|
||||
TRUE);
|
||||
update_ibuf_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ buf_flush_ready_for_replace(
|
||||
|
||||
if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
|
||||
|
||||
return((bpage->oldest_modification == 0 || bpage->space_was_being_deleted)
|
||||
return(bpage->oldest_modification == 0
|
||||
&& buf_page_get_io_fix(bpage) == BUF_IO_NONE
|
||||
&& bpage->buf_fix_count == 0);
|
||||
}
|
||||
@ -501,13 +501,6 @@ buf_flush_ready_for_flush(
|
||||
&& buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
|
||||
ut_ad(bpage->in_flush_list);
|
||||
|
||||
if (bpage->space_was_being_deleted) {
|
||||
/* should be removed from flush_list here */
|
||||
/* because buf_flush_try_neighbors() cannot flush without fil_space_get_size(space) */
|
||||
buf_flush_remove(bpage);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (flush_type != BUF_FLUSH_LRU) {
|
||||
|
||||
return(TRUE);
|
||||
|
@ -884,42 +884,6 @@ buf_LRU_flush_or_remove_pages(
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_mark_space_was_deleted(
|
||||
/*===========================*/
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
buf_page_t* bpage;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
|
||||
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
|
||||
|
||||
while (bpage != NULL) {
|
||||
if (buf_page_get_space(bpage) == id) {
|
||||
bpage->space_was_being_deleted = TRUE;
|
||||
}
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage);
|
||||
}
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
|
||||
/* The AHI entries for the tablespace being deleted should be
|
||||
removed by now. */
|
||||
ut_ad(buf_LRU_drop_page_hash_for_tablespace(buf_pool, id)
|
||||
== 0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
@ -1891,10 +1855,6 @@ buf_LRU_free_block(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) {
|
||||
buf_flush_remove(bpage);
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0);
|
||||
#endif /* UNIV_IBUF_COUNT_DEBUG */
|
||||
|
@ -245,13 +245,7 @@ not_to_recover:
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table) {
|
||||
if (*err != DB_SUCCESS) {
|
||||
bpage->is_corrupt = TRUE;
|
||||
}
|
||||
} else {
|
||||
ut_a(*err == DB_SUCCESS);
|
||||
}
|
||||
SRV_CORRUPT_TABLE_CHECK(*err == DB_SUCCESS, bpage->is_corrupt = TRUE;);
|
||||
|
||||
if (sync) {
|
||||
/* The i/o is already completed when we arrive from
|
||||
|
@ -4419,7 +4419,7 @@ dict_reload_statistics(
|
||||
while (index) {
|
||||
mtr_t mtr;
|
||||
|
||||
if (table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(table->is_corrupt)) {
|
||||
ut_a(srv_pass_corrupt_table);
|
||||
mem_heap_free(heap);
|
||||
return(FALSE);
|
||||
@ -4577,7 +4577,7 @@ dict_store_statistics(
|
||||
heap = mem_heap_create(1000);
|
||||
|
||||
while (index) {
|
||||
if (table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(table->is_corrupt)) {
|
||||
ut_a(srv_pass_corrupt_table);
|
||||
mem_heap_free(heap);
|
||||
return;
|
||||
@ -4771,7 +4771,7 @@ dict_update_statistics(
|
||||
mtr_t mtr;
|
||||
ulint size;
|
||||
|
||||
if (table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(table->is_corrupt)) {
|
||||
ut_a(srv_pass_corrupt_table);
|
||||
dict_table_stats_unlock(table, RW_X_LATCH);
|
||||
return;
|
||||
|
109
fil/fil0fil.c
109
fil/fil0fil.c
@ -2426,15 +2426,11 @@ try_again:
|
||||
To deal with potential read requests by checking the
|
||||
::stop_new_ops flag in fil_io() */
|
||||
|
||||
if (srv_lazy_drop_table) {
|
||||
buf_LRU_mark_space_was_deleted(id);
|
||||
} else {
|
||||
buf_LRU_flush_or_remove_pages(
|
||||
id, evict_all
|
||||
? BUF_REMOVE_ALL_NO_WRITE
|
||||
: BUF_REMOVE_FLUSH_NO_WRITE);
|
||||
|
||||
}
|
||||
#endif
|
||||
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
|
||||
|
||||
@ -5304,22 +5300,6 @@ _fil_io(
|
||||
srv_data_written+= len;
|
||||
}
|
||||
|
||||
/* if the table space was already deleted, space might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
if (mode == OS_AIO_NORMAL) {
|
||||
buf_page_io_complete(message);
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
if (type == OS_FILE_READ) {
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
} else {
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserve the fil_system mutex and make sure that we can open at
|
||||
least one file while holding it, if the file is not already open */
|
||||
|
||||
@ -5423,35 +5403,38 @@ _fil_io(
|
||||
ut_a(byte_offset % OS_MIN_LOG_BLOCK_SIZE == 0);
|
||||
ut_a((len % OS_MIN_LOG_BLOCK_SIZE) == 0);
|
||||
|
||||
if (srv_pass_corrupt_table == 1 && space->is_corrupt) {
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (UNIV_UNLIKELY(space->is_corrupt && srv_pass_corrupt_table)) {
|
||||
|
||||
/* should ignore i/o for the crashed space */
|
||||
mutex_enter(&fil_system->mutex);
|
||||
fil_node_complete_io(node, fil_system, type);
|
||||
mutex_exit(&fil_system->mutex);
|
||||
if (mode == OS_AIO_NORMAL) {
|
||||
ut_a(space->purpose == FIL_TABLESPACE);
|
||||
buf_page_io_complete(message);
|
||||
}
|
||||
if (type == OS_FILE_READ) {
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
} else {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
} else {
|
||||
if (srv_pass_corrupt_table > 1 && space->is_corrupt) {
|
||||
/* should ignore write i/o for the crashed space */
|
||||
if (type == OS_FILE_WRITE) {
|
||||
mutex_enter(&fil_system->mutex);
|
||||
fil_node_complete_io(node, fil_system, type);
|
||||
mutex_exit(&fil_system->mutex);
|
||||
if (mode == OS_AIO_NORMAL) {
|
||||
ut_a(space->purpose == FIL_TABLESPACE);
|
||||
buf_page_io_complete(message);
|
||||
}
|
||||
return(DB_SUCCESS);
|
||||
if (srv_pass_corrupt_table == 1 ||
|
||||
type == OS_FILE_WRITE) {
|
||||
|
||||
mutex_enter(&fil_system->mutex);
|
||||
fil_node_complete_io(node, fil_system, type);
|
||||
mutex_exit(&fil_system->mutex);
|
||||
if (mode == OS_AIO_NORMAL) {
|
||||
ut_a(space->purpose == FIL_TABLESPACE);
|
||||
buf_page_io_complete(message);
|
||||
}
|
||||
}
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
|
||||
if (srv_pass_corrupt_table == 1 && type == OS_FILE_READ) {
|
||||
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
|
||||
} else if (type == OS_FILE_WRITE) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
} /**/
|
||||
|
||||
/* Queue the aio request */
|
||||
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
|
||||
offset_low, offset_high, len, node, message, space_id,
|
||||
trx);
|
||||
|
||||
#else
|
||||
/* In ibbackup do normal i/o, not aio */
|
||||
if (type == OS_FILE_READ) {
|
||||
ret = os_file_read(node->handle, buf, offset_low, offset_high,
|
||||
@ -5460,26 +5443,7 @@ _fil_io(
|
||||
ret = os_file_write(node->name, node->handle, buf,
|
||||
offset_low, offset_high, len);
|
||||
}
|
||||
#else
|
||||
/* Queue the aio request */
|
||||
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
|
||||
offset_low, offset_high, len, node, message, space_id, trx);
|
||||
#endif
|
||||
} /**/
|
||||
|
||||
/* if the table space was already deleted, space might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
if (mode == OS_AIO_SYNC) {
|
||||
if (type == OS_FILE_READ) {
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
} else {
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(ret);
|
||||
|
||||
@ -5603,21 +5567,6 @@ fil_aio_wait(
|
||||
&message, &type, &space_id);
|
||||
}
|
||||
|
||||
/* if the table space was already deleted, fil_node might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
/* intended not to be uncompress read page */
|
||||
ut_a(buf_page_get_io_fix_unlocked(message) == BUF_IO_WRITE
|
||||
|| !buf_page_get_zip_size(message)
|
||||
|| buf_page_get_state(message) != BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
srv_set_io_thread_op_info(segment, "complete io for buf page");
|
||||
buf_page_io_complete(message);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(ret);
|
||||
if (UNIV_UNLIKELY(fil_node == NULL)) {
|
||||
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
|
||||
|
@ -317,10 +317,7 @@ fsp_get_space_header(
|
||||
|
||||
block = buf_page_get(id, zip_size, 0, RW_X_LATCH, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
|
||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||
@ -731,10 +728,7 @@ xdes_get_descriptor(
|
||||
|
||||
block = buf_page_get(space, zip_size, 0, RW_X_LATCH, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||
|
||||
@ -1882,10 +1876,7 @@ fsp_seg_inode_page_find_free(
|
||||
{
|
||||
fseg_inode_t* inode;
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
return(ULINT_UNDEFINED);
|
||||
}
|
||||
ut_a(page);
|
||||
SRV_CORRUPT_TABLE_CHECK(page, return(ULINT_UNDEFINED););
|
||||
|
||||
for (; i < FSP_SEG_INODES_PER_PAGE(zip_size); i++) {
|
||||
|
||||
@ -1999,10 +1990,7 @@ fsp_alloc_seg_inode(
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
if (srv_pass_corrupt_table && !page) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(page);
|
||||
SRV_CORRUPT_TABLE_CHECK(page, return(0););
|
||||
|
||||
n = fsp_seg_inode_page_find_free(page, 0, zip_size, mtr);
|
||||
|
||||
@ -2097,10 +2085,7 @@ fseg_inode_try_get(
|
||||
|
||||
inode = fut_get_ptr(space, zip_size, inode_addr, RW_X_LATCH, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !inode) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(inode);
|
||||
SRV_CORRUPT_TABLE_CHECK(inode, return(0););
|
||||
|
||||
if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
|
||||
|
||||
@ -2128,7 +2113,7 @@ fseg_inode_get(
|
||||
{
|
||||
fseg_inode_t* inode
|
||||
= fseg_inode_try_get(header, space, zip_size, mtr);
|
||||
ut_a(srv_pass_corrupt_table || inode);
|
||||
SRV_CORRUPT_TABLE_CHECK(inode, ; /* do nothing */);
|
||||
return(inode);
|
||||
}
|
||||
|
||||
@ -3320,12 +3305,12 @@ fseg_free_page_low(
|
||||
|
||||
descr = xdes_get_descriptor(space, zip_size, page, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !descr) {
|
||||
SRV_CORRUPT_TABLE_CHECK(descr,
|
||||
{
|
||||
/* The page may be corrupt. pass it. */
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
ut_a(descr);
|
||||
if (xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, mtr)) {
|
||||
fputs("InnoDB: Dump of the tablespace extent descriptor: ",
|
||||
stderr);
|
||||
@ -3574,15 +3559,15 @@ fseg_free_step(
|
||||
|
||||
descr = xdes_get_descriptor(space, zip_size, header_page, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !descr) {
|
||||
SRV_CORRUPT_TABLE_CHECK(descr,
|
||||
{
|
||||
/* The page may be corrupt. pass it. */
|
||||
return(TRUE);
|
||||
}
|
||||
});
|
||||
|
||||
/* Check that the header resides on a page which has not been
|
||||
freed yet */
|
||||
|
||||
ut_a(descr);
|
||||
ut_a(xdes_get_bit(descr, XDES_FREE_BIT,
|
||||
header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
|
||||
inode = fseg_inode_try_get(header, space, zip_size, mtr);
|
||||
@ -3663,11 +3648,11 @@ fseg_free_step_not_header(
|
||||
|
||||
inode = fseg_inode_get(header, space, zip_size, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !inode) {
|
||||
SRV_CORRUPT_TABLE_CHECK(inode,
|
||||
{
|
||||
/* ignore the corruption */
|
||||
return(TRUE);
|
||||
}
|
||||
ut_a(inode);
|
||||
});
|
||||
|
||||
descr = fseg_get_first_extent(inode, space, zip_size, mtr);
|
||||
|
||||
|
@ -202,6 +202,8 @@ static ulong innobase_sys_stats_root_page = 0;
|
||||
#endif
|
||||
static my_bool innobase_buffer_pool_shm_checksum = TRUE;
|
||||
static uint innobase_buffer_pool_shm_key = 0;
|
||||
static ulong srv_lazy_drop_table = 0;
|
||||
|
||||
|
||||
|
||||
static char* internal_innobase_data_file_path = NULL;
|
||||
@ -1910,7 +1912,7 @@ trx_is_started(
|
||||
/*===========*/
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
return(trx->conc_state != TRX_NOT_STARTED);
|
||||
return(trx->state != TRX_NOT_STARTED);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -3009,6 +3011,12 @@ innobase_change_buffering_inited_ok:
|
||||
"InnoDB: innodb_buffer_pool_shm_key was ignored.\n");
|
||||
}
|
||||
|
||||
if (srv_lazy_drop_table) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: "
|
||||
"innodb_lazy_drop_table is deprecated and ignored.\n");
|
||||
}
|
||||
|
||||
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
|
||||
|
||||
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
|
||||
@ -4599,7 +4607,8 @@ ha_innobase::open(
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table && share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
free_share(share);
|
||||
|
||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||
@ -4624,7 +4633,8 @@ retry:
|
||||
/* Get pointer to a table object in InnoDB dictionary cache */
|
||||
ib_table = dict_table_get(norm_name, TRUE);
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(ib_table && ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
free_share(share);
|
||||
my_free(upd_buf);
|
||||
upd_buf = NULL;
|
||||
@ -6692,7 +6702,8 @@ ha_innobase::index_read(
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
@ -6763,7 +6774,8 @@ ha_innobase::index_read(
|
||||
ret = DB_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
@ -6881,7 +6893,8 @@ ha_innobase::change_active_index(
|
||||
{
|
||||
DBUG_ENTER("change_active_index");
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
@ -6998,7 +7011,8 @@ ha_innobase::general_fetch(
|
||||
|
||||
DBUG_ENTER("general_fetch");
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
@ -7011,7 +7025,8 @@ ha_innobase::general_fetch(
|
||||
|
||||
innodb_srv_conc_exit_innodb(prebuilt->trx);
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
if (UNIV_UNLIKELY(share->ib_table->is_corrupt &&
|
||||
srv_pass_corrupt_table <= 1)) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
|
||||
@ -9039,7 +9054,7 @@ ha_innobase::info_low(
|
||||
|
||||
prebuilt->trx->op_info = "confirming rows of SYS_STATS to store statistics";
|
||||
|
||||
ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
|
||||
ut_a(!trx_is_started(prebuilt->trx));
|
||||
|
||||
for (index = dict_table_get_first_index(ib_table);
|
||||
index != NULL;
|
||||
@ -9052,7 +9067,7 @@ ha_innobase::info_low(
|
||||
innobase_commit_low(prebuilt->trx);
|
||||
}
|
||||
|
||||
ut_a(prebuilt->trx->conc_state == TRX_NOT_STARTED);
|
||||
ut_a(!trx_is_started(prebuilt->trx));
|
||||
}
|
||||
|
||||
prebuilt->trx->op_info = "updating table statistics";
|
||||
@ -13020,8 +13035,7 @@ static MYSQL_SYSVAR_ENUM(corrupt_table_action, srv_pass_corrupt_table,
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(lazy_drop_table, srv_lazy_drop_table,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"At deleting tablespace, only miminum needed processes at the time are done. "
|
||||
"e.g. for http://bugs.mysql.com/51325",
|
||||
"[Deprecated option] no effect",
|
||||
NULL, NULL, 0, 0, 1, 0);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(locking_fake_changes, srv_fake_changes_locks,
|
||||
|
@ -59,7 +59,7 @@ btr_block_get_func(
|
||||
block = buf_page_get_gen(space, zip_size, page_no, mode,
|
||||
NULL, BUF_GET, file, line, mtr);
|
||||
|
||||
ut_a(srv_pass_corrupt_table || block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, ; /* do nothing */);
|
||||
|
||||
if (block && mode != RW_NO_LATCH) {
|
||||
|
||||
|
@ -1587,7 +1587,6 @@ struct buf_page_struct{
|
||||
0 if the block was never accessed
|
||||
in the buffer pool. Protected by
|
||||
block mutex */
|
||||
ibool space_was_being_deleted;
|
||||
ibool is_corrupt;
|
||||
# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ibool file_page_was_freed;
|
||||
|
@ -430,7 +430,6 @@ buf_block_set_file_page(
|
||||
buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
|
||||
block->page.space = space;
|
||||
block->page.offset = page_no;
|
||||
block->page.space_was_being_deleted = FALSE;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -712,13 +711,7 @@ buf_block_get_frame(
|
||||
/*================*/
|
||||
const buf_block_t* block) /*!< in: pointer to the control block */
|
||||
{
|
||||
ut_a(srv_pass_corrupt_table || block);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
ut_ad(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
switch (buf_block_get_state(block)) {
|
||||
case BUF_BLOCK_ZIP_FREE:
|
||||
|
@ -70,7 +70,7 @@ buf_flush_note_modification(
|
||||
|
||||
ut_ad(!buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!buf_flush_list_mutex_own(buf_pool));
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
ut_ad(!mtr->made_dirty || log_flush_order_mutex_own());
|
||||
|
||||
ut_ad(mtr->start_lsn != 0);
|
||||
ut_ad(mtr->modifications);
|
||||
|
@ -73,13 +73,6 @@ buf_LRU_flush_or_remove_pages(
|
||||
enum buf_remove_t buf_remove);/*!< in: remove or flush
|
||||
strategy */
|
||||
|
||||
/******************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_mark_space_was_deleted(
|
||||
/*===========================*/
|
||||
ulint id); /*!< in: space id */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
|
@ -50,10 +50,7 @@ fut_get_ptr(
|
||||
|
||||
block = buf_page_get(space, zip_size, addr.page, rw_latch, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
return(0);
|
||||
}
|
||||
ut_a(block);
|
||||
SRV_CORRUPT_TABLE_CHECK(block, return(0););
|
||||
|
||||
ptr = buf_block_get_frame(block) + addr.boffset;
|
||||
|
||||
|
@ -122,16 +122,24 @@ UNIV_INLINE
|
||||
void
|
||||
log_free_check(void);
|
||||
/*================*/
|
||||
/************************************************************//**
|
||||
Opens the log for log_write_low. The log must be closed with log_close and
|
||||
released with log_release.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INTERN
|
||||
/**************************************************************************//**
|
||||
Locks the log mutex and opens the log for log_write_low. The log must be closed
|
||||
with log_close and released with log_release.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
log_reserve_and_open(
|
||||
/*=================*/
|
||||
ulint len); /*!< in: length of data to be catenated */
|
||||
/************************************************************//**
|
||||
Opens the log for log_write_low. The log must be closed with log_close.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INTERN
|
||||
ib_uint64_t
|
||||
log_open(
|
||||
/*=====*/
|
||||
ulint len); /*!< in: length of data to be catenated */
|
||||
/************************************************************//**
|
||||
Writes to the log the string given. It is assumed that the caller holds the
|
||||
log mutex. */
|
||||
UNIV_INTERN
|
||||
|
@ -332,10 +332,10 @@ log_reserve_and_write_fast(
|
||||
|
||||
if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
|
||||
|
||||
/* The string does not fit within the current log block
|
||||
or the log block would become full */
|
||||
|
||||
mutex_exit(&log_sys->mutex);
|
||||
/* The string does not fit within the current log block or the
|
||||
log block would become full. Do not release the log mutex,
|
||||
because it has to be reacquired immediately for the "slow" write
|
||||
procedure via log_write_low(). */
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -382,6 +382,21 @@ log_reserve_and_write_fast(
|
||||
return(log_sys->lsn);
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
Locks the log mutex and opens the log for log_write_low. The log must be closed
|
||||
with log_close and released with log_release.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
log_reserve_and_open(
|
||||
/*=================*/
|
||||
ulint len) /*!< in: length of data to be catenated */
|
||||
{
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
return log_open(len);
|
||||
}
|
||||
|
||||
/***********************************************************************//**
|
||||
Releases the log mutex. */
|
||||
UNIV_INLINE
|
||||
|
@ -375,6 +375,8 @@ struct mtr_struct{
|
||||
ibool modifications;
|
||||
/* TRUE if the mtr made modifications to
|
||||
buffer pool pages */
|
||||
ibool made_dirty;/*!< TRUE if mtr has made at least
|
||||
one buffer pool page dirty */
|
||||
ulint n_log_recs;
|
||||
/* count of how many page initial log records
|
||||
have been written to the mtr log */
|
||||
|
@ -29,6 +29,17 @@ Created 11/26/1995 Heikki Tuuri
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
#include "mach0data.h"
|
||||
|
||||
/***************************************************//**
|
||||
Checks if a mini-transaction is dirtying a clean page.
|
||||
@return TRUE if the mtr is dirtying a clean page. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mtr_block_dirtied(
|
||||
/*==============*/
|
||||
const buf_block_t* block) /*!< in: block being x-fixed */
|
||||
__attribute__((nonnull,warn_unused_result));
|
||||
|
||||
|
||||
/***************************************************************//**
|
||||
Starts a mini-transaction. */
|
||||
UNIV_INLINE
|
||||
@ -47,6 +58,7 @@ mtr_start(
|
||||
mtr->inside_ibuf = FALSE;
|
||||
mtr->n_log_recs = 0;
|
||||
mtr->n_freed_pages = 0;
|
||||
mtr->made_dirty = FALSE;
|
||||
|
||||
ut_d(mtr->state = MTR_ACTIVE);
|
||||
ut_d(mtr->magic_n = MTR_MAGIC_N);
|
||||
@ -65,6 +77,15 @@ mtr_memo_push(
|
||||
dyn_array_t* memo;
|
||||
mtr_memo_slot_t* slot;
|
||||
|
||||
/* If this mtr has x-fixed a clean page then we set
|
||||
the made_dirty flag. This tells us if we need to
|
||||
grab log_flush_order_mutex at mtr_commit so that we
|
||||
can insert the dirtied page to the flush list. */
|
||||
if (type == MTR_MEMO_PAGE_X_FIX && !mtr->made_dirty) {
|
||||
mtr->made_dirty =
|
||||
mtr_block_dirtied((const buf_block_t *)object);
|
||||
}
|
||||
|
||||
ut_ad(object);
|
||||
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
|
||||
ut_ad(type <= MTR_MEMO_X_LOCK);
|
||||
|
@ -32,6 +32,7 @@ Created 2/16/1997 Heikki Tuuri
|
||||
#include "ut0byte.h"
|
||||
#include "ut0lst.h"
|
||||
#include "trx0trx.h"
|
||||
#include "trx0sys.h"
|
||||
#include "read0types.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -44,8 +45,11 @@ read_view_open_now(
|
||||
/*===============*/
|
||||
trx_id_t cr_trx_id, /*!< in: trx_id of creating
|
||||
transaction, or 0 used in purge */
|
||||
mem_heap_t* heap); /*!< in: memory heap from which
|
||||
allocated */
|
||||
read_view_t* view, /*!< in: current read view or NULL if it
|
||||
doesn't exist yet */
|
||||
ibool exclude_self); /*!< in: TRUE, if cr_trx_id should be
|
||||
excluded from the resulting view */
|
||||
|
||||
/*********************************************************************//**
|
||||
Makes a copy of the oldest existing read view, or opens a new. The view
|
||||
must be closed with ..._close.
|
||||
@ -56,8 +60,8 @@ read_view_oldest_copy_or_open_new(
|
||||
/*==============================*/
|
||||
trx_id_t cr_trx_id, /*!< in: trx_id of creating
|
||||
transaction, or 0 used in purge */
|
||||
mem_heap_t* heap); /*!< in: memory heap from which
|
||||
allocated */
|
||||
read_view_t* view); /*!< in: pre-allocated view array or
|
||||
NULL if a new one needs to be created */
|
||||
/*********************************************************************//**
|
||||
Closes a read view. */
|
||||
UNIV_INTERN
|
||||
@ -66,6 +70,13 @@ read_view_close(
|
||||
/*============*/
|
||||
read_view_t* view); /*!< in: read view */
|
||||
/*********************************************************************//**
|
||||
Frees memory allocated by a read view. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
read_view_free(
|
||||
/*===========*/
|
||||
read_view_t* view); /*< in: read view */
|
||||
/*********************************************************************//**
|
||||
Closes a consistent read view for MySQL. This function is called at an SQL
|
||||
statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
|
||||
UNIV_INTERN
|
||||
@ -143,16 +154,20 @@ struct read_view_struct{
|
||||
are strictly smaller (<) than this value.
|
||||
In other words,
|
||||
this is the "low water mark". */
|
||||
ulint n_trx_ids;
|
||||
ulint n_descr;
|
||||
/*!< Number of cells in the trx_ids array */
|
||||
trx_id_t* trx_ids;/*!< Additional trx ids which the read should
|
||||
not see: typically, these are the active
|
||||
ulint max_descr;
|
||||
/*!< Maximum number of cells in the trx_ids
|
||||
array */
|
||||
trx_id_t* descriptors;
|
||||
/*!< Array of trx descriptors which the read
|
||||
should not see: typically, these are the active
|
||||
transactions at the time when the read is
|
||||
serialized, except the reading transaction
|
||||
itself; the trx ids in this array are in a
|
||||
descending order. These trx_ids should be
|
||||
between the "low" and "high" water marks,
|
||||
that is, up_limit_id and low_limit_id. */
|
||||
between the "low" and "high" water marks, that
|
||||
is, up_limit_id and low_limit_id. */
|
||||
trx_id_t creator_trx_id;
|
||||
/*!< trx id of creating transaction, or
|
||||
0 used in purge */
|
||||
|
@ -25,6 +25,11 @@ Created 2/16/1997 Heikki Tuuri
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the nth trx id in a read view.
|
||||
|
||||
Upstream code stores array of trx_ids in the descending order. Percona Server
|
||||
keeps it in the ascending order for performance reasons. Let us keep the
|
||||
semantics.
|
||||
|
||||
@return trx id */
|
||||
UNIV_INLINE
|
||||
trx_id_t
|
||||
@ -33,13 +38,17 @@ read_view_get_nth_trx_id(
|
||||
const read_view_t* view, /*!< in: read view */
|
||||
ulint n) /*!< in: position */
|
||||
{
|
||||
ut_ad(n < view->n_trx_ids);
|
||||
ut_ad(n < view->n_descr);
|
||||
|
||||
return(*(view->trx_ids + n));
|
||||
return(view->descriptors[view->n_descr - 1 - n]);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Sets the nth trx id in a read view. */
|
||||
Sets the nth trx id in a read view.
|
||||
|
||||
Upstream code stores array of trx_ids in the descending order. Percona Server
|
||||
keeps it in the ascending order for performance reasons. Let us keep the
|
||||
semantics. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
read_view_set_nth_trx_id(
|
||||
@ -48,9 +57,9 @@ read_view_set_nth_trx_id(
|
||||
ulint n, /*!< in: position */
|
||||
trx_id_t trx_id) /*!< in: trx id to set */
|
||||
{
|
||||
ut_ad(n < view->n_trx_ids);
|
||||
ut_ad(n < view->n_descr);
|
||||
|
||||
*(view->trx_ids + n) = trx_id;
|
||||
view->descriptors[view->n_descr - 1 - n] = trx_id;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -63,9 +72,6 @@ read_view_sees_trx_id(
|
||||
const read_view_t* view, /*!< in: read view */
|
||||
trx_id_t trx_id) /*!< in: trx id */
|
||||
{
|
||||
ulint n_ids;
|
||||
ulint i;
|
||||
|
||||
if (trx_id < view->up_limit_id) {
|
||||
|
||||
return(TRUE);
|
||||
@ -76,21 +82,8 @@ read_view_sees_trx_id(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* We go through the trx ids in the array smallest first: this order
|
||||
may save CPU time, because if there was a very long running
|
||||
transaction in the trx id array, its trx id is looked at first, and
|
||||
the first two comparisons may well decide the visibility of trx_id. */
|
||||
/* Do a binary search over this view's descriptors array */
|
||||
|
||||
n_ids = view->n_trx_ids;
|
||||
|
||||
for (i = 0; i < n_ids; i++) {
|
||||
trx_id_t view_trx_id
|
||||
= read_view_get_nth_trx_id(view, n_ids - i - 1);
|
||||
|
||||
if (trx_id <= view_trx_id) {
|
||||
return(trx_id != view_trx_id);
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
return(trx_find_descriptor(view->descriptors, view->n_descr,
|
||||
trx_id) == NULL);
|
||||
}
|
||||
|
@ -266,9 +266,22 @@ extern ulint srv_adaptive_flushing_method;
|
||||
extern ulint srv_expand_import;
|
||||
extern ulint srv_pass_corrupt_table;
|
||||
|
||||
extern ulint srv_dict_size_limit;
|
||||
/* Helper macro to support srv_pass_corrupt_table checks. If 'cond' is FALSE,
|
||||
execute 'code' if srv_pass_corrupt_table is non-zero, or trigger a fatal error
|
||||
otherwise. The break statement in 'code' will obviously not work as expected. */
|
||||
|
||||
extern ulint srv_lazy_drop_table;
|
||||
#define SRV_CORRUPT_TABLE_CHECK(cond,code) \
|
||||
do { \
|
||||
if (UNIV_UNLIKELY(!(cond))) { \
|
||||
if (srv_pass_corrupt_table) { \
|
||||
code \
|
||||
} else { \
|
||||
ut_error; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
extern ulint srv_dict_size_limit;
|
||||
/*-------------------------------------------*/
|
||||
|
||||
extern ulint srv_n_rows_inserted;
|
||||
|
@ -143,6 +143,7 @@ struct trx_purge_struct{
|
||||
obtaining an s-latch here. */
|
||||
read_view_t* view; /*!< The purge will not remove undo logs
|
||||
which are >= this view (purge view) */
|
||||
read_view_t* prebuilt_view; /*!< Pre-built view array */
|
||||
ulonglong n_pages_handled;/*!< Approximate number of undo log
|
||||
pages processed in purge */
|
||||
ulonglong handle_limit; /*!< Target of how many pages to get
|
||||
|
@ -249,6 +249,17 @@ trx_id_t
|
||||
trx_sys_get_new_trx_id(void);
|
||||
/*========================*/
|
||||
|
||||
/*************************************************************//**
|
||||
Find a slot for a given trx ID in a descriptors array.
|
||||
@return: slot pointer */
|
||||
UNIV_INLINE
|
||||
trx_id_t*
|
||||
trx_find_descriptor(
|
||||
/*================*/
|
||||
const trx_id_t* descriptors, /*!< in: descriptors array */
|
||||
ulint n_descr, /*!< in: array size */
|
||||
trx_id_t trx_id); /*!< in: trx pointer */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Flag to control TRX_RSEG_N_SLOTS behavior debugging. */
|
||||
extern uint trx_rseg_n_slots_debug;
|
||||
@ -633,6 +644,8 @@ identifier is added to this 64-bit constant. */
|
||||
| TRX_SYS_FILE_FORMAT_TAG_MAGIC_N_LOW)
|
||||
/* @} */
|
||||
|
||||
#define TRX_DESCR_ARRAY_INITIAL_SIZE 1000
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Doublewrite control struct */
|
||||
struct trx_doublewrite_struct{
|
||||
@ -660,16 +673,41 @@ struct trx_sys_struct{
|
||||
trx_id_t max_trx_id; /*!< The smallest number not yet
|
||||
assigned as a transaction id or
|
||||
transaction number */
|
||||
char pad1[64]; /*!< Ensure max_trx_id does not share
|
||||
cache line with other fields. */
|
||||
trx_id_t* descriptors; /*!< Array of trx descriptors */
|
||||
ulint descr_n_max; /*!< The current size of the descriptors
|
||||
array. */
|
||||
char pad2[64]; /*!< Ensure static descriptor fields
|
||||
do not share cache lines with
|
||||
descr_n_used */
|
||||
ulint descr_n_used; /*!< Number of used elements in the
|
||||
descriptors array. */
|
||||
char pad3[64]; /*!< Ensure descriptors do not share
|
||||
cache line with other fields */
|
||||
UT_LIST_BASE_NODE_T(trx_t) trx_list;
|
||||
/*!< List of active and committed in
|
||||
memory transactions, sorted on trx id,
|
||||
biggest first */
|
||||
char pad4[64]; /*!< Ensure list base nodes do not
|
||||
share cache line with other fields */
|
||||
UT_LIST_BASE_NODE_T(trx_t) mysql_trx_list;
|
||||
/*!< List of transactions created
|
||||
for MySQL */
|
||||
char pad5[64]; /*!< Ensure list base nodes do not
|
||||
share cache line with other fields */
|
||||
UT_LIST_BASE_NODE_T(trx_t) trx_serial_list;
|
||||
/*!< trx->no ordered List of
|
||||
transactions in either TRX_PREPARED or
|
||||
TRX_ACTIVE which have already been
|
||||
assigned a serialization number */
|
||||
char pad6[64]; /*!< Ensure trx_serial_list does not
|
||||
share cache line with other fields */
|
||||
UT_LIST_BASE_NODE_T(trx_rseg_t) rseg_list;
|
||||
/*!< List of rollback segment
|
||||
objects */
|
||||
char pad7[64]; /*!< Ensure list base nodes do not
|
||||
share cache line with other fields */
|
||||
trx_rseg_t* latest_rseg; /*!< Latest rollback segment in the
|
||||
round-robin assignment of rollback
|
||||
segments to transactions */
|
||||
|
@ -367,28 +367,11 @@ trx_is_active(
|
||||
/*==========*/
|
||||
trx_id_t trx_id) /*!< in: trx id of the transaction */
|
||||
{
|
||||
trx_t* trx;
|
||||
|
||||
ut_ad(mutex_own(&(kernel_mutex)));
|
||||
|
||||
if (trx_id < trx_list_get_min_trx_id()) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
|
||||
|
||||
/* There must be corruption: we return TRUE because this
|
||||
function is only called by lock_clust_rec_some_has_impl()
|
||||
and row_vers_impl_x_locked_off_kernel() and they have
|
||||
diagnostic prints in this case */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
trx = trx_get_on_id(trx_id);
|
||||
if (trx && (trx->conc_state == TRX_ACTIVE
|
||||
|| trx->conc_state == TRX_PREPARED)) {
|
||||
if (trx_find_descriptor(trx_sys->descriptors,
|
||||
trx_sys->descr_n_used,
|
||||
trx_id)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
@ -425,4 +408,27 @@ trx_sys_get_new_trx_id(void)
|
||||
return(id);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************//**
|
||||
Find a slot for a given trx ID in a descriptors array.
|
||||
@return: slot pointer */
|
||||
UNIV_INLINE
|
||||
trx_id_t*
|
||||
trx_find_descriptor(
|
||||
/*================*/
|
||||
const trx_id_t* descriptors, /*!< in: descriptors array */
|
||||
ulint n_descr, /*!< in: array size */
|
||||
trx_id_t trx_id) /*!< in: trx pointer */
|
||||
{
|
||||
ut_ad(descriptors != trx_sys->descriptors ||
|
||||
mutex_own(&kernel_mutex));
|
||||
|
||||
if (UNIV_UNLIKELY(n_descr == 0)) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return((trx_id_t *) bsearch(&trx_id, descriptors, n_descr,
|
||||
sizeof(trx_id_t), trx_descr_cmp));
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
@ -447,6 +447,23 @@ trx_get_que_state_str(
|
||||
/*==================*/
|
||||
const trx_t* trx); /*!< in: transaction */
|
||||
|
||||
/*************************************************************//**
|
||||
Callback function for trx_find_descriptor() to compare trx IDs. */
|
||||
UNIV_INTERN
|
||||
int
|
||||
trx_descr_cmp(
|
||||
/*==========*/
|
||||
const void *a, /*!< in: pointer to first comparison argument */
|
||||
const void *b); /*!< in: pointer to second comparison argument */
|
||||
|
||||
/*************************************************************//**
|
||||
Release a slot for a given trx in the global descriptors array. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_release_descriptor(
|
||||
/*===================*/
|
||||
trx_t* trx); /*!< in: trx pointer */
|
||||
|
||||
/* Signal to a transaction */
|
||||
struct trx_sig_struct{
|
||||
unsigned type:3; /*!< signal type */
|
||||
@ -477,10 +494,18 @@ struct trx_struct{
|
||||
const char* op_info; /*!< English text describing the
|
||||
current operation, or an empty
|
||||
string */
|
||||
ulint conc_state; /*!< state of the trx from the point
|
||||
of view of concurrency control:
|
||||
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
|
||||
... */
|
||||
ulint state; /*!< state of the trx from the point of
|
||||
view of concurrency control: TRX_ACTIVE,
|
||||
TRX_COMMITTED_IN_MEMORY, ... This was
|
||||
called 'conc_state' in the upstream and
|
||||
has been renamed in Percona Server,
|
||||
because changing it's value to/from
|
||||
either TRX_ACTIVE or TRX_PREPARED
|
||||
requires calling
|
||||
trx_reserve_descriptor() /
|
||||
trx_release_descriptor(). Different name
|
||||
ensures we notice any new code changing
|
||||
the state. */
|
||||
/*------------------------------*/
|
||||
/* MySQL has a transaction coordinator to coordinate two phase
|
||||
commit between multiple storage engines and the binary log. When
|
||||
@ -495,6 +520,9 @@ struct trx_struct{
|
||||
also be set to 1. This is used in the
|
||||
XA code */
|
||||
unsigned called_commit_ordered:1;/* 1 if innobase_commit_ordered has run. */
|
||||
unsigned is_in_trx_serial_list:1;
|
||||
/* Set when transaction is in the
|
||||
trx_serial_list */
|
||||
/*------------------------------*/
|
||||
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
|
||||
ulint check_foreigns; /* normally TRUE, but if the user
|
||||
@ -628,6 +656,9 @@ struct trx_struct{
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
mysql_trx_list; /*!< list of transactions created for
|
||||
MySQL */
|
||||
UT_LIST_NODE_T(trx_t)
|
||||
trx_serial_list;/*!< list node for
|
||||
trx_sys->trx_serial_list */
|
||||
/*------------------------------*/
|
||||
ulint error_state; /*!< 0 if no error, otherwise error
|
||||
number; NOTE That ONLY the thread
|
||||
@ -686,9 +717,6 @@ struct trx_struct{
|
||||
UT_LIST_BASE_NODE_T(lock_t)
|
||||
trx_locks; /*!< locks reserved by the transaction */
|
||||
/*------------------------------*/
|
||||
mem_heap_t* global_read_view_heap;
|
||||
/* memory heap for the global read
|
||||
view */
|
||||
read_view_t* global_read_view;
|
||||
/* consistent read view associated
|
||||
to a transaction or NULL */
|
||||
@ -698,6 +726,7 @@ struct trx_struct{
|
||||
associated to a transaction (i.e.
|
||||
same as global_read_view) or read view
|
||||
associated to a cursor */
|
||||
read_view_t* prebuilt_view; /* pre-built view array */
|
||||
/*------------------------------*/
|
||||
UT_LIST_BASE_NODE_T(trx_named_savept_t)
|
||||
trx_savepoints; /*!< savepoints set with SAVEPOINT ...,
|
||||
|
@ -31,9 +31,9 @@ trx_start_if_not_started(
|
||||
/*=====================*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY);
|
||||
ut_ad(trx->state != TRX_COMMITTED_IN_MEMORY);
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
|
||||
trx_start(trx, ULINT_UNDEFINED);
|
||||
}
|
||||
@ -48,9 +48,9 @@ trx_start_if_not_started_low(
|
||||
/*=========================*/
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
ut_ad(trx->conc_state != TRX_COMMITTED_IN_MEMORY);
|
||||
ut_ad(trx->state != TRX_COMMITTED_IN_MEMORY);
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
|
||||
trx_start_low(trx, ULINT_UNDEFINED);
|
||||
}
|
||||
|
@ -4652,7 +4652,7 @@ lock_print_info_all_transactions(
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
|
||||
|
||||
while (trx) {
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
fputs("---", file);
|
||||
trx_print(file, trx, 600);
|
||||
}
|
||||
@ -4820,9 +4820,9 @@ lock_table_queue_validate(
|
||||
lock = UT_LIST_GET_FIRST(table->locks);
|
||||
|
||||
while (lock) {
|
||||
ut_a(((lock->trx)->conc_state == TRX_ACTIVE)
|
||||
|| ((lock->trx)->conc_state == TRX_PREPARED)
|
||||
|| ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY));
|
||||
ut_a(((lock->trx)->state == TRX_ACTIVE)
|
||||
|| ((lock->trx)->state == TRX_PREPARED)
|
||||
|| ((lock->trx)->state == TRX_COMMITTED_IN_MEMORY));
|
||||
|
||||
if (!lock_get_wait(lock)) {
|
||||
|
||||
@ -4870,7 +4870,7 @@ lock_rec_queue_validate(
|
||||
lock = lock_rec_get_first(block, heap_no);
|
||||
|
||||
while (lock) {
|
||||
switch(lock->trx->conc_state) {
|
||||
switch(lock->trx->state) {
|
||||
case TRX_ACTIVE:
|
||||
case TRX_PREPARED:
|
||||
case TRX_COMMITTED_IN_MEMORY:
|
||||
@ -4957,9 +4957,9 @@ lock_rec_queue_validate(
|
||||
lock = lock_rec_get_first(block, heap_no);
|
||||
|
||||
while (lock) {
|
||||
ut_a(lock->trx->conc_state == TRX_ACTIVE
|
||||
|| lock->trx->conc_state == TRX_PREPARED
|
||||
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
||||
ut_a(lock->trx->state == TRX_ACTIVE
|
||||
|| lock->trx->state == TRX_PREPARED
|
||||
|| lock->trx->state == TRX_COMMITTED_IN_MEMORY);
|
||||
ut_a(trx_in_trx_list(lock->trx));
|
||||
|
||||
if (index) {
|
||||
@ -5036,9 +5036,9 @@ loop:
|
||||
}
|
||||
|
||||
ut_a(trx_in_trx_list(lock->trx));
|
||||
ut_a(lock->trx->conc_state == TRX_ACTIVE
|
||||
|| lock->trx->conc_state == TRX_PREPARED
|
||||
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
|
||||
ut_a(lock->trx->state == TRX_ACTIVE
|
||||
|| lock->trx->state == TRX_PREPARED
|
||||
|| lock->trx->state == TRX_COMMITTED_IN_MEMORY);
|
||||
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
/* Only validate the record queues when this thread is not
|
||||
|
@ -263,13 +263,12 @@ log_check_tracking_margin(
|
||||
}
|
||||
|
||||
/************************************************************//**
|
||||
Opens the log for log_write_low. The log must be closed with log_close and
|
||||
released with log_release.
|
||||
Opens the log for log_write_low. The log must be closed with log_close.
|
||||
@return start lsn of the log record */
|
||||
UNIV_INTERN
|
||||
ib_uint64_t
|
||||
log_reserve_and_open(
|
||||
/*=================*/
|
||||
log_open(
|
||||
/*=====*/
|
||||
ulint len) /*!< in: length of data to be catenated */
|
||||
{
|
||||
log_t* log = log_sys;
|
||||
@ -282,7 +281,6 @@ log_reserve_and_open(
|
||||
|
||||
ut_a(len < log->buf_size / 2);
|
||||
loop:
|
||||
mutex_enter(&(log->mutex));
|
||||
ut_ad(!recv_no_log_write);
|
||||
|
||||
/* Calculate an upper limit for the space the string may take in the
|
||||
@ -303,6 +301,8 @@ loop:
|
||||
|
||||
ut_ad(++count < 50);
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
@ -316,6 +316,8 @@ loop:
|
||||
|
||||
os_thread_sleep(10000);
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
@ -336,6 +338,8 @@ loop:
|
||||
|
||||
ut_ad(++count < 50);
|
||||
|
||||
mutex_enter(&(log->mutex));
|
||||
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
@ -492,9 +496,12 @@ log_close(void)
|
||||
|
||||
if (tracked_lsn_age >= log->log_group_capacity) {
|
||||
|
||||
fprintf(stderr, " InnoDB: Error: the age of the "
|
||||
fprintf(stderr, "InnoDB: Error: the age of the "
|
||||
"oldest untracked record exceeds the log "
|
||||
"group capacity!\n");
|
||||
fprintf(stderr, "InnoDB: Error: stopping the log "
|
||||
"tracking thread at LSN %llu\n", tracked_lsn);
|
||||
srv_track_changed_pages = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,25 @@ Created 11/26/1995 Heikki Tuuri
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "log0recv.h"
|
||||
|
||||
/***************************************************//**
|
||||
Checks if a mini-transaction is dirtying a clean page.
|
||||
@return TRUE if the mtr is dirtying a clean page. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
mtr_block_dirtied(
|
||||
/*==============*/
|
||||
const buf_block_t* block) /*!< in: block being x-fixed */
|
||||
{
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count > 0);
|
||||
|
||||
/* It is OK to read oldest_modification because no
|
||||
other thread can be performing a write of it and it
|
||||
is only during write that the value is reset to 0. */
|
||||
return(block->page.oldest_modification == 0);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Releases the item in the slot given. */
|
||||
static
|
||||
@ -125,7 +144,7 @@ mtr_memo_slot_note_modification(
|
||||
buf_block_t* block = (buf_block_t*) slot->object;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
ut_ad(!mtr->made_dirty || log_flush_order_mutex_own());
|
||||
#endif /* UNIV_DEBUG */
|
||||
buf_flush_note_modification(block, mtr);
|
||||
}
|
||||
@ -201,12 +220,14 @@ mtr_log_reserve_and_write(
|
||||
Add pages to flush list and exit */
|
||||
goto func_exit;
|
||||
}
|
||||
} else {
|
||||
mutex_enter(&log_sys->mutex);
|
||||
}
|
||||
|
||||
data_size = dyn_array_get_data_size(mlog);
|
||||
|
||||
/* Open the database log for log_write_low */
|
||||
mtr->start_lsn = log_reserve_and_open(data_size);
|
||||
mtr->start_lsn = log_open(data_size);
|
||||
|
||||
if (mtr->log_mode == MTR_LOG_ALL) {
|
||||
|
||||
@ -225,7 +246,15 @@ mtr_log_reserve_and_write(
|
||||
mtr->end_lsn = log_close();
|
||||
|
||||
func_exit:
|
||||
log_flush_order_mutex_enter();
|
||||
|
||||
/* No need to acquire log_flush_order_mutex if this mtr has
|
||||
not dirtied a clean page. log_flush_order_mutex is used to
|
||||
ensure ordered insertions in the flush_list. We need to
|
||||
insert in the flush_list iff the page in question was clean
|
||||
before modifications. */
|
||||
if (mtr->made_dirty) {
|
||||
log_flush_order_mutex_enter();
|
||||
}
|
||||
|
||||
/* It is now safe to release the log mutex because the
|
||||
flush_order mutex will ensure that we are the first one
|
||||
@ -236,7 +265,9 @@ func_exit:
|
||||
mtr_memo_note_modifications(mtr);
|
||||
}
|
||||
|
||||
log_flush_order_mutex_exit();
|
||||
if (mtr->made_dirty) {
|
||||
log_flush_order_mutex_exit();
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
198
read/read0read.c
198
read/read0read.c
@ -145,14 +145,27 @@ read_view_t*
|
||||
read_view_create_low(
|
||||
/*=================*/
|
||||
ulint n, /*!< in: number of cells in the trx_ids array */
|
||||
mem_heap_t* heap) /*!< in: memory heap from which allocated */
|
||||
read_view_t* view) /*!< in: pre-allocated view array or NULL if a
|
||||
new one needs to be created */
|
||||
{
|
||||
read_view_t* view;
|
||||
if (view == NULL) {
|
||||
view = ut_malloc(sizeof(read_view_t));
|
||||
view->max_descr = 0;
|
||||
view->descriptors = NULL;
|
||||
}
|
||||
|
||||
view = mem_heap_alloc(heap, sizeof(read_view_t));
|
||||
if (UNIV_UNLIKELY(view->max_descr < n)) {
|
||||
|
||||
view->n_trx_ids = n;
|
||||
view->trx_ids = mem_heap_alloc(heap, n * sizeof *view->trx_ids);
|
||||
/* avoid frequent re-allocations by extending the array to the
|
||||
desired size + 10% */
|
||||
|
||||
view->max_descr = n + n / 10;
|
||||
view->descriptors = ut_realloc(view->descriptors,
|
||||
view->max_descr *
|
||||
sizeof(trx_id_t));
|
||||
}
|
||||
|
||||
view->n_descr = n;
|
||||
|
||||
return(view);
|
||||
}
|
||||
@ -169,8 +182,8 @@ read_view_oldest_copy_or_open_new(
|
||||
/*==============================*/
|
||||
trx_id_t cr_trx_id, /*!< in: trx_id of creating
|
||||
transaction, or 0 used in purge */
|
||||
mem_heap_t* heap) /*!< in: memory heap from which
|
||||
allocated */
|
||||
read_view_t* view) /*!< in: pre-allocated view array or
|
||||
NULL if a new one needs to be created */
|
||||
{
|
||||
read_view_t* old_view;
|
||||
read_view_t* view_copy;
|
||||
@ -185,10 +198,10 @@ read_view_oldest_copy_or_open_new(
|
||||
|
||||
if (old_view == NULL) {
|
||||
|
||||
return(read_view_open_now(cr_trx_id, heap));
|
||||
return(read_view_open_now(cr_trx_id, view, TRUE));
|
||||
}
|
||||
|
||||
n = old_view->n_trx_ids;
|
||||
n = old_view->n_descr;
|
||||
|
||||
if (old_view->creator_trx_id) {
|
||||
n++;
|
||||
@ -196,7 +209,7 @@ read_view_oldest_copy_or_open_new(
|
||||
needs_insert = FALSE;
|
||||
}
|
||||
|
||||
view_copy = read_view_create_low(n, heap);
|
||||
view_copy = read_view_create_low(n, view);
|
||||
|
||||
/* Insert the id of the creator in the right place of the descending
|
||||
array of ids, if needs_insert is TRUE: */
|
||||
@ -204,7 +217,7 @@ read_view_oldest_copy_or_open_new(
|
||||
i = 0;
|
||||
while (i < n) {
|
||||
if (needs_insert
|
||||
&& (i >= old_view->n_trx_ids
|
||||
&& (i >= old_view->n_descr
|
||||
|| old_view->creator_trx_id
|
||||
> read_view_get_nth_trx_id(old_view, i))) {
|
||||
|
||||
@ -251,16 +264,17 @@ read_view_open_now(
|
||||
/*===============*/
|
||||
trx_id_t cr_trx_id, /*!< in: trx_id of creating
|
||||
transaction, or 0 used in purge */
|
||||
mem_heap_t* heap) /*!< in: memory heap from which
|
||||
allocated */
|
||||
read_view_t* view, /*!< in: current read view or NULL if it
|
||||
doesn't exist yet */
|
||||
ibool exclude_self) /*!< in: TRUE, if cr_trx_id should be
|
||||
excluded from the resulting view */
|
||||
{
|
||||
read_view_t* view;
|
||||
trx_t* trx;
|
||||
ulint n;
|
||||
trx_id_t* descr;
|
||||
ulint i;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
view = read_view_create_low(UT_LIST_GET_LEN(trx_sys->trx_list), heap);
|
||||
view = read_view_create_low(trx_sys->descr_n_used, view);
|
||||
|
||||
view->creator_trx_id = cr_trx_id;
|
||||
view->type = VIEW_NORMAL;
|
||||
@ -271,40 +285,58 @@ read_view_open_now(
|
||||
view->low_limit_no = trx_sys->max_trx_id;
|
||||
view->low_limit_id = view->low_limit_no;
|
||||
|
||||
n = 0;
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||
/* No active transaction should be visible */
|
||||
|
||||
/* No active transaction should be visible, except cr_trx */
|
||||
descr = trx_find_descriptor(trx_sys->descriptors,
|
||||
trx_sys->descr_n_used,
|
||||
cr_trx_id);
|
||||
|
||||
while (trx) {
|
||||
if (trx->id != cr_trx_id
|
||||
&& (trx->conc_state == TRX_ACTIVE
|
||||
|| trx->conc_state == TRX_PREPARED)) {
|
||||
if (UNIV_LIKELY(exclude_self && descr != NULL)) {
|
||||
|
||||
read_view_set_nth_trx_id(view, n, trx->id);
|
||||
ut_ad(trx_sys->descr_n_used > 0);
|
||||
ut_ad(view->n_descr > 0);
|
||||
|
||||
n++;
|
||||
view->n_descr--;
|
||||
|
||||
/* NOTE that a transaction whose trx number is <
|
||||
trx_sys->max_trx_id can still be active, if it is
|
||||
in the middle of its commit! Note that when a
|
||||
transaction starts, we initialize trx->no to
|
||||
IB_ULONGLONG_MAX. */
|
||||
|
||||
if (view->low_limit_no > trx->no) {
|
||||
|
||||
view->low_limit_no = trx->no;
|
||||
}
|
||||
}
|
||||
|
||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
||||
i = descr - trx_sys->descriptors;
|
||||
} else {
|
||||
i = trx_sys->descr_n_used;
|
||||
}
|
||||
|
||||
view->n_trx_ids = n;
|
||||
if (UNIV_LIKELY(i > 0)) {
|
||||
|
||||
if (n > 0) {
|
||||
/* Copy the [0; i-1] range */
|
||||
memcpy(view->descriptors, trx_sys->descriptors,
|
||||
i * sizeof(trx_id_t));
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(i + 1 < trx_sys->descr_n_used)) {
|
||||
|
||||
/* Copy the [i+1; descr_n_used-1] range */
|
||||
memcpy(view->descriptors + i,
|
||||
trx_sys->descriptors + i + 1,
|
||||
(trx_sys->descr_n_used - i - 1) *
|
||||
sizeof(trx_id_t));
|
||||
}
|
||||
|
||||
/* NOTE that a transaction whose trx number is < trx_sys->max_trx_id can
|
||||
still be active, if it is in the middle of its commit! Note that when a
|
||||
transaction starts, we initialize trx->no to IB_ULONGLONG_MAX. */
|
||||
|
||||
if (UT_LIST_GET_LEN(trx_sys->trx_serial_list) > 0) {
|
||||
|
||||
trx_id_t trx_no;
|
||||
|
||||
trx_no = UT_LIST_GET_FIRST(trx_sys->trx_serial_list)->no;
|
||||
|
||||
if (trx_no < view->low_limit_no) {
|
||||
view->low_limit_no = trx_no;
|
||||
}
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY(view->n_descr > 0)) {
|
||||
/* The last active transaction has the smallest id: */
|
||||
view->up_limit_id = read_view_get_nth_trx_id(view, n - 1);
|
||||
view->up_limit_id = view->descriptors[0];
|
||||
} else {
|
||||
view->up_limit_id = view->low_limit_id;
|
||||
}
|
||||
@ -328,6 +360,23 @@ read_view_close(
|
||||
UT_LIST_REMOVE(view_list, trx_sys->view_list, view);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Frees resource allocated by a read view. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
read_view_free(
|
||||
/*===========*/
|
||||
read_view_t* view) /*< in: read view */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (view->descriptors != NULL) {
|
||||
ut_free(view->descriptors);
|
||||
}
|
||||
|
||||
ut_free(view);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Closes a consistent read view for MySQL. This function is called at an SQL
|
||||
statement end if the trx isolation level is <= TRX_ISO_READ_COMMITTED. */
|
||||
@ -343,8 +392,6 @@ read_view_close_for_mysql(
|
||||
|
||||
read_view_close(trx->global_read_view);
|
||||
|
||||
mem_heap_empty(trx->global_read_view_heap);
|
||||
|
||||
trx->read_view = NULL;
|
||||
trx->global_read_view = NULL;
|
||||
|
||||
@ -382,7 +429,7 @@ read_view_print(
|
||||
|
||||
fprintf(file, "Read view individually stored trx ids:\n");
|
||||
|
||||
n_ids = view->n_trx_ids;
|
||||
n_ids = view->n_descr;
|
||||
|
||||
for (i = 0; i < n_ids; i++) {
|
||||
fprintf(file, "Read view trx id " TRX_ID_FMT "\n",
|
||||
@ -404,8 +451,6 @@ read_cursor_view_create_for_mysql(
|
||||
cursor_view_t* curview;
|
||||
read_view_t* view;
|
||||
mem_heap_t* heap;
|
||||
trx_t* trx;
|
||||
ulint n;
|
||||
|
||||
ut_a(cr_trx);
|
||||
|
||||
@ -424,61 +469,14 @@ read_cursor_view_create_for_mysql(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
curview->read_view = read_view_create_low(
|
||||
UT_LIST_GET_LEN(trx_sys->trx_list), curview->heap);
|
||||
|
||||
view = curview->read_view;
|
||||
view->creator_trx_id = cr_trx->id;
|
||||
view->type = VIEW_HIGH_GRANULARITY;
|
||||
view->undo_no = cr_trx->undo_no;
|
||||
|
||||
/* No future transactions should be visible in the view */
|
||||
|
||||
view->low_limit_no = trx_sys->max_trx_id;
|
||||
view->low_limit_id = view->low_limit_no;
|
||||
|
||||
n = 0;
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||
|
||||
/* No active transaction should be visible */
|
||||
|
||||
while (trx) {
|
||||
|
||||
if (trx->conc_state == TRX_ACTIVE
|
||||
|| trx->conc_state == TRX_PREPARED) {
|
||||
|
||||
read_view_set_nth_trx_id(view, n, trx->id);
|
||||
|
||||
n++;
|
||||
|
||||
/* NOTE that a transaction whose trx number is <
|
||||
trx_sys->max_trx_id can still be active, if it is
|
||||
in the middle of its commit! Note that when a
|
||||
transaction starts, we initialize trx->no to
|
||||
IB_ULONGLONG_MAX. */
|
||||
|
||||
if (view->low_limit_no > trx->no) {
|
||||
|
||||
view->low_limit_no = trx->no;
|
||||
}
|
||||
}
|
||||
|
||||
trx = UT_LIST_GET_NEXT(trx_list, trx);
|
||||
}
|
||||
|
||||
view->n_trx_ids = n;
|
||||
|
||||
if (n > 0) {
|
||||
/* The last active transaction has the smallest id: */
|
||||
view->up_limit_id = read_view_get_nth_trx_id(view, n - 1);
|
||||
} else {
|
||||
view->up_limit_id = view->low_limit_id;
|
||||
}
|
||||
|
||||
UT_LIST_ADD_FIRST(view_list, trx_sys->view_list, view);
|
||||
curview->read_view = read_view_open_now(cr_trx->id, NULL, FALSE);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
view = curview->read_view;
|
||||
view->type = VIEW_HIGH_GRANULARITY;
|
||||
view->undo_no = cr_trx->undo_no;
|
||||
|
||||
return(curview);
|
||||
}
|
||||
|
||||
@ -503,6 +501,8 @@ read_cursor_view_close_for_mysql(
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
read_view_close(curview->read_view);
|
||||
read_view_free(curview->read_view);
|
||||
|
||||
trx->read_view = trx->global_read_view;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
@ -1346,11 +1346,11 @@ run_again:
|
||||
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
||||
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
||||
|
||||
if (srv_pass_corrupt_table && !block) {
|
||||
SRV_CORRUPT_TABLE_CHECK(block,
|
||||
{
|
||||
err = DB_CORRUPTION;
|
||||
break;
|
||||
}
|
||||
ut_a(block);
|
||||
goto exit_loop;
|
||||
});
|
||||
|
||||
if (page_rec_is_infimum(rec)) {
|
||||
|
||||
@ -1474,6 +1474,7 @@ run_again:
|
||||
}
|
||||
} while (btr_pcur_move_to_next(&pcur, &mtr));
|
||||
|
||||
exit_loop:
|
||||
if (check_ref) {
|
||||
row_ins_foreign_report_add_err(
|
||||
trx, foreign, btr_pcur_get_rec(&pcur), entry);
|
||||
|
@ -1298,11 +1298,11 @@ row_merge_read_clustered_index(
|
||||
if (UNIV_LIKELY(has_next)) {
|
||||
rec = btr_pcur_get_rec(&pcur);
|
||||
|
||||
if (srv_pass_corrupt_table && !rec) {
|
||||
SRV_CORRUPT_TABLE_CHECK(rec,
|
||||
{
|
||||
err = DB_CORRUPTION;
|
||||
goto err_exit;
|
||||
}
|
||||
ut_a(rec);
|
||||
});
|
||||
|
||||
offsets = rec_get_offsets(rec, clust_index, NULL,
|
||||
ULINT_UNDEFINED, &row_heap);
|
||||
|
@ -3813,9 +3813,9 @@ release_search_latch_if_needed:
|
||||
trx->has_search_latch = FALSE;
|
||||
}
|
||||
|
||||
ut_ad(prebuilt->sql_stat_start || trx->conc_state == TRX_ACTIVE);
|
||||
ut_ad(trx->conc_state == TRX_NOT_STARTED
|
||||
|| trx->conc_state == TRX_ACTIVE);
|
||||
ut_ad(prebuilt->sql_stat_start || trx->state == TRX_ACTIVE);
|
||||
ut_ad(trx->state == TRX_NOT_STARTED
|
||||
|| trx->state == TRX_ACTIVE);
|
||||
ut_ad(prebuilt->sql_stat_start
|
||||
|| prebuilt->select_lock_type != LOCK_NONE
|
||||
|| trx->read_view);
|
||||
@ -3997,11 +3997,11 @@ rec_loop:
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (srv_pass_corrupt_table && !rec) {
|
||||
SRV_CORRUPT_TABLE_CHECK(rec,
|
||||
{
|
||||
err = DB_CORRUPTION;
|
||||
goto lock_wait_or_error;
|
||||
}
|
||||
ut_a(rec);
|
||||
});
|
||||
|
||||
ut_ad(!!page_rec_is_comp(rec) == comp);
|
||||
#ifdef UNIV_SEARCH_DEBUG
|
||||
@ -4138,8 +4138,9 @@ wrong_offs:
|
||||
|
||||
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_force_recovery > 0)
|
||||
|| (srv_pass_corrupt_table == 2 && index->table->is_corrupt)) {
|
||||
if (UNIV_UNLIKELY(srv_force_recovery > 0
|
||||
|| (index->table->is_corrupt &&
|
||||
srv_pass_corrupt_table == 2))) {
|
||||
if (!rec_validate(rec, offsets)
|
||||
|| !btr_index_rec_validate(rec, index, FALSE)) {
|
||||
fprintf(stderr,
|
||||
@ -4896,8 +4897,10 @@ row_search_check_if_query_cache_permitted(
|
||||
if (trx->isolation_level >= TRX_ISO_REPEATABLE_READ
|
||||
&& !trx->read_view) {
|
||||
|
||||
trx->read_view = read_view_open_now(
|
||||
trx->id, trx->global_read_view_heap);
|
||||
trx->read_view =
|
||||
read_view_open_now(trx->id,
|
||||
NULL, TRUE);
|
||||
|
||||
trx->global_read_view = trx->read_view;
|
||||
}
|
||||
}
|
||||
|
@ -667,9 +667,9 @@ row_vers_build_for_semi_consistent_read(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
version_trx = trx_get_on_id(version_trx_id);
|
||||
if (version_trx
|
||||
&& (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY
|
||||
|| version_trx->conc_state == TRX_NOT_STARTED)) {
|
||||
if (version_trx &&
|
||||
(version_trx->state == TRX_COMMITTED_IN_MEMORY
|
||||
|| version_trx->state == TRX_NOT_STARTED)) {
|
||||
|
||||
version_trx = NULL;
|
||||
}
|
||||
|
@ -430,8 +430,6 @@ UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */
|
||||
UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
|
||||
|
||||
UNIV_INTERN ulint srv_dict_size_limit = 0;
|
||||
|
||||
UNIV_INTERN ulint srv_lazy_drop_table = 0;
|
||||
/*-------------------------------------------*/
|
||||
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
|
||||
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
|
||||
@ -2925,7 +2923,7 @@ rescan_idle:
|
||||
mutex_enter(&kernel_mutex);
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
|
||||
while (trx) {
|
||||
if (trx->conc_state == TRX_ACTIVE
|
||||
if (trx->state == TRX_ACTIVE
|
||||
&& trx->mysql_thd
|
||||
&& innobase_thd_is_idle(trx->mysql_thd)) {
|
||||
ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd);
|
||||
|
@ -263,8 +263,9 @@ trx_purge_sys_create(
|
||||
|
||||
purge_sys->query = trx_purge_graph_build();
|
||||
|
||||
purge_sys->view = read_view_oldest_copy_or_open_new(0,
|
||||
purge_sys->heap);
|
||||
purge_sys->prebuilt_view =
|
||||
read_view_oldest_copy_or_open_new(0, NULL);
|
||||
purge_sys->view = purge_sys->prebuilt_view;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -279,7 +280,12 @@ trx_purge_sys_close(void)
|
||||
que_graph_free(purge_sys->query);
|
||||
|
||||
ut_a(purge_sys->sess->trx->is_purge);
|
||||
purge_sys->sess->trx->conc_state = TRX_NOT_STARTED;
|
||||
purge_sys->sess->trx->state = TRX_NOT_STARTED;
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
trx_release_descriptor(purge_sys->sess->trx);
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
sess_close(purge_sys->sess);
|
||||
purge_sys->sess = NULL;
|
||||
|
||||
@ -289,6 +295,8 @@ trx_purge_sys_close(void)
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
read_view_close(purge_sys->view);
|
||||
read_view_free(purge_sys->prebuilt_view);
|
||||
purge_sys->prebuilt_view = NULL;
|
||||
purge_sys->view = NULL;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
@ -1177,7 +1185,7 @@ trx_purge(
|
||||
}
|
||||
|
||||
purge_sys->view = read_view_oldest_copy_or_open_new(
|
||||
0, purge_sys->heap);
|
||||
0, purge_sys->prebuilt_view);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
|
@ -132,7 +132,7 @@ trx_rollback_for_mysql(
|
||||
{
|
||||
int err;
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
@ -161,7 +161,7 @@ trx_rollback_last_sql_stat_for_mysql(
|
||||
{
|
||||
int err;
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
@ -263,7 +263,7 @@ trx_rollback_to_savepoint_for_mysql(
|
||||
return(DB_NO_SAVEPOINT);
|
||||
}
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: transaction has a savepoint ", stderr);
|
||||
ut_print_name(stderr, trx, FALSE, savep->name);
|
||||
@ -560,7 +560,7 @@ loop:
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (trx->conc_state) {
|
||||
switch (trx->state) {
|
||||
case TRX_NOT_STARTED:
|
||||
case TRX_PREPARED:
|
||||
continue;
|
||||
|
@ -1319,6 +1319,12 @@ trx_sys_init_at_db_start(void)
|
||||
|
||||
trx_sys = mem_zalloc(sizeof(*trx_sys));
|
||||
|
||||
/* Allocate the trx descriptors array */
|
||||
trx_sys->descriptors = ut_malloc(sizeof(trx_id_t) *
|
||||
TRX_DESCR_ARRAY_INITIAL_SIZE);
|
||||
trx_sys->descr_n_max = TRX_DESCR_ARRAY_INITIAL_SIZE;
|
||||
trx_sys->descr_n_used = 0;
|
||||
|
||||
sys_header = trx_sysf_get(&mtr);
|
||||
|
||||
trx_rseg_list_and_array_init(sys_header, ib_bh, &mtr);
|
||||
@ -1346,7 +1352,7 @@ trx_sys_init_at_db_start(void)
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (trx->conc_state != TRX_PREPARED) {
|
||||
if (trx->state != TRX_PREPARED) {
|
||||
rows_to_undo += trx->undo_no;
|
||||
}
|
||||
|
||||
@ -2028,6 +2034,9 @@ trx_sys_close(void)
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->view_list) == 0);
|
||||
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
|
||||
|
||||
ut_ad(trx_sys->descr_n_used == 0);
|
||||
ut_free(trx_sys->descriptors);
|
||||
|
||||
mem_free(trx_sys);
|
||||
|
||||
trx_sys = NULL;
|
||||
|
243
trx/trx0trx.c
243
trx/trx0trx.c
@ -85,6 +85,126 @@ trx_set_detailed_error_from_file(
|
||||
sizeof(trx->detailed_error));
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Callback function for trx_find_descriptor() to compare trx IDs. */
|
||||
UNIV_INTERN
|
||||
int
|
||||
trx_descr_cmp(
|
||||
/*==========*/
|
||||
const void *a, /*!< in: pointer to first comparison argument */
|
||||
const void *b) /*!< in: pointer to second comparison argument */
|
||||
{
|
||||
const trx_id_t* da = (const trx_id_t*) a;
|
||||
const trx_id_t* db = (const trx_id_t*) b;
|
||||
|
||||
if (*da < *db) {
|
||||
return -1;
|
||||
} else if (*da > *db) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Reserve a slot for a given trx in the global descriptors array. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
trx_reserve_descriptor(
|
||||
/*===================*/
|
||||
const trx_t* trx) /*!< in: trx pointer */
|
||||
{
|
||||
ulint n_used;
|
||||
ulint n_max;
|
||||
trx_id_t* descr;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad(!trx_find_descriptor(trx_sys->descriptors,
|
||||
trx_sys->descr_n_used,
|
||||
trx->id));
|
||||
|
||||
n_used = trx_sys->descr_n_used + 1;
|
||||
n_max = trx_sys->descr_n_max;
|
||||
|
||||
if (UNIV_UNLIKELY(n_used > n_max)) {
|
||||
|
||||
n_max = n_max * 2;
|
||||
|
||||
trx_sys->descriptors =
|
||||
ut_realloc(trx_sys->descriptors,
|
||||
n_max * sizeof(trx_id_t));
|
||||
|
||||
trx_sys->descr_n_max = n_max;
|
||||
}
|
||||
|
||||
descr = trx_sys->descriptors + n_used - 1;
|
||||
|
||||
if (UNIV_UNLIKELY(n_used > 1 && trx->id < descr[-1])) {
|
||||
|
||||
/* Find the slot where it should be inserted. We could use a
|
||||
binary search, but in reality linear search should be faster,
|
||||
because the slot we are looking for is near the array end. */
|
||||
|
||||
trx_id_t* tdescr;
|
||||
|
||||
for (tdescr = descr - 1;
|
||||
tdescr >= trx_sys->descriptors && *tdescr > trx->id;
|
||||
tdescr--) {
|
||||
}
|
||||
|
||||
tdescr++;
|
||||
|
||||
ut_memmove(tdescr + 1, tdescr, (descr - tdescr) *
|
||||
sizeof(trx_id_t));
|
||||
|
||||
descr = tdescr;
|
||||
}
|
||||
|
||||
*descr = trx->id;
|
||||
|
||||
trx_sys->descr_n_used = n_used;
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
Release a slot for a given trx in the global descriptors array. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_release_descriptor(
|
||||
/*===================*/
|
||||
trx_t* trx) /*!< in: trx pointer */
|
||||
{
|
||||
ulint size;
|
||||
trx_id_t* descr;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (UNIV_LIKELY(trx->is_in_trx_serial_list)) {
|
||||
|
||||
UT_LIST_REMOVE(trx_serial_list, trx_sys->trx_serial_list,
|
||||
trx);
|
||||
trx->is_in_trx_serial_list = 0;
|
||||
}
|
||||
|
||||
descr = trx_find_descriptor(trx_sys->descriptors,
|
||||
trx_sys->descr_n_used,
|
||||
trx->id);
|
||||
|
||||
if (UNIV_UNLIKELY(descr == NULL)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size = (trx_sys->descriptors + trx_sys->descr_n_used - 1 - descr) *
|
||||
sizeof(trx_id_t);
|
||||
|
||||
if (UNIV_LIKELY(size > 0)) {
|
||||
|
||||
ut_memmove(descr, descr + 1, size);
|
||||
}
|
||||
|
||||
trx_sys->descr_n_used--;
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Creates and initializes a transaction object.
|
||||
@return own: the transaction */
|
||||
@ -107,7 +227,7 @@ trx_create(
|
||||
|
||||
trx->is_purge = 0;
|
||||
trx->is_recovered = 0;
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
trx->state = TRX_NOT_STARTED;
|
||||
|
||||
trx->is_registered = 0;
|
||||
trx->owns_prepare_mutex = 0;
|
||||
@ -119,6 +239,7 @@ trx_create(
|
||||
|
||||
trx->id = 0;
|
||||
trx->no = IB_ULONGLONG_MAX;
|
||||
trx->is_in_trx_serial_list = 0;
|
||||
|
||||
trx->support_xa = TRUE;
|
||||
|
||||
@ -190,9 +311,9 @@ trx_create(
|
||||
trx->declared_to_be_inside_innodb = FALSE;
|
||||
trx->n_tickets_to_enter_innodb = 0;
|
||||
|
||||
trx->global_read_view_heap = mem_heap_create(256);
|
||||
trx->global_read_view = NULL;
|
||||
trx->read_view = NULL;
|
||||
trx->prebuilt_view = NULL;
|
||||
|
||||
trx->io_reads = 0;
|
||||
trx->io_read = 0;
|
||||
@ -328,7 +449,7 @@ trx_free(
|
||||
|
||||
trx->magic_n = 11112222;
|
||||
|
||||
ut_a(trx->conc_state == TRX_NOT_STARTED);
|
||||
ut_a(trx->state == TRX_NOT_STARTED);
|
||||
|
||||
mutex_free(&(trx->undo_mutex));
|
||||
|
||||
@ -355,18 +476,18 @@ trx_free(
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(trx->trx_locks) == 0);
|
||||
|
||||
if (trx->global_read_view_heap) {
|
||||
mem_heap_free(trx->global_read_view_heap);
|
||||
if (trx->prebuilt_view != NULL) {
|
||||
read_view_free(trx->prebuilt_view);
|
||||
}
|
||||
|
||||
trx->global_read_view = NULL;
|
||||
|
||||
ut_a(trx->read_view == NULL);
|
||||
|
||||
ut_a(ib_vector_is_empty(trx->autoinc_locks));
|
||||
/* We allocated a dedicated heap for the vector. */
|
||||
ib_vector_free(trx->autoinc_locks);
|
||||
|
||||
trx_release_descriptor(trx);
|
||||
|
||||
mem_free(trx);
|
||||
}
|
||||
|
||||
@ -379,7 +500,7 @@ trx_free_prepared(
|
||||
trx_t* trx) /*!< in, own: trx object */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_a(trx->conc_state == TRX_PREPARED);
|
||||
ut_a(trx->state == TRX_PREPARED);
|
||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
/* Prepared transactions are sort of active; they allow
|
||||
@ -412,15 +533,19 @@ trx_free_prepared(
|
||||
mem_heap_free(trx->lock_heap);
|
||||
}
|
||||
|
||||
if (trx->global_read_view_heap) {
|
||||
mem_heap_free(trx->global_read_view_heap);
|
||||
}
|
||||
|
||||
ut_a(ib_vector_is_empty(trx->autoinc_locks));
|
||||
ib_vector_free(trx->autoinc_locks);
|
||||
|
||||
trx_release_descriptor(trx);
|
||||
|
||||
if (trx->prebuilt_view != NULL) {
|
||||
read_view_free(trx->prebuilt_view);
|
||||
}
|
||||
|
||||
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
|
||||
|
||||
ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list));
|
||||
|
||||
mem_free(trx);
|
||||
}
|
||||
|
||||
@ -529,6 +654,7 @@ trx_lists_init_at_db_start(void)
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
UT_LIST_INIT(trx_sys->trx_list);
|
||||
UT_LIST_INIT(trx_sys->trx_serial_list);
|
||||
|
||||
/* Look from the rollback segments if there exist undo logs for
|
||||
transactions */
|
||||
@ -565,7 +691,7 @@ trx_lists_init_at_db_start(void)
|
||||
|
||||
if (srv_force_recovery == 0) {
|
||||
|
||||
trx->conc_state = TRX_PREPARED;
|
||||
trx->state = TRX_PREPARED;
|
||||
trx_n_prepared++;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
@ -575,11 +701,12 @@ trx_lists_init_at_db_start(void)
|
||||
" rollback it"
|
||||
" anyway.\n");
|
||||
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
trx->state = TRX_ACTIVE;
|
||||
}
|
||||
|
||||
trx_reserve_descriptor(trx);
|
||||
} else {
|
||||
trx->conc_state
|
||||
= TRX_COMMITTED_IN_MEMORY;
|
||||
trx->state = TRX_COMMITTED_IN_MEMORY;
|
||||
}
|
||||
|
||||
/* We give a dummy value for the trx no;
|
||||
@ -591,12 +718,15 @@ trx_lists_init_at_db_start(void)
|
||||
|
||||
trx->no = trx->id;
|
||||
} else {
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
trx->state = TRX_ACTIVE;
|
||||
|
||||
/* A running transaction always has the number
|
||||
field inited to IB_ULONGLONG_MAX */
|
||||
|
||||
trx->no = IB_ULONGLONG_MAX;
|
||||
|
||||
trx_reserve_descriptor(trx);
|
||||
|
||||
}
|
||||
|
||||
if (undo->dict_operation) {
|
||||
@ -641,7 +771,7 @@ trx_lists_init_at_db_start(void)
|
||||
|
||||
if (srv_force_recovery == 0) {
|
||||
|
||||
trx->conc_state
|
||||
trx->state
|
||||
= TRX_PREPARED;
|
||||
trx_n_prepared++;
|
||||
} else {
|
||||
@ -652,11 +782,12 @@ trx_lists_init_at_db_start(void)
|
||||
" rollback it"
|
||||
" anyway.\n");
|
||||
|
||||
trx->conc_state
|
||||
= TRX_ACTIVE;
|
||||
trx->state = TRX_ACTIVE;
|
||||
trx_reserve_descriptor(
|
||||
trx);
|
||||
}
|
||||
} else {
|
||||
trx->conc_state
|
||||
trx->state
|
||||
= TRX_COMMITTED_IN_MEMORY;
|
||||
}
|
||||
|
||||
@ -665,13 +796,14 @@ trx_lists_init_at_db_start(void)
|
||||
|
||||
trx->no = trx->id;
|
||||
} else {
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
|
||||
trx->state = TRX_ACTIVE;
|
||||
/* A running transaction always has
|
||||
the number field inited to
|
||||
IB_ULONGLONG_MAX */
|
||||
|
||||
trx->no = IB_ULONGLONG_MAX;
|
||||
|
||||
trx_reserve_descriptor(trx);
|
||||
}
|
||||
|
||||
trx->rseg = rseg;
|
||||
@ -742,13 +874,15 @@ trx_start_low(
|
||||
|
||||
if (trx->is_purge) {
|
||||
trx->id = 0;
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
/* Don't reserve a descriptor, since this trx is not added to
|
||||
trx_list. */
|
||||
trx->state = TRX_ACTIVE;
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
ut_ad(trx->conc_state != TRX_ACTIVE);
|
||||
ut_ad(trx->state != TRX_ACTIVE);
|
||||
|
||||
ut_a(rseg_id == ULINT_UNDEFINED);
|
||||
|
||||
@ -763,7 +897,10 @@ trx_start_low(
|
||||
|
||||
trx->rseg = rseg;
|
||||
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
trx->state = TRX_ACTIVE;
|
||||
|
||||
trx_reserve_descriptor(trx);
|
||||
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
|
||||
@ -820,6 +957,14 @@ trx_serialisation_number_get(
|
||||
|
||||
trx->no = trx_sys_get_new_trx_id();
|
||||
|
||||
if (UNIV_LIKELY(trx->is_in_trx_serial_list == 0)) {
|
||||
|
||||
UT_LIST_ADD_LAST(trx_serial_list, trx_sys->trx_serial_list,
|
||||
trx);
|
||||
|
||||
trx->is_in_trx_serial_list = 1;
|
||||
}
|
||||
|
||||
/* If the rollack segment is not empty then the
|
||||
new trx_t::no can't be less than any trx_t::no
|
||||
already in the rollback segment. User threads only
|
||||
@ -1001,10 +1146,10 @@ trx_commit_off_kernel(
|
||||
lsn = 0;
|
||||
}
|
||||
|
||||
ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
|
||||
ut_ad(trx->state == TRX_ACTIVE || trx->state == TRX_PREPARED);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (UNIV_UNLIKELY(trx->conc_state == TRX_PREPARED)) {
|
||||
if (UNIV_UNLIKELY(trx->state == TRX_PREPARED)) {
|
||||
ut_a(trx_n_prepared > 0);
|
||||
trx_n_prepared--;
|
||||
}
|
||||
@ -1024,7 +1169,9 @@ trx_commit_off_kernel(
|
||||
committed. */
|
||||
|
||||
/*--------------------------------------*/
|
||||
trx->conc_state = TRX_COMMITTED_IN_MEMORY;
|
||||
trx->state = TRX_COMMITTED_IN_MEMORY;
|
||||
/* The following also removes trx from trx_serial_list */
|
||||
trx_release_descriptor(trx);
|
||||
/*--------------------------------------*/
|
||||
|
||||
/* If we release kernel_mutex below and we are still doing
|
||||
@ -1045,7 +1192,6 @@ trx_commit_off_kernel(
|
||||
|
||||
if (trx->global_read_view) {
|
||||
read_view_close(trx->global_read_view);
|
||||
mem_heap_empty(trx->global_read_view_heap);
|
||||
trx->global_read_view = NULL;
|
||||
}
|
||||
|
||||
@ -1131,7 +1277,7 @@ trx_commit_off_kernel(
|
||||
/* Free all savepoints */
|
||||
trx_roll_free_all_savepoints(trx);
|
||||
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
trx->state = TRX_NOT_STARTED;
|
||||
trx->rseg = NULL;
|
||||
trx->undo_no = 0;
|
||||
trx->last_sql_stat_start.least_undo_no = 0;
|
||||
@ -1141,6 +1287,8 @@ trx_commit_off_kernel(
|
||||
|
||||
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
|
||||
|
||||
ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list));
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1159,12 +1307,15 @@ trx_cleanup_at_db_startup(
|
||||
trx_undo_insert_cleanup(trx);
|
||||
}
|
||||
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
trx->state = TRX_NOT_STARTED;
|
||||
trx_release_descriptor(trx);
|
||||
trx->rseg = NULL;
|
||||
trx->undo_no = 0;
|
||||
trx->last_sql_stat_start.least_undo_no = 0;
|
||||
|
||||
UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx);
|
||||
|
||||
ut_ad(trx_sys->descr_n_used <= UT_LIST_GET_LEN(trx_sys->trx_list));
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
@ -1178,7 +1329,7 @@ trx_assign_read_view(
|
||||
/*=================*/
|
||||
trx_t* trx) /*!< in: active transaction */
|
||||
{
|
||||
ut_ad(trx->conc_state == TRX_ACTIVE);
|
||||
ut_ad(trx->state == TRX_ACTIVE);
|
||||
|
||||
if (trx->read_view) {
|
||||
return(trx->read_view);
|
||||
@ -1186,11 +1337,9 @@ trx_assign_read_view(
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
if (!trx->read_view) {
|
||||
trx->read_view = read_view_open_now(
|
||||
trx->id, trx->global_read_view_heap);
|
||||
trx->global_read_view = trx->read_view;
|
||||
}
|
||||
trx->read_view = read_view_open_now(trx->id, trx->prebuilt_view, TRUE);
|
||||
trx->prebuilt_view = trx->read_view;
|
||||
trx->global_read_view = trx->read_view;
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
@ -1555,7 +1704,7 @@ loop:
|
||||
return;
|
||||
}
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
|
||||
trx_start_low(trx, ULINT_UNDEFINED);
|
||||
}
|
||||
@ -1847,7 +1996,7 @@ trx_mark_sql_stat_end(
|
||||
{
|
||||
ut_a(trx);
|
||||
|
||||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
if (trx->state == TRX_NOT_STARTED) {
|
||||
trx->undo_no = 0;
|
||||
}
|
||||
|
||||
@ -1870,7 +2019,7 @@ trx_print(
|
||||
|
||||
fprintf(f, "TRANSACTION " TRX_ID_FMT, (ullint) trx->id);
|
||||
|
||||
switch (trx->conc_state) {
|
||||
switch (trx->state) {
|
||||
case TRX_NOT_STARTED:
|
||||
fputs(", not started", f);
|
||||
break;
|
||||
@ -1886,7 +2035,7 @@ trx_print(
|
||||
fputs(", COMMITTED IN MEMORY", f);
|
||||
break;
|
||||
default:
|
||||
fprintf(f, " state %lu", (ulong) trx->conc_state);
|
||||
fprintf(f, " state %lu", (ulong) trx->state);
|
||||
}
|
||||
|
||||
if (*trx->op_info) {
|
||||
@ -2081,7 +2230,11 @@ trx_prepare_off_kernel(
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
/*--------------------------------------*/
|
||||
trx->conc_state = TRX_PREPARED;
|
||||
if (UNIV_UNLIKELY(trx->state != TRX_ACTIVE)) {
|
||||
|
||||
trx_reserve_descriptor(trx);
|
||||
}
|
||||
trx->state = TRX_PREPARED;
|
||||
trx_n_prepared++;
|
||||
/*--------------------------------------*/
|
||||
|
||||
@ -2195,7 +2348,7 @@ trx_recover_for_mysql(
|
||||
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
|
||||
|
||||
while (trx) {
|
||||
if (trx->conc_state == TRX_PREPARED) {
|
||||
if (trx->state == TRX_PREPARED) {
|
||||
xid_list[count] = trx->xid;
|
||||
|
||||
if (count == 0) {
|
||||
@ -2268,7 +2421,7 @@ trx_get_trx_by_xid(
|
||||
the same */
|
||||
|
||||
if (trx->is_recovered
|
||||
&& trx->conc_state == TRX_PREPARED
|
||||
&& trx->state == TRX_PREPARED
|
||||
&& xid->gtrid_length == trx->xid.gtrid_length
|
||||
&& xid->bqual_length == trx->xid.bqual_length
|
||||
&& memcmp(xid->data, trx->xid.data,
|
||||
|
Loading…
x
Reference in New Issue
Block a user