diff options
author | unknown <knielsen@knielsen-hq.org> | 2011-12-14 14:58:22 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2011-12-14 14:58:22 +0100 |
commit | 6afbf295f018e077be7c569ef8e433e510441bea (patch) | |
tree | 2be3dc217f20980e3d2b8c6e933286d967b6ba58 | |
parent | d4d7a8fa62c406be73f6c0f6d75e795293db548b (diff) | |
download | mariadb-git-6afbf295f018e077be7c569ef8e433e510441bea.tar.gz |
Updated with XtraDB from Percona Server 5.5.17-rel22.1
Files copied from Percona-Server-5.5.17-rel22.1.tar.gz source tarball.
103 files changed, 5921 insertions, 2880 deletions
diff --git a/btr/btr0btr.c b/btr/btr0btr.c index c0c27128441..ca98afc04ad 100644 --- a/btr/btr0btr.c +++ b/btr/btr0btr.c @@ -690,7 +690,8 @@ btr_root_block_get( zip_size = dict_table_zip_size(index->table); root_page_no = dict_index_get_page(index); - block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); + block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, + index, mtr); if (srv_pass_corrupt_table && !block) { return(0); @@ -897,7 +898,7 @@ btr_page_alloc_for_ibuf( dict_table_zip_size(index->table), node_addr.page, RW_X_LATCH, mtr); new_page = buf_block_get_frame(new_block); - buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW); + buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW); flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, @@ -1151,7 +1152,7 @@ btr_node_ptr_get_child( page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets); return(btr_block_get(space, dict_table_zip_size(index->table), - page_no, RW_X_LATCH, mtr)); + page_no, RW_X_LATCH, index, mtr)); } /************************************************************//** @@ -1324,7 +1325,8 @@ btr_create( space, 0, IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr); - buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW); + buf_block_dbg_add_level( + ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW); ut_ad(buf_block_get_page_no(ibuf_hdr_block) == IBUF_HEADER_PAGE_NO); @@ -1362,10 +1364,9 @@ btr_create( page_no = buf_block_get_page_no(block); frame = buf_block_get_frame(block); - buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); - if (type & DICT_IBUF) { /* It is an insert buffer tree: initialize the free list */ + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO); @@ -1373,6 +1374,8 @@ btr_create( } else { /* It is a non-ibuf tree: create a file segment for leaf pages */ + buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); + if (!fseg_create(space, page_no, PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { /* Not enough space for new segment, free root @@ -1444,14 +1447,15 @@ btr_free_but_not_root( leaf_loop: mtr_start(&mtr); - root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); + root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, + NULL, &mtr); if (srv_pass_corrupt_table && !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 + root, space)); @@ -1473,7 +1477,8 @@ leaf_loop: top_loop: mtr_start(&mtr); - root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr); + root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, + NULL, &mtr); if (srv_pass_corrupt_table && !root) { mtr_commit(&mtr); @@ -1505,13 +1510,13 @@ btr_free_root( ulint zip_size, /*!< in: compressed page size in bytes or 0 for uncompressed pages */ ulint root_page_no, /*!< in: root page number */ - mtr_t* mtr) /*!< in: a mini-transaction which has already - been started */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { buf_block_t* block; fseg_header_t* header; - block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); + block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, + NULL, mtr); if (srv_pass_corrupt_table && !block) { return; @@ -2395,9 +2400,8 @@ btr_attach_half_pages( /* Update page links of the level */ if (prev_page_no != FIL_NULL) { - buf_block_t* prev_block = btr_block_get(space, zip_size, - prev_page_no, - RW_X_LATCH, mtr); + buf_block_t* prev_block = btr_block_get( + space, zip_size, prev_page_no, RW_X_LATCH, index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(prev_block->frame) == page_is_comp(page)); ut_a(btr_page_get_next(prev_block->frame, mtr) @@ -2410,9 +2414,8 @@ btr_attach_half_pages( } if (next_page_no != FIL_NULL) { - buf_block_t* next_block = btr_block_get(space, zip_size, - next_page_no, - RW_X_LATCH, mtr); + buf_block_t* next_block = btr_block_get( + space, zip_size, next_page_no, RW_X_LATCH, index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_block->frame) == page_is_comp(page)); ut_a(btr_page_get_prev(next_block->frame, mtr) @@ -2834,17 +2837,42 @@ func_exit: return(rec); } +#ifdef UNIV_SYNC_DEBUG +/*************************************************************//** +Removes a page from the level list of pages. +@param space in: space where removed +@param zip_size in: compressed page size in bytes, or 0 for uncompressed +@param page in/out: page to remove +@param index in: index tree +@param mtr in/out: mini-transaction */ +# define btr_level_list_remove(space,zip_size,page,index,mtr) \ + btr_level_list_remove_func(space,zip_size,page,index,mtr) +#else /* UNIV_SYNC_DEBUG */ +/*************************************************************//** +Removes a page from the level list of pages. +@param space in: space where removed +@param zip_size in: compressed page size in bytes, or 0 for uncompressed +@param page in/out: page to remove +@param index in: index tree +@param mtr in/out: mini-transaction */ +# define btr_level_list_remove(space,zip_size,page,index,mtr) \ + btr_level_list_remove_func(space,zip_size,page,mtr) +#endif /* UNIV_SYNC_DEBUG */ + /*************************************************************//** Removes a page from the level list of pages. */ -static +static __attribute__((nonnull)) void -btr_level_list_remove( -/*==================*/ - ulint space, /*!< in: space where removed */ - ulint zip_size,/*!< in: compressed page size in bytes - or 0 for uncompressed pages */ - page_t* page, /*!< in: page to remove */ - mtr_t* mtr) /*!< in: mtr */ +btr_level_list_remove_func( +/*=======================*/ + ulint space, /*!< in: space where removed */ + ulint zip_size,/*!< in: compressed page size in bytes + or 0 for uncompressed pages */ + page_t* page, /*!< in/out: page to remove */ +#ifdef UNIV_SYNC_DEBUG + const dict_index_t* index, /*!< in: index tree */ +#endif /* UNIV_SYNC_DEBUG */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint prev_page_no; ulint next_page_no; @@ -2862,7 +2890,7 @@ btr_level_list_remove( if (prev_page_no != FIL_NULL) { buf_block_t* prev_block = btr_block_get(space, zip_size, prev_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); page_t* prev_page = buf_block_get_frame(prev_block); #ifdef UNIV_BTR_DEBUG @@ -2879,7 +2907,7 @@ btr_level_list_remove( if (next_page_no != FIL_NULL) { buf_block_t* next_block = btr_block_get(space, zip_size, next_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); page_t* next_page = buf_block_get_frame(next_block); #ifdef UNIV_BTR_DEBUG @@ -3194,7 +3222,7 @@ btr_compress( if (is_left) { merge_block = btr_block_get(space, zip_size, left_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_next(merge_page, mtr) @@ -3203,7 +3231,7 @@ btr_compress( } else if (right_page_no != FIL_NULL) { merge_block = btr_block_get(space, zip_size, right_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_prev(merge_page, mtr) @@ -3292,7 +3320,7 @@ err_exit: btr_search_drop_page_hash_index(block, index); /* Remove the page from the level list */ - btr_level_list_remove(space, zip_size, page, mtr); + btr_level_list_remove(space, zip_size, page, index, mtr); btr_node_ptr_delete(index, block, mtr); lock_update_merge_left(merge_block, orig_pred, block); @@ -3345,7 +3373,7 @@ err_exit: #endif /* UNIV_BTR_DEBUG */ /* Remove the page from the level list */ - btr_level_list_remove(space, zip_size, page, mtr); + btr_level_list_remove(space, zip_size, page, index, mtr); /* Replace the address of the old child node (= page) with the address of the merge page to the right */ @@ -3528,7 +3556,7 @@ btr_discard_page( if (left_page_no != FIL_NULL) { merge_block = btr_block_get(space, zip_size, left_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_next(merge_page, mtr) @@ -3536,7 +3564,7 @@ btr_discard_page( #endif /* UNIV_BTR_DEBUG */ } else if (right_page_no != FIL_NULL) { merge_block = btr_block_get(space, zip_size, right_page_no, - RW_X_LATCH, mtr); + RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_prev(merge_page, mtr) @@ -3571,7 +3599,7 @@ btr_discard_page( btr_node_ptr_delete(index, block, mtr); /* Remove the page from the level list */ - btr_level_list_remove(space, zip_size, page, mtr); + btr_level_list_remove(space, zip_size, page, index, mtr); #ifdef UNIV_ZIP_DEBUG { page_zip_des_t* merge_page_zip @@ -4089,7 +4117,7 @@ loop: if (right_page_no != FIL_NULL) { const rec_t* right_rec; right_block = btr_block_get(space, zip_size, right_page_no, - RW_X_LATCH, &mtr); + RW_X_LATCH, index, &mtr); right_page = buf_block_get_frame(right_block); if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr) != page_get_page_no(page))) { @@ -4315,7 +4343,7 @@ node_ptr_fails: mtr_start(&mtr); block = btr_block_get(space, zip_size, right_page_no, - RW_X_LATCH, &mtr); + RW_X_LATCH, index, &mtr); page = buf_block_get_frame(block); goto loop; diff --git a/btr/btr0cur.c b/btr/btr0cur.c index f6ef44e5b5c..717663a123a 100644 --- a/btr/btr0cur.c +++ b/btr/btr0cur.c @@ -249,7 +249,8 @@ btr_cur_latch_leaves( case BTR_SEARCH_LEAF: case BTR_MODIFY_LEAF: mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH; - get_block = btr_block_get(space, zip_size, page_no, mode, mtr); + get_block = btr_block_get( + space, zip_size, page_no, mode, cursor->index, mtr); if (srv_pass_corrupt_table && !get_block) { return; @@ -265,9 +266,9 @@ btr_cur_latch_leaves( left_page_no = btr_page_get_prev(page, mtr); if (left_page_no != FIL_NULL) { - get_block = btr_block_get(space, zip_size, - left_page_no, - RW_X_LATCH, mtr); + get_block = btr_block_get( + space, zip_size, left_page_no, + RW_X_LATCH, cursor->index, mtr); if (srv_pass_corrupt_table && !get_block) { return; @@ -282,8 +283,9 @@ btr_cur_latch_leaves( get_block->check_index_page_at_flush = TRUE; } - get_block = btr_block_get(space, zip_size, page_no, - RW_X_LATCH, mtr); + get_block = btr_block_get( + space, zip_size, page_no, + RW_X_LATCH, cursor->index, mtr); if (srv_pass_corrupt_table && !get_block) { return; @@ -297,9 +299,9 @@ btr_cur_latch_leaves( right_page_no = btr_page_get_next(page, mtr); if (right_page_no != FIL_NULL) { - get_block = btr_block_get(space, zip_size, - right_page_no, - RW_X_LATCH, mtr); + get_block = btr_block_get( + space, zip_size, right_page_no, + RW_X_LATCH, cursor->index, mtr); if (srv_pass_corrupt_table && !get_block) { return; @@ -323,8 +325,9 @@ btr_cur_latch_leaves( left_page_no = btr_page_get_prev(page, mtr); if (left_page_no != FIL_NULL) { - get_block = btr_block_get(space, zip_size, - left_page_no, mode, mtr); + get_block = btr_block_get( + space, zip_size, + left_page_no, mode, cursor->index, mtr); cursor->left_block = get_block; if (srv_pass_corrupt_table && !get_block) { @@ -340,7 +343,8 @@ btr_cur_latch_leaves( get_block->check_index_page_at_flush = TRUE; } - get_block = btr_block_get(space, zip_size, page_no, mode, mtr); + get_block = btr_block_get( + space, zip_size, page_no, mode, cursor->index, mtr); if (srv_pass_corrupt_table && !get_block) { return; @@ -722,7 +726,9 @@ retry_page_get: ut_a(!page_zip || page_zip_validate(page_zip, page)); #endif /* UNIV_ZIP_DEBUG */ - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level( + block, dict_index_is_ibuf(index) + ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); } ut_ad(index->id == btr_page_get_index_id(page)); @@ -820,7 +826,7 @@ retry_page_get: if (level != 0) { /* x-latch the page */ page = btr_page_get( - space, zip_size, page_no, RW_X_LATCH, mtr); + space, zip_size, page_no, RW_X_LATCH, index, mtr); ut_a((ibool)!!page_is_comp(page) == dict_table_is_comp(index->table)); @@ -1167,6 +1173,11 @@ btr_cur_ins_lock_and_undo( rec_t* rec; roll_ptr_t roll_ptr; + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip LOCK, UNDO */ + return(DB_SUCCESS); + } + /* Check if we have to wait for a lock: enqueue an explicit lock request if yes */ @@ -1298,7 +1309,7 @@ btr_cur_optimistic_insert( } #endif /* UNIV_DEBUG */ - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); max_size = page_get_max_insert_size_after_reorganize(page, 1); leaf = page_is_leaf(page); @@ -1393,6 +1404,12 @@ fail_err: goto fail_err; } + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip CHANGE, LOG */ + *big_rec = big_rec_vec; + return(err); /* == DB_SUCCESS */ + } + page_cursor = btr_cur_get_page_cur(cursor); /* Now, try the insert */ @@ -1535,10 +1552,10 @@ btr_cur_pessimistic_insert( *big_rec = NULL; - ut_ad(mtr_memo_contains(mtr, + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(btr_cur_get_index(cursor)), MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); /* Try first an optimistic insert; reset the cursor flag: we do not @@ -1604,6 +1621,16 @@ btr_cur_pessimistic_insert( } } + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip CHANGE, LOG */ + if (n_extents > 0) { + fil_space_release_free_extents(index->space, + n_reserved); + } + *big_rec = big_rec_vec; + return(DB_SUCCESS); + } + if (dict_index_get_page(index) == buf_block_get_page_no(btr_cur_get_block(cursor))) { @@ -1660,6 +1687,11 @@ btr_cur_upd_lock_and_undo( ut_ad(cursor && update && thr && roll_ptr); + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip LOCK, UNDO */ + return(DB_SUCCESS); + } + rec = btr_cur_get_rec(cursor); index = cursor->index; @@ -1917,6 +1949,7 @@ btr_cur_update_in_place( roll_ptr_t roll_ptr = 0; trx_t* trx; ulint was_delete_marked; + ibool is_hashed; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -1958,7 +1991,29 @@ btr_cur_update_in_place( return(err); } - if (block->is_hashed) { + if (trx->fake_changes) { + /* skip CHANGE, LOG */ + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + return(err); /* == DB_SUCCESS */ + } + + if (!(flags & BTR_KEEP_SYS_FLAG)) { + row_upd_rec_sys_fields(rec, NULL, + index, offsets, trx, roll_ptr); + } + + was_delete_marked = rec_get_deleted_flag( + rec, page_is_comp(buf_block_get_frame(block))); + + is_hashed = block->is_hashed; + + if (is_hashed) { + /* TO DO: Can we skip this if none of the fields + index->search_info->curr_n_fields + are being updated? */ + /* The function row_upd_changes_ord_field_binary works only if the update vector was built for a clustered index, we must NOT call it if index is secondary */ @@ -1974,17 +2029,9 @@ btr_cur_update_in_place( rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); } - if (!(flags & BTR_KEEP_SYS_FLAG)) { - row_upd_rec_sys_fields(rec, NULL, - index, offsets, trx, roll_ptr); - } - - was_delete_marked = rec_get_deleted_flag( - rec, page_is_comp(buf_block_get_frame(block))); - row_upd_rec_in_place(rec, index, offsets, update, page_zip); - if (block->is_hashed) { + if (is_hashed) { rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); } @@ -2061,7 +2108,7 @@ btr_cur_optimistic_update( rec = btr_cur_get_rec(cursor); index = cursor->index; ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); /* The insert buffer tree should never be updated in place. */ ut_ad(!dict_index_is_ibuf(index)); @@ -2174,6 +2221,11 @@ any_extern: goto err_exit; } + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip CHANGE, LOG */ + goto err_exit; /* == DB_SUCCESS */ + } + /* Ok, we may do the replacement. Store on the page infimum the explicit locks on rec, before deleting rec (see the comment in btr_cur_pessimistic_update). */ @@ -2324,9 +2376,9 @@ btr_cur_pessimistic_update( rec = btr_cur_get_rec(cursor); index = cursor->index; - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, dict_index_get_lock(index), MTR_MEMO_X_LOCK)); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, page)); #endif /* UNIV_ZIP_DEBUG */ @@ -2414,6 +2466,9 @@ btr_cur_pessimistic_update( ut_ad(big_rec_vec == NULL); + /* fake_changes should not cause undo. so never reaches here */ + ut_ad(!(trx->fake_changes)); + btr_rec_free_updated_extern_fields( index, rec, page_zip, offsets, update, trx_is_recv(trx) ? RB_RECOVERY : RB_NORMAL, mtr); @@ -2448,6 +2503,12 @@ make_external: } } + if (trx->fake_changes) { + /* skip CHANGE, LOG */ + err = DB_SUCCESS; + goto return_after_reservations; + } + /* Store state of explicit locks on rec on the page infimum record, before deleting rec. The page infimum acts as a dummy carrier of the locks, taking care also of lock releases, before we can move the locks @@ -2685,7 +2746,8 @@ btr_cur_parse_del_mark_set_clust_rec( /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to - it. */ + it. Besides, these fields are being updated in place + and the adaptive hash index does not depend on them. */ btr_rec_set_deleted_flag(rec, page_zip, val); @@ -2749,6 +2811,11 @@ btr_cur_del_mark_set_clust_rec( ut_ad(dict_index_is_clust(index)); ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip LOCK, UNDO, CHANGE, LOG */ + return(DB_SUCCESS); + } + err = lock_clust_rec_modify_check_and_lock(flags, block, rec, index, offsets, thr); @@ -2765,9 +2832,9 @@ btr_cur_del_mark_set_clust_rec( return(err); } - if (block->is_hashed) { - rw_lock_x_lock(btr_search_get_latch(index->id)); - } + /* The btr_search_latch is not needed here, because + the adaptive hash index does not depend on the delete-mark + and the delete-mark is being updated in place. */ page_zip = buf_block_get_page_zip(block); @@ -2781,10 +2848,6 @@ btr_cur_del_mark_set_clust_rec( index, offsets, trx, roll_ptr); } - if (block->is_hashed) { - rw_lock_x_unlock(btr_search_get_latch(index->id)); - } - btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx, roll_ptr, mtr); @@ -2860,7 +2923,8 @@ btr_cur_parse_del_mark_set_sec_rec( /* We do not need to reserve btr_search_latch, as the page is only being recovered, and there cannot be a hash index to - it. */ + it. Besides, the delete-mark flag is being updated in place + and the adaptive hash index does not depend on it. */ btr_rec_set_deleted_flag(rec, page_zip, val); } @@ -2886,6 +2950,11 @@ btr_cur_del_mark_set_sec_rec( rec_t* rec; ulint err; + if (thr && thr_get_trx(thr)->fake_changes) { + /* skip LOCK, CHANGE, LOG */ + return(DB_SUCCESS); + } + block = btr_cur_get_block(cursor); rec = btr_cur_get_rec(cursor); @@ -2908,16 +2977,11 @@ btr_cur_del_mark_set_sec_rec( ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(cursor->index->table)); - if (block->is_hashed) { - rw_lock_x_lock(btr_search_get_latch(cursor->index->id)); - } - + /* We do not need to reserve btr_search_latch, as the + delete-mark flag is being updated in place and the adaptive + hash index does not depend on it. */ btr_rec_set_deleted_flag(rec, buf_block_get_page_zip(block), val); - if (block->is_hashed) { - rw_lock_x_unlock(btr_search_get_latch(cursor->index->id)); - } - btr_cur_del_mark_set_sec_rec_log(rec, val, mtr); return(DB_SUCCESS); @@ -2938,8 +3002,11 @@ btr_cur_set_deleted_flag_for_ibuf( ibool val, /*!< in: value to set */ mtr_t* mtr) /*!< in: mtr */ { - /* We do not need to reserve btr_search_latch, as the page has just - been read to the buffer pool and there cannot be a hash index to it. */ + /* We do not need to reserve btr_search_latch, as the page + has just been read to the buffer pool and there cannot be + a hash index to it. Besides, the delete-mark flag is being + updated in place and the adaptive hash index does not depend + on it. */ btr_rec_set_deleted_flag(rec, page_zip, val); @@ -3598,7 +3665,6 @@ static void btr_record_not_null_field_in_rec( /*=============================*/ - rec_t* rec, /*!< in: physical record */ ulint n_unique, /*!< in: dict_index_get_n_unique(index), number of columns uniquely determine an index entry */ @@ -3618,9 +3684,8 @@ btr_record_not_null_field_in_rec( for (i = 0; i < n_unique; i++) { ulint rec_len; - byte* field; - field = rec_get_nth_field(rec, offsets, i, &rec_len); + rec_get_nth_field_offs(offsets, i, &rec_len); if (rec_len != UNIV_SQL_NULL) { n_not_null[i]++; @@ -3740,7 +3805,7 @@ btr_estimate_number_of_different_key_vals( if (n_not_null) { btr_record_not_null_field_in_rec( - rec, n_cols, offsets_rec, n_not_null); + n_cols, offsets_rec, n_not_null); } } @@ -3775,7 +3840,7 @@ btr_estimate_number_of_different_key_vals( if (n_not_null) { btr_record_not_null_field_in_rec( - next_rec, n_cols, offsets_next_rec, + n_cols, offsets_next_rec, n_not_null); } @@ -4184,7 +4249,7 @@ btr_blob_free( && buf_block_get_space(block) == space && buf_block_get_page_no(block) == page_no) { - if (buf_LRU_free_block(&block->page, all, TRUE) != BUF_LRU_FREED + if (!buf_LRU_free_block(&block->page, all, TRUE) && all && block->page.zip.data /* Now, buf_LRU_free_block() may release mutex temporarily */ && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE diff --git a/btr/btr0pcur.c b/btr/btr0pcur.c index f95a5487c94..081ef9c9457 100644 --- a/btr/btr0pcur.c +++ b/btr/btr0pcur.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -272,8 +272,10 @@ btr_pcur_restore_position_func( file, line, mtr))) { cursor->pos_state = BTR_PCUR_IS_POSITIONED; - buf_block_dbg_add_level(btr_pcur_get_block(cursor), - SYNC_TREE_NODE); + buf_block_dbg_add_level( + btr_pcur_get_block(cursor), + dict_index_is_ibuf(index) + ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); if (cursor->rel_pos == BTR_PCUR_ON) { #ifdef UNIV_DEBUG @@ -362,33 +364,6 @@ btr_pcur_restore_position_func( return(FALSE); } -/**************************************************************//** -If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY, -releases the page latch and bufferfix reserved by the cursor. -NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes -made by the current mini-transaction to the data protected by the -cursor latch, as then the latch must not be released until mtr_commit. */ -UNIV_INTERN -void -btr_pcur_release_leaf( -/*==================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr) /*!< in: mtr */ -{ - buf_block_t* block; - - ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - block = btr_pcur_get_block(cursor); - - btr_leaf_page_release(block, cursor->latch_mode, mtr); - - cursor->latch_mode = BTR_NO_LATCHES; - - cursor->pos_state = BTR_PCUR_WAS_POSITIONED; -} - /*********************************************************//** Moves the persistent cursor to the first record on the next page. Releases the latch on the current page, and bufferunfixes it. Note that there must not be @@ -423,7 +398,8 @@ btr_pcur_move_to_next_page( ut_ad(next_page_no != FIL_NULL); next_block = btr_block_get(space, zip_size, next_page_no, - cursor->latch_mode, mtr); + cursor->latch_mode, + btr_pcur_get_btr_cur(cursor)->index, mtr); next_page = buf_block_get_frame(next_block); if (srv_pass_corrupt_table && !next_page) { diff --git a/btr/btr0sea.c b/btr/btr0sea.c index 0630b634b53..f27afe216ec 100644 --- a/btr/btr0sea.c +++ b/btr/btr0sea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -878,6 +878,7 @@ btr_search_guess_on_hash( btr_pcur_t pcur; #endif ut_ad(index && info && tuple && cursor && mtr); + ut_ad(!dict_index_is_ibuf(index)); ut_ad((latch_mode == BTR_SEARCH_LEAF) || (latch_mode == BTR_MODIFY_LEAF)); diff --git a/buf/buf0buddy.c b/buf/buf0buddy.c index 07898950fab..9c1ff645260 100644 --- a/buf/buf0buddy.c +++ b/buf/buf0buddy.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,6 +56,14 @@ buf_buddy_get( } } +/** Validate a given zip_free list. */ +#define BUF_BUDDY_LIST_VALIDATE(b, i) \ + UT_LIST_VALIDATE(zip_list, buf_page_t, \ + b->zip_free[i], \ + ut_ad(buf_page_get_state( \ + ut_list_node_313) \ + == BUF_BLOCK_ZIP_FREE)) + /**********************************************************************//** Add a block to the head of the appropriate buddy free list. */ UNIV_INLINE @@ -67,22 +75,11 @@ buf_buddy_add_to_free( ulint i) /*!< in: index of buf_pool->zip_free[] */ { -#ifdef UNIV_DEBUG_VALGRIND - buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); - - if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i); -#endif /* UNIV_DEBUG_VALGRIND */ - //ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(&buf_pool->zip_free_mutex)); ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); ut_ad(buf_pool->zip_free[i].start != bpage); UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_free[i], bpage); - -#ifdef UNIV_DEBUG_VALGRIND - if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i); - UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i); -#endif /* UNIV_DEBUG_VALGRIND */ } /**********************************************************************//** @@ -96,26 +93,18 @@ buf_buddy_remove_from_free( ulint i) /*!< in: index of buf_pool->zip_free[] */ { -#ifdef UNIV_DEBUG_VALGRIND +#ifdef UNIV_DEBUG buf_page_t* prev = UT_LIST_GET_PREV(zip_list, bpage); buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage); - if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i); - if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i); - ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE); ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE); -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* UNIV_DEBUG */ //ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(&buf_pool->zip_free_mutex)); ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); UT_LIST_REMOVE(zip_list, buf_pool->zip_free[i], bpage); - -#ifdef UNIV_DEBUG_VALGRIND - if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i); - if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i); -#endif /* UNIV_DEBUG_VALGRIND */ } /**********************************************************************//** @@ -133,17 +122,13 @@ buf_buddy_alloc_zip( //ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(&buf_pool->zip_free_mutex)); ut_a(i < BUF_BUDDY_SIZES); + ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); + + ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i)); -#ifndef UNIV_DEBUG_VALGRIND - /* Valgrind would complain about accessing free memory. */ - ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], - ut_ad(buf_page_get_state(ut_list_node_313) - == BUF_BLOCK_ZIP_FREE))); -#endif /* !UNIV_DEBUG_VALGRIND */ bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]); if (bpage) { - UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i); ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); buf_buddy_remove_from_free(buf_pool, bpage, i); @@ -162,13 +147,10 @@ buf_buddy_alloc_zip( } } -#ifdef UNIV_DEBUG if (bpage) { - memset(bpage, ~i, BUF_BUDDY_LOW << i); + ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i)); + UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i); } -#endif /* UNIV_DEBUG */ - - UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i); return(bpage); } @@ -264,6 +246,7 @@ buf_buddy_alloc_from( { ulint offs = BUF_BUDDY_LOW << j; ut_ad(j <= BUF_BUDDY_SIZES); + ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); ut_ad(j >= i); ut_ad(!ut_align_offset(buf, offs)); @@ -277,13 +260,7 @@ buf_buddy_alloc_from( bpage = (buf_page_t*) ((byte*) buf + offs); ut_d(memset(bpage, j, BUF_BUDDY_LOW << j)); bpage->state = BUF_BLOCK_ZIP_FREE; -#ifndef UNIV_DEBUG_VALGRIND - /* Valgrind would complain about accessing free memory. */ - ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], - ut_ad(buf_page_get_state( - ut_list_node_313) - == BUF_BLOCK_ZIP_FREE))); -#endif /* !UNIV_DEBUG_VALGRIND */ + ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i)); buf_buddy_add_to_free(buf_pool, bpage, j); } @@ -293,28 +270,29 @@ buf_buddy_alloc_from( /**********************************************************************//** Allocate a block. The thread calling this function must hold buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. -The buf_pool->mutex may only be released and reacquired if lru != NULL. -@return allocated block, possibly NULL if lru==NULL */ +The buf_pool_mutex may be released and reacquired. +@return allocated block, never NULL */ UNIV_INTERN void* buf_buddy_alloc_low( /*================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ ulint i, /*!< in: index of buf_pool->zip_free[], or BUF_BUDDY_SIZES */ ibool* lru, /*!< in: pointer to a variable that will be assigned TRUE if storage was allocated from the LRU list and buf_pool->mutex was temporarily - released, or NULL if the LRU list - should not be used */ + released */ ibool have_page_hash_mutex) { buf_block_t* block; + ut_ad(lru); //ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(&buf_pool->LRU_list_mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); + ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); if (i < BUF_BUDDY_SIZES) { /* Try to allocate from the buddy system. */ @@ -335,11 +313,6 @@ buf_buddy_alloc_low( goto alloc_big; } - if (!lru) { - - return(NULL); - } - /* Try replacing an uncompressed page in the buffer pool. */ //buf_pool_mutex_exit(buf_pool); mutex_exit(&buf_pool->LRU_list_mutex); @@ -369,76 +342,6 @@ func_exit: } /**********************************************************************//** -Try to relocate the control block of a compressed page. -@return TRUE if relocated */ -static -ibool -buf_buddy_relocate_block( -/*=====================*/ - buf_page_t* bpage, /*!< in: block to relocate */ - buf_page_t* dpage) /*!< in: free block to relocate to */ -{ - buf_page_t* b; - buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); - - //ut_ad(buf_pool_mutex_own(buf_pool)); -#ifdef UNIV_SYNC_DEBUG - ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)); -#endif - - switch (buf_page_get_state(bpage)) { - case BUF_BLOCK_ZIP_FREE: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_FILE_PAGE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - /* ut_error; */ /* optimistic */ - case BUF_BLOCK_ZIP_DIRTY: - /* Cannot relocate dirty pages. */ - return(FALSE); - - case BUF_BLOCK_ZIP_PAGE: - break; - } - - mutex_enter(&buf_pool->zip_mutex); - mutex_enter(&buf_pool->zip_free_mutex); - - if (!buf_page_can_relocate(bpage)) { - mutex_exit(&buf_pool->zip_mutex); - mutex_exit(&buf_pool->zip_free_mutex); - return(FALSE); - } - - if (bpage != buf_page_hash_get(buf_pool, - bpage->space, bpage->offset)) { - mutex_exit(&buf_pool->zip_mutex); - mutex_exit(&buf_pool->zip_free_mutex); - return(FALSE); - } - - buf_relocate(bpage, dpage); - ut_d(bpage->state = BUF_BLOCK_ZIP_FREE); - - /* relocate buf_pool->zip_clean */ - b = UT_LIST_GET_PREV(zip_list, dpage); - UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, dpage); - - if (b) { - UT_LIST_INSERT_AFTER(zip_list, buf_pool->zip_clean, b, dpage); - } else { - UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, dpage); - } - - UNIV_MEM_INVALID(bpage, sizeof *bpage); - - mutex_exit(&buf_pool->zip_mutex); - mutex_exit(&buf_pool->zip_free_mutex); - return(TRUE); -} - -/**********************************************************************//** Try to relocate a block. @return TRUE if relocated */ static @@ -454,164 +357,122 @@ buf_buddy_relocate( { buf_page_t* bpage; const ulint size = BUF_BUDDY_LOW << i; - ullint usec = ut_time_us(NULL); + mutex_t* mutex; + ulint space; + ulint page_no; //ut_ad(buf_pool_mutex_own(buf_pool)); ut_ad(mutex_own(&buf_pool->zip_free_mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(!ut_align_offset(src, size)); ut_ad(!ut_align_offset(dst, size)); + ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); UNIV_MEM_ASSERT_W(dst, size); + if (!have_page_hash_mutex) { + mutex_exit(&buf_pool->zip_free_mutex); + mutex_enter(&buf_pool->LRU_list_mutex); + rw_lock_x_lock(&buf_pool->page_hash_latch); + } + /* We assume that all memory from buf_buddy_alloc() - is used for either compressed pages or buf_page_t - objects covering compressed pages. */ + is used for compressed page frames. */ /* We look inside the allocated objects returned by - buf_buddy_alloc() and assume that anything of - PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains - a valid space_id and page_no in the page header. Should the - fields be invalid, we will be unable to relocate the block. - We also assume that anything that fits sizeof(buf_page_t) - actually is a properly initialized buf_page_t object. */ - - if (size >= PAGE_ZIP_MIN_SIZE) { - /* This is a compressed page. */ - mutex_t* mutex; - ulint space, page_no; + buf_buddy_alloc() and assume that each block is a compressed + page that contains a valid space_id and page_no in the page + header. Should the fields be invalid, we will be unable to + relocate the block. */ + + /* The src block may be split into smaller blocks, + some of which may be free. Thus, the + mach_read_from_4() calls below may attempt to read + from free memory. The memory is "owned" by the buddy + allocator (and it has been allocated from the buffer + pool), so there is nothing wrong about this. The + mach_read_from_4() calls here will only trigger bogus + Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */ + space = mach_read_from_4((const byte *) src + + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + page_no = mach_read_from_4((const byte *) src + + FIL_PAGE_OFFSET); + /* Suppress Valgrind warnings about conditional jump + on uninitialized value. */ + UNIV_MEM_VALID(&space, sizeof space); + UNIV_MEM_VALID(&page_no, sizeof page_no); + bpage = buf_page_hash_get(buf_pool, space, page_no); + + if (!bpage || bpage->zip.data != src) { + /* The block has probably been freshly + allocated by buf_LRU_get_free_block() but not + added to buf_pool->page_hash yet. Obviously, + it cannot be relocated. */ if (!have_page_hash_mutex) { - mutex_exit(&buf_pool->zip_free_mutex); - mutex_enter(&buf_pool->LRU_list_mutex); - rw_lock_x_lock(&buf_pool->page_hash_latch); - } - - /* The src block may be split into smaller blocks, - some of which may be free. Thus, the - mach_read_from_4() calls below may attempt to read - from free memory. The memory is "owned" by the buddy - allocator (and it has been allocated from the buffer - pool), so there is nothing wrong about this. The - mach_read_from_4() calls here will only trigger bogus - Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */ - space = mach_read_from_4( - (const byte*) src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - page_no = mach_read_from_4( - (const byte*) src + FIL_PAGE_OFFSET); - /* Suppress Valgrind warnings about conditional jump - on uninitialized value. */ - UNIV_MEM_VALID(&space, sizeof space); - UNIV_MEM_VALID(&page_no, sizeof page_no); - bpage = buf_page_hash_get(buf_pool, space, page_no); - - if (!bpage || bpage->zip.data != src) { - /* The block has probably been freshly - allocated by buf_LRU_get_free_block() but not - added to buf_pool->page_hash yet. Obviously, - it cannot be relocated. */ - - if (!have_page_hash_mutex) { - mutex_enter(&buf_pool->zip_free_mutex); - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - } - return(FALSE); - } - - ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage)); - - if (page_zip_get_size(&bpage->zip) != size) { - /* The block is of different size. We would - have to relocate all blocks covered by src. - For the sake of simplicity, give up. */ - ut_ad(page_zip_get_size(&bpage->zip) < size); - - if (!have_page_hash_mutex) { - mutex_enter(&buf_pool->zip_free_mutex); - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - } - return(FALSE); + mutex_enter(&buf_pool->zip_free_mutex); + mutex_exit(&buf_pool->LRU_list_mutex); + rw_lock_x_unlock(&buf_pool->page_hash_latch); } + return(FALSE); + } - /* To keep latch order */ - if (have_page_hash_mutex) - mutex_exit(&buf_pool->zip_free_mutex); - - /* The block must have been allocated, but it may - contain uninitialized data. */ - UNIV_MEM_ASSERT_W(src, size); - - mutex = buf_page_get_mutex_enter(bpage); - - mutex_enter(&buf_pool->zip_free_mutex); - - if (mutex && buf_page_can_relocate(bpage)) { - /* Relocate the compressed page. */ - ut_a(bpage->zip.data == src); - memcpy(dst, src, size); - bpage->zip.data = dst; - mutex_exit(mutex); -success: - UNIV_MEM_INVALID(src, size); - { - buf_buddy_stat_t* buddy_stat - = &buf_pool->buddy_stat[i]; - buddy_stat->relocated++; - buddy_stat->relocated_usec - += ut_time_us(NULL) - usec; - } - - if (!have_page_hash_mutex) { - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - } - return(TRUE); - } + if (page_zip_get_size(&bpage->zip) != size) { + /* The block is of different size. We would + have to relocate all blocks covered by src. + For the sake of simplicity, give up. */ + ut_ad(page_zip_get_size(&bpage->zip) < size); if (!have_page_hash_mutex) { + mutex_enter(&buf_pool->zip_free_mutex); mutex_exit(&buf_pool->LRU_list_mutex); rw_lock_x_unlock(&buf_pool->page_hash_latch); } + return(FALSE); + } - if (mutex) { - mutex_exit(mutex); - } - } else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) { - /* This must be a buf_page_t object. */ -#if UNIV_WORD_SIZE == 4 - /* On 32-bit systems, there is no padding in - buf_page_t. On other systems, Valgrind could complain - about uninitialized pad bytes. */ - UNIV_MEM_ASSERT_RW(src, size); -#endif - + /* To keep latch order */ + if (have_page_hash_mutex) mutex_exit(&buf_pool->zip_free_mutex); - if (!have_page_hash_mutex) { - mutex_enter(&buf_pool->LRU_list_mutex); - rw_lock_x_lock(&buf_pool->page_hash_latch); - } + /* The block must have been allocated, but it may + contain uninitialized data. */ + UNIV_MEM_ASSERT_W(src, size); - if (buf_buddy_relocate_block(src, dst)) { - mutex_enter(&buf_pool->zip_free_mutex); + mutex = buf_page_get_mutex_enter(bpage); - if (!have_page_hash_mutex) { - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - } + mutex_enter(&buf_pool->zip_free_mutex); - goto success; + if (mutex && buf_page_can_relocate(bpage)) { + /* Relocate the compressed page. */ + ullint usec = ut_time_us(NULL); + ut_a(bpage->zip.data == src); + memcpy(dst, src, size); + bpage->zip.data = dst; + mutex_exit(mutex); + UNIV_MEM_INVALID(src, size); + { + buf_buddy_stat_t* buddy_stat + = &buf_pool->buddy_stat[i]; + buddy_stat->relocated++; + buddy_stat->relocated_usec + += ut_time_us(NULL) - usec; } - mutex_enter(&buf_pool->zip_free_mutex); - if (!have_page_hash_mutex) { mutex_exit(&buf_pool->LRU_list_mutex); rw_lock_x_unlock(&buf_pool->page_hash_latch); } + return(TRUE); } + if (!have_page_hash_mutex) { + mutex_exit(&buf_pool->LRU_list_mutex); + rw_lock_x_unlock(&buf_pool->page_hash_latch); + } + + if (mutex) { + mutex_exit(mutex); + } return(FALSE); } @@ -635,12 +496,13 @@ buf_buddy_free_low( ut_ad(mutex_own(&buf_pool->zip_free_mutex)); ut_ad(!mutex_own(&buf_pool->zip_mutex)); ut_ad(i <= BUF_BUDDY_SIZES); + ut_ad(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); ut_ad(buf_pool->buddy_stat[i].used > 0); buf_pool->buddy_stat[i].used--; recombine: UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i); - ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE); + ((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE; if (i == BUF_BUDDY_SIZES) { mutex_exit(&buf_pool->zip_free_mutex); @@ -653,32 +515,36 @@ recombine: ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i)); ut_ad(!buf_pool_contains_zip(buf_pool, buf)); - /* Try to combine adjacent blocks. */ + /* Do not recombine blocks if there are few free blocks. + We may waste up to 15360*max_len bytes to free blocks + (1024 + 2048 + 4096 + 8192 = 15360) */ + if (UT_LIST_GET_LEN(buf_pool->zip_free[i]) < 16) { + goto func_exit; + } + /* Try to combine adjacent blocks. */ buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i); #ifndef UNIV_DEBUG_VALGRIND - /* Valgrind would complain about accessing free memory. */ + /* When Valgrind instrumentation is not enabled, we can read + buddy->state to quickly determine that a block is not free. + When the block is not free, buddy->state belongs to a compressed + page frame that may be flagged uninitialized in our Valgrind + instrumentation. */ if (buddy->state != BUF_BLOCK_ZIP_FREE) { goto buddy_nonfree; } - - /* The field buddy->state can only be trusted for free blocks. - If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if - it is in the free list. */ #endif /* !UNIV_DEBUG_VALGRIND */ for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) { - UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i); ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); if (bpage == buddy) { -buddy_free: /* The buddy is free: recombine */ buf_buddy_remove_from_free(buf_pool, bpage, i); -buddy_free2: +buddy_is_free: ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE); ut_ad(!buf_pool_contains_zip(buf_pool, buddy)); i++; @@ -688,122 +554,42 @@ buddy_free2: } ut_a(bpage != buf); - - { - buf_page_t* next = UT_LIST_GET_NEXT(zip_list, bpage); - UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i); - bpage = next; - } + UNIV_MEM_ASSERT_W(bpage, BUF_BUDDY_LOW << i); + bpage = UT_LIST_GET_NEXT(zip_list, bpage); } #ifndef UNIV_DEBUG_VALGRIND buddy_nonfree: - /* Valgrind would complain about accessing free memory. */ - ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], - ut_ad(buf_page_get_state(ut_list_node_313) - == BUF_BLOCK_ZIP_FREE))); -#endif /* UNIV_DEBUG_VALGRIND */ +#endif /* !UNIV_DEBUG_VALGRIND */ + + ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i)); /* The buddy is not free. Is there a free block of this size? */ bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]); if (bpage) { + /* Remove the block from the free list, because a successful buf_buddy_relocate() will overwrite bpage->list. */ - - UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i); buf_buddy_remove_from_free(buf_pool, bpage, i); /* Try to relocate the buddy of buf to the free block. */ if (buf_buddy_relocate(buf_pool, buddy, bpage, i, have_page_hash_mutex)) { - ut_d(buddy->state = BUF_BLOCK_ZIP_FREE); - goto buddy_free2; + buddy->state = BUF_BLOCK_ZIP_FREE; + goto buddy_is_free; } buf_buddy_add_to_free(buf_pool, bpage, i); - - /* Try to relocate the buddy of the free block to buf. */ - buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage), - BUF_BUDDY_LOW << i); - -#ifndef UNIV_DEBUG_VALGRIND - /* Valgrind would complain about accessing free memory. */ - - /* The buddy must not be (completely) free, because we - always recombine adjacent free blocks. - - (Parts of the buddy can be free in - buf_pool->zip_free[j] with j < i.) */ - ut_d(UT_LIST_VALIDATE(zip_list, buf_page_t, buf_pool->zip_free[i], - ut_ad(buf_page_get_state( - ut_list_node_313) - == BUF_BLOCK_ZIP_FREE - && ut_list_node_313 != buddy))); -#endif /* !UNIV_DEBUG_VALGRIND */ - - if (buf_buddy_relocate(buf_pool, buddy, buf, i, have_page_hash_mutex)) { - - buf = bpage; - UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i); - ut_d(buddy->state = BUF_BLOCK_ZIP_FREE); - goto buddy_free; - } } +func_exit: /* Free the block to the buddy list. */ bpage = buf; -#ifdef UNIV_DEBUG - if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) { - /* This area has most likely been allocated for at - least one compressed-only block descriptor. Check - that there are no live objects in the area. This is - not a complete check: it may yield false positives as - well as false negatives. Also, due to buddy blocks - being recombined, it is possible (although unlikely) - that this branch is never reached. */ - - char* c; - -# ifndef UNIV_DEBUG_VALGRIND - /* Valgrind would complain about accessing - uninitialized memory. Besides, Valgrind performs a - more exhaustive check, at every memory access. */ - const buf_page_t* b = buf; - const buf_page_t* const b_end = (buf_page_t*) - ((char*) b + (BUF_BUDDY_LOW << i)); - - for (; b < b_end; b++) { - /* Avoid false positives (and cause false - negatives) by checking for b->space < 1000. */ - - if ((b->state == BUF_BLOCK_ZIP_PAGE - || b->state == BUF_BLOCK_ZIP_DIRTY) - && b->space > 0 && b->space < 1000) { - fprintf(stderr, - "buddy dirty %p %u (%u,%u) %p,%lu\n", - (void*) b, - b->state, b->space, b->offset, - buf, i); - } - } -# endif /* !UNIV_DEBUG_VALGRIND */ - - /* Scramble the block. This should make any pointers - invalid and trigger a segmentation violation. Because - the scrambling can be reversed, it may be possible to - track down the object pointing to the freed data by - dereferencing the unscrambled bpage->LRU or - bpage->list pointers. */ - for (c = (char*) buf + (BUF_BUDDY_LOW << i); - c-- > (char*) buf; ) { - *c = ~*c ^ i; - } - } else { - /* Fill large blocks with a constant pattern. */ - memset(bpage, i, BUF_BUDDY_LOW << i); - } -#endif /* UNIV_DEBUG */ + + /* Fill large blocks with a constant pattern. */ + ut_d(memset(bpage, i, BUF_BUDDY_LOW << i)); + UNIV_MEM_INVALID(bpage, BUF_BUDDY_LOW << i); bpage->state = BUF_BLOCK_ZIP_FREE; buf_buddy_add_to_free(buf_pool, bpage, i); } diff --git a/buf/buf0buf.c b/buf/buf0buf.c index d588d2b90f9..b75a7c82f42 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -442,6 +442,7 @@ buf_get_total_stat( tot_stat->n_pages_read += buf_stat->n_pages_read; tot_stat->n_pages_written += buf_stat->n_pages_written; tot_stat->n_pages_created += buf_stat->n_pages_created; + tot_stat->n_ra_pages_read_rnd += buf_stat->n_ra_pages_read_rnd; tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read; tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted; tot_stat->n_pages_made_young += buf_stat->n_pages_made_young; @@ -1196,72 +1197,6 @@ buf_chunk_not_freed( return(NULL); } -/*********************************************************************//** -Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state. -@return TRUE if all freed */ -static -ibool -buf_chunk_all_free( -/*===============*/ - const buf_chunk_t* chunk) /*!< in: chunk being checked */ -{ - const buf_block_t* block; - ulint i; - - block = chunk->blocks; - - for (i = chunk->size; i--; block++) { - - if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) { - - return(FALSE); - } - } - - return(TRUE); -} - -/********************************************************************//** -Frees a chunk of buffer frames. */ -static -void -buf_chunk_free( -/*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - buf_chunk_t* chunk) /*!< out: chunk of buffers */ -{ - buf_block_t* block; - const buf_block_t* block_end; - - //ut_ad(buf_pool_mutex_own(buf_pool)); /* but we need all mutex here */ - - block_end = chunk->blocks + chunk->size; - - for (block = chunk->blocks; block < block_end; block++) { - ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED); - ut_a(!block->page.zip.data); - - ut_ad(!block->page.in_LRU_list); - ut_ad(!block->in_unzip_LRU_list); - ut_ad(!block->page.in_flush_list); - /* Remove the block from the free list. */ - mutex_enter(&buf_pool->free_list_mutex); - ut_ad(block->page.in_free_list); - UT_LIST_REMOVE(free, buf_pool->free, (&block->page)); - mutex_exit(&buf_pool->free_list_mutex); - - /* Free the latches. */ - mutex_free(&block->mutex); - rw_lock_free(&block->lock); -#ifdef UNIV_SYNC_DEBUG - rw_lock_free(&block->debug_latch); -#endif /* UNIV_SYNC_DEBUG */ - UNIV_MEM_UNDESC(block); - } - - os_mem_free_large(chunk->mem, chunk->mem_size); -} - /********************************************************************//** Set buffer pool size variables after resizing it */ static @@ -1387,8 +1322,6 @@ buf_pool_free_instance( chunk = chunks + buf_pool->n_chunks; while (--chunk >= chunks) { - /* Bypass the checks of buf_chunk_free(), since they - would fail at shutdown. */ os_mem_free_large(chunk->mem, chunk->mem_size); } @@ -1656,290 +1589,6 @@ buf_relocate( } /********************************************************************//** -Shrinks a buffer pool instance. */ -static -void -buf_pool_shrink_instance( -/*=====================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - ulint chunk_size) /*!< in: number of pages to remove */ -{ - buf_chunk_t* chunks; - buf_chunk_t* chunk; - ulint max_size; - ulint max_free_size; - buf_chunk_t* max_chunk; - buf_chunk_t* max_free_chunk; - - ut_ad(!buf_pool_mutex_own(buf_pool)); - -try_again: - btr_search_disable(); /* Empty the adaptive hash index again */ - //buf_pool_mutex_enter(buf_pool); - mutex_enter(&buf_pool->LRU_list_mutex); - -shrink_again: - if (buf_pool->n_chunks <= 1) { - - /* Cannot shrink if there is only one chunk */ - goto func_done; - } - - /* Search for the largest free chunk - not larger than the size difference */ - chunks = buf_pool->chunks; - chunk = chunks + buf_pool->n_chunks; - max_size = max_free_size = 0; - max_chunk = max_free_chunk = NULL; - - while (--chunk >= chunks) { - if (chunk->size <= chunk_size - && chunk->size > max_free_size) { - if (chunk->size > max_size) { - max_size = chunk->size; - max_chunk = chunk; - } - - if (buf_chunk_all_free(chunk)) { - max_free_size = chunk->size; - max_free_chunk = chunk; - } - } - } - - if (!max_free_size) { - - ulint dirty = 0; - ulint nonfree = 0; - buf_block_t* block; - buf_block_t* bend; - - /* Cannot shrink: try again later - (do not assign srv_buf_pool_old_size) */ - if (!max_chunk) { - - goto func_exit; - } - - block = max_chunk->blocks; - bend = block + max_chunk->size; - - /* Move the blocks of chunk to the end of the - LRU list and try to flush them. */ - for (; block < bend; block++) { - switch (buf_block_get_state(block)) { - case BUF_BLOCK_NOT_USED: - continue; - case BUF_BLOCK_FILE_PAGE: - break; - default: - nonfree++; - continue; - } - - mutex_enter(&block->mutex); - /* The following calls will temporarily - release block->mutex and buf_pool->mutex. - Therefore, we have to always retry, - even if !dirty && !nonfree. */ - - if (!buf_flush_ready_for_replace(&block->page)) { - - buf_LRU_make_block_old(&block->page); - dirty++; - } else if (buf_LRU_free_block(&block->page, TRUE, TRUE) - != BUF_LRU_FREED) { - nonfree++; - } - - mutex_exit(&block->mutex); - } - - //buf_pool_mutex_exit(buf_pool); - mutex_exit(&buf_pool->LRU_list_mutex); - - /* Request for a flush of the chunk if it helps. - Do not flush if there are non-free blocks, since - flushing will not make the chunk freeable. */ - if (nonfree) { - /* Avoid busy-waiting. */ - os_thread_sleep(100000); - } else if (dirty - && buf_flush_LRU(buf_pool, dirty) - == ULINT_UNDEFINED) { - - buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU); - } - - goto try_again; - } - - max_size = max_free_size; - max_chunk = max_free_chunk; - - buf_pool->old_pool_size = buf_pool->curr_pool_size; - - /* Rewrite buf_pool->chunks. Copy everything but max_chunk. */ - chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks); - memcpy(chunks, buf_pool->chunks, - (max_chunk - buf_pool->chunks) * sizeof *chunks); - memcpy(chunks + (max_chunk - buf_pool->chunks), - max_chunk + 1, - buf_pool->chunks + buf_pool->n_chunks - - (max_chunk + 1)); - ut_a(buf_pool->curr_size > max_chunk->size); - buf_pool->curr_size -= max_chunk->size; - buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE; - chunk_size -= max_chunk->size; - buf_chunk_free(buf_pool, max_chunk); - mem_free(buf_pool->chunks); - buf_pool->chunks = chunks; - buf_pool->n_chunks--; - - /* Allow a slack of one megabyte. */ - if (chunk_size > 1048576 / UNIV_PAGE_SIZE) { - - goto shrink_again; - } - goto func_exit; - -func_done: - buf_pool->old_pool_size = buf_pool->curr_pool_size; -func_exit: - //buf_pool_mutex_exit(buf_pool); - mutex_exit(&buf_pool->LRU_list_mutex); - btr_search_enable(); -} - -/********************************************************************//** -Shrinks the buffer pool. */ -static -void -buf_pool_shrink( -/*============*/ - ulint chunk_size) /*!< in: number of pages to remove */ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool; - ulint instance_chunk_size; - - instance_chunk_size = chunk_size / srv_buf_pool_instances; - buf_pool = buf_pool_from_array(i); - buf_pool_shrink_instance(buf_pool, instance_chunk_size); - } - - buf_pool_set_sizes(); -} - -/********************************************************************//** -Rebuild buf_pool->page_hash for a buffer pool instance. */ -static -void -buf_pool_page_hash_rebuild_instance( -/*================================*/ - buf_pool_t* buf_pool) /*!< in: buffer pool instance */ -{ - ulint i; - buf_page_t* b; - buf_chunk_t* chunk; - ulint n_chunks; - hash_table_t* zip_hash; - hash_table_t* page_hash; - - //buf_pool_mutex_enter(buf_pool); - mutex_enter(&buf_pool->LRU_list_mutex); - rw_lock_x_lock(&buf_pool->page_hash_latch); - - /* Free, create, and populate the hash table. */ - hash_table_free(buf_pool->page_hash); - buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size); - zip_hash = hash_create(2 * buf_pool->curr_size); - - HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash, - BUF_POOL_ZIP_FOLD_BPAGE); - - hash_table_free(buf_pool->zip_hash); - buf_pool->zip_hash = zip_hash; - - /* Insert the uncompressed file pages to buf_pool->page_hash. */ - - chunk = buf_pool->chunks; - n_chunks = buf_pool->n_chunks; - - for (i = 0; i < n_chunks; i++, chunk++) { - ulint j; - buf_block_t* block = chunk->blocks; - - for (j = 0; j < chunk->size; j++, block++) { - if (buf_block_get_state(block) - == BUF_BLOCK_FILE_PAGE) { - ut_ad(!block->page.in_zip_hash); - ut_ad(block->page.in_page_hash); - - HASH_INSERT(buf_page_t, hash, page_hash, - buf_page_address_fold( - block->page.space, - block->page.offset), - &block->page); - } - } - } - - /* Insert the compressed-only pages to buf_pool->page_hash. - All such blocks are either in buf_pool->zip_clean or - in buf_pool->flush_list. */ - - mutex_enter(&buf_pool->zip_mutex); - for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b; - b = UT_LIST_GET_NEXT(zip_list, b)) { - ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE); - ut_ad(!b->in_flush_list); - ut_ad(b->in_LRU_list); - ut_ad(b->in_page_hash); - ut_ad(!b->in_zip_hash); - - HASH_INSERT(buf_page_t, hash, page_hash, - buf_page_address_fold(b->space, b->offset), b); - } - mutex_exit(&buf_pool->zip_mutex); - - buf_flush_list_mutex_enter(buf_pool); - for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b; - b = UT_LIST_GET_NEXT(flush_list, b)) { - ut_ad(b->in_flush_list); - ut_ad(b->in_LRU_list); - ut_ad(b->in_page_hash); - ut_ad(!b->in_zip_hash); - - switch (buf_page_get_state(b)) { - case BUF_BLOCK_ZIP_DIRTY: - HASH_INSERT(buf_page_t, hash, page_hash, - buf_page_address_fold(b->space, - b->offset), b); - break; - case BUF_BLOCK_FILE_PAGE: - /* uncompressed page */ - break; - case BUF_BLOCK_ZIP_FREE: - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_NOT_USED: - case BUF_BLOCK_READY_FOR_USE: - case BUF_BLOCK_MEMORY: - case BUF_BLOCK_REMOVE_HASH: - ut_error; - break; - } - } - - buf_flush_list_mutex_exit(buf_pool); - //buf_pool_mutex_exit(buf_pool); - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); -} - -/******************************************************************** Determine if a block is a sentinel for a buffer pool watch. @return TRUE if a sentinel for a buffer pool watch, FALSE if not */ UNIV_INTERN @@ -2060,127 +1709,6 @@ buf_pool_watch_set( return(NULL); } -/********************************************************************//** -Rebuild buf_pool->page_hash. */ -static -void -buf_pool_page_hash_rebuild(void) -/*============================*/ -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i)); - } -} - -/********************************************************************//** -Increase the buffer pool size of one buffer pool instance. */ -static -void -buf_pool_increase_instance( -/*=======================*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instane */ - ulint change_size) /*!< in: new size of the pool */ -{ - buf_chunk_t* chunks; - buf_chunk_t* chunk; - - mutex_enter(&buf_pool->LRU_list_mutex); - rw_lock_x_lock(&buf_pool->page_hash_latch); - buf_pool_mutex_enter(buf_pool); - chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks); - - memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks); - - chunk = &chunks[buf_pool->n_chunks]; - - if (!buf_chunk_init(buf_pool, chunk, change_size)) { - mem_free(chunks); - } else { - buf_pool->old_pool_size = buf_pool->curr_pool_size; - buf_pool->curr_size += chunk->size; - buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE; - mem_free(buf_pool->chunks); - buf_pool->chunks = chunks; - buf_pool->n_chunks++; - } - - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); - buf_pool_mutex_exit(buf_pool); -} - -/********************************************************************//** -Increase the buffer pool size. */ -static -void -buf_pool_increase( -/*==============*/ - ulint change_size) -{ - ulint i; - - for (i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_increase_instance( - buf_pool_from_array(i), - change_size / srv_buf_pool_instances); - } - - buf_pool_set_sizes(); -} - -/********************************************************************//** -Resizes the buffer pool. */ -UNIV_INTERN -void -buf_pool_resize(void) -/*=================*/ -{ - ulint change_size; - ulint min_change_size = 1048576 * srv_buf_pool_instances; - - buf_pool_mutex_enter_all(); - - if (srv_buf_pool_old_size == srv_buf_pool_size) { - - buf_pool_mutex_exit_all(); - - return; - - } else if (srv_buf_pool_curr_size + min_change_size - > srv_buf_pool_size) { - - change_size = (srv_buf_pool_curr_size - srv_buf_pool_size) - / UNIV_PAGE_SIZE; - - buf_pool_mutex_exit_all(); - - /* Disable adaptive hash indexes and empty the index - in order to free up memory in the buffer pool chunks. */ - buf_pool_shrink(change_size); - - } else if (srv_buf_pool_curr_size + min_change_size - < srv_buf_pool_size) { - - /* Enlarge the buffer pool by at least one megabyte */ - - change_size = srv_buf_pool_size - srv_buf_pool_curr_size; - - buf_pool_mutex_exit_all(); - - buf_pool_increase(change_size); - } else { - srv_buf_pool_size = srv_buf_pool_old_size; - - buf_pool_mutex_exit_all(); - - return; - } - - buf_pool_page_hash_rebuild(); -} - /****************************************************************//** Remove the sentinel block for the watch before replacing it with a real block. buf_page_watch_clear() or buf_page_watch_occurred() will notice that @@ -2524,6 +2052,27 @@ 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: @@ -2580,7 +2129,7 @@ err_exit: } /* Discard the uncompressed page frame if possible. */ - if (buf_LRU_free_block(bpage, FALSE, TRUE) == BUF_LRU_FREED) { + if (buf_LRU_free_block(bpage, FALSE, TRUE)) { mutex_exit(&buf_pool->LRU_list_mutex); mutex_exit(block_mutex); goto lookup; @@ -3010,12 +2559,8 @@ loop: block_mutex = buf_page_get_mutex_enter((buf_page_t*)block); /* If the guess is a compressed page descriptor that - has been allocated by buf_buddy_alloc(), it may have - been invalidated by buf_buddy_relocate(). In that - case, block could point to something that happens to - contain the expected bits in block->page. Similarly, - the guess may be pointing to a buffer pool chunk that - has been released when resizing the buffer pool. */ + has been allocated by buf_page_alloc_descriptor(), + it may have been freed by buf_relocate(). */ if (!block_mutex) { block = guess = NULL; @@ -3038,6 +2583,27 @@ 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); } @@ -3075,6 +2641,9 @@ loop2: } if (buf_read_page(space, zip_size, offset, trx)) { + buf_read_ahead_random(space, zip_size, offset, + ibuf_inside(mtr), trx); + retries = 0; } else if (retries < BUF_PAGE_READ_MAX_RETRIES) { ++retries; @@ -3237,8 +2806,10 @@ wait_until_unfixed: if (buf_page_get_state(&block->page) == BUF_BLOCK_ZIP_PAGE) { +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, &block->page); +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ ut_ad(!block->page.in_flush_list); } else { /* Relocate buf_pool->flush_list. */ @@ -3269,11 +2840,10 @@ wait_until_unfixed: buf_pool->n_pend_unzip++; buf_pool_mutex_exit(buf_pool); - bpage->state = BUF_BLOCK_ZIP_FREE; - buf_buddy_free(buf_pool, bpage, sizeof *bpage, FALSE); - //buf_pool_mutex_exit(buf_pool); + buf_page_free_descriptor(bpage); + /* Decompress the page and apply buffered operations while not holding buf_pool->mutex or block->mutex. */ success = buf_zip_decompress(block, srv_use_checksums); @@ -3322,7 +2892,7 @@ wait_until_unfixed: /* Try to evict the block from the buffer pool, to use the insert buffer (change buffer) as much as possible. */ - if (buf_LRU_free_block(&block->page, TRUE, FALSE) == BUF_LRU_FREED) { + if (buf_LRU_free_block(&block->page, TRUE, FALSE)) { mutex_exit(block_mutex); if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) { /* Set the watch, as it would have @@ -3809,19 +3379,20 @@ buf_page_init_low( /********************************************************************//** Inits a page to the buffer buf_pool. */ -static +static __attribute__((nonnull)) void buf_page_init( /*==========*/ + buf_pool_t* buf_pool,/*!< in/out: buffer pool */ ulint space, /*!< in: space id */ ulint offset, /*!< in: offset of the page within space in units of a page */ ulint fold, /*!< in: buf_page_address_fold(space,offset) */ - buf_block_t* block) /*!< in: block to init */ + buf_block_t* block) /*!< in/out: block to init */ { buf_page_t* hash_page; - buf_pool_t* buf_pool = buf_pool_get(space, offset); + ut_ad(buf_pool == buf_pool_get(space, offset)); //ut_ad(buf_pool_mutex_own(buf_pool)); #ifdef UNIV_SYNC_DEBUG ut_ad(rw_lock_own(&buf_pool->page_hash_latch, RW_LOCK_EX)); @@ -3955,11 +3526,28 @@ 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; @@ -3995,7 +3583,7 @@ err_exit: ut_ad(buf_pool_from_bpage(bpage) == buf_pool); - buf_page_init(space, offset, fold, block); + buf_page_init(buf_pool, space, offset, fold, block); rw_lock_x_unlock(&buf_pool->page_hash_latch); @@ -4042,20 +3630,11 @@ err_exit: mutex_exit(&buf_pool->LRU_list_mutex); mutex_exit(&block->mutex); } else { - /* Defer buf_buddy_alloc() until after the block has - been found not to exist. The buf_buddy_alloc() and - buf_buddy_free() calls may be expensive because of - buf_buddy_relocate(). */ - /* The compressed page must be allocated before the control block (bpage), in order to avoid the invocation of buf_buddy_relocate_block() on uninitialized data. */ data = buf_buddy_alloc(buf_pool, zip_size, &lru, TRUE); - bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru, TRUE); - - /* Initialize the buf_pool pointer. */ - bpage->buf_pool_index = buf_pool_index(buf_pool); /* If buf_buddy_alloc() allocated storage from the LRU list, it released and reacquired buf_pool->mutex. Thus, we must @@ -4071,8 +3650,6 @@ err_exit: /* The block was added by some other thread. */ watch_page = NULL; - bpage->state = BUF_BLOCK_ZIP_FREE; - buf_buddy_free(buf_pool, bpage, sizeof *bpage, TRUE); buf_buddy_free(buf_pool, data, zip_size, TRUE); mutex_exit(&buf_pool->LRU_list_mutex); @@ -4083,6 +3660,11 @@ err_exit: } } + bpage = buf_page_alloc_descriptor(); + + /* Initialize the buf_pool pointer. */ + bpage->buf_pool_index = buf_pool_index(buf_pool); + page_zip_des_init(&bpage->zip); page_zip_set_size(&bpage->zip, zip_size); bpage->zip.data = data; @@ -4098,7 +3680,6 @@ err_exit: bpage->offset = offset; bpage->space_was_being_deleted = FALSE; - #ifdef UNIV_DEBUG bpage->in_page_hash = FALSE; bpage->in_zip_hash = FALSE; @@ -4125,7 +3706,9 @@ err_exit: /* The block must be put to the LRU list, to the old blocks */ buf_LRU_add_block(bpage, TRUE/* to old blocks */); +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG buf_LRU_insert_zip_clean(bpage); +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ mutex_exit(&buf_pool->LRU_list_mutex); @@ -4180,6 +3763,7 @@ 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); @@ -4187,6 +3771,21 @@ buf_page_create( 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)) { @@ -4221,7 +3820,7 @@ buf_page_create( mutex_enter(&block->mutex); - buf_page_init(space, offset, fold, block); + buf_page_init(buf_pool, space, offset, fold, block); rw_lock_x_unlock(&buf_pool->page_hash_latch); /* The block must be put to the LRU list */ @@ -4307,6 +3906,59 @@ buf_page_create( } /********************************************************************//** +Mark a table with the specified space pointed by bpage->space corrupted. +Also remove the bpage from LRU list. +@return TRUE if successful */ +static +ibool +buf_mark_space_corrupt( +/*===================*/ + buf_page_t* bpage) /*!< in: pointer to the block in question */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + const ibool uncompressed = (buf_page_get_state(bpage) + == BUF_BLOCK_FILE_PAGE); + ulint space = bpage->space; + ibool ret = TRUE; + + /* First unfix and release lock on the bpage */ + //buf_pool_mutex_enter(buf_pool); + mutex_enter(&buf_pool->LRU_list_mutex); + rw_lock_x_lock(&buf_pool->page_hash_latch); + mutex_enter(buf_page_get_mutex(bpage)); + ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ); + ut_ad(bpage->buf_fix_count == 0); + + /* Set BUF_IO_NONE before we remove the block from LRU list */ + buf_page_set_io_fix(bpage, BUF_IO_NONE); + + if (uncompressed) { + rw_lock_x_unlock_gen( + &((buf_block_t*) bpage)->lock, + BUF_IO_READ); + } + + /* Find the table with specified space id, and mark it corrupted */ + if (dict_set_corrupted_by_space(space)) { + buf_LRU_free_one_page(bpage); + } else { + ret = FALSE; + } + + buf_pool_mutex_enter(buf_pool); + ut_ad(buf_pool->n_pend_reads > 0); + buf_pool->n_pend_reads--; + buf_pool_mutex_exit(buf_pool); + + mutex_exit(buf_page_get_mutex(bpage)); + //buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->LRU_list_mutex); + rw_lock_x_unlock(&buf_pool->page_hash_latch); + + return(ret); +} + +/********************************************************************//** Completes an asynchronous read or write request of a file page to or from the buffer pool. */ UNIV_INTERN @@ -4452,10 +4104,19 @@ corrupt: bpage->is_corrupt = TRUE; } else if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { - fputs("InnoDB: Ending processing because of" - " a corrupt database page.\n", - stderr); - exit(1); + /* If page space id is larger than TRX_SYS_SPACE + (0), we will attempt to mark the corresponding + table as corrupted instead of crashing server */ + if (bpage->space > TRX_SYS_SPACE + && buf_mark_space_corrupt(bpage)) { + return; + } else { + fputs("InnoDB: Ending processing" + " because of" + " a corrupt database page.\n", + stderr); + ut_error; + } } } } /**/ @@ -4478,8 +4139,11 @@ corrupt: } if (io_type == BUF_IO_WRITE - && (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY - || buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) { + && ( +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG + buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY || +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ + buf_page_get_flush_type(bpage) == BUF_FLUSH_LRU)) { /* to keep consistency at buf_LRU_insert_zip_clean() */ have_LRU_mutex = TRUE; /* optimistic */ } @@ -5314,6 +4978,7 @@ buf_stats_aggregate_pool_info( total_info->n_pages_created += pool_info->n_pages_created; total_info->n_pages_written += pool_info->n_pages_written; total_info->n_page_gets += pool_info->n_page_gets; + total_info->n_ra_pages_read_rnd += pool_info->n_ra_pages_read_rnd; total_info->n_ra_pages_read += pool_info->n_ra_pages_read; total_info->n_ra_pages_evicted += pool_info->n_ra_pages_evicted; total_info->page_made_young_rate += pool_info->page_made_young_rate; @@ -5326,6 +4991,7 @@ buf_stats_aggregate_pool_info( total_info->page_read_delta += pool_info->page_read_delta; total_info->young_making_delta += pool_info->young_making_delta; total_info->not_young_making_delta += pool_info->not_young_making_delta; + total_info->pages_readahead_rnd_rate += pool_info->pages_readahead_rnd_rate; total_info->pages_readahead_rate += pool_info->pages_readahead_rate; total_info->pages_evicted_rate += pool_info->pages_evicted_rate; total_info->unzip_lru_len += pool_info->unzip_lru_len; @@ -5407,6 +5073,7 @@ buf_stats_get_pool_info( pool_info->n_page_gets = buf_pool->stat.n_page_gets; + pool_info->n_ra_pages_read_rnd = buf_pool->stat.n_ra_pages_read_rnd; pool_info->n_ra_pages_read = buf_pool->stat.n_ra_pages_read; pool_info->n_ra_pages_evicted = buf_pool->stat.n_ra_pages_evicted; @@ -5446,6 +5113,10 @@ buf_stats_get_pool_info( buf_pool->stat.n_pages_not_made_young - buf_pool->old_stat.n_pages_not_made_young; } + pool_info->pages_readahead_rnd_rate = + (buf_pool->stat.n_ra_pages_read_rnd + - buf_pool->old_stat.n_ra_pages_read_rnd) / time_elapsed; + pool_info->pages_readahead_rate = (buf_pool->stat.n_ra_pages_read @@ -5535,9 +5206,12 @@ buf_print_io_instance( /* Statistics about read ahead algorithm */ fprintf(file, "Pages read ahead %.2f/s," - " evicted without access %.2f/s\n", + " evicted without access %.2f/s," + " Random read ahead %.2f/s\n", + pool_info->pages_readahead_rate, - pool_info->pages_evicted_rate); + pool_info->pages_evicted_rate, + pool_info->pages_readahead_rnd_rate); /* Print some values to help us with visualizing what is happening with LRU eviction. */ diff --git a/buf/buf0flu.c b/buf/buf0flu.c index 09d11dd21db..73a9ff96289 100644 --- a/buf/buf0flu.c +++ b/buf/buf0flu.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -534,7 +534,9 @@ buf_flush_remove( case BUF_BLOCK_ZIP_DIRTY: buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE); UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage); +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG buf_LRU_insert_zip_clean(bpage); +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ break; case BUF_BLOCK_FILE_PAGE: UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage); diff --git a/buf/buf0lru.c b/buf/buf0lru.c index c92e72a1729..06ce43a4d2d 100644 --- a/buf/buf0lru.c +++ b/buf/buf0lru.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -390,39 +390,41 @@ scan_again: while (bpage != NULL) { buf_page_t* prev_bpage; - ibool prev_bpage_buf_fix = FALSE; + mutex_t* block_mutex = NULL; ut_a(buf_page_in_file(bpage)); prev_bpage = UT_LIST_GET_PREV(LRU, bpage); /* bpage->space and bpage->io_fix are protected by - buf_pool->mutex and block_mutex. It is safe to check - them while holding buf_pool->mutex only. */ + buf_pool_mutex and block_mutex. It is safe to check + them while holding buf_pool_mutex only. */ if (buf_page_get_space(bpage) != id) { /* Skip this block, as it does not belong to the space that is being invalidated. */ + goto next_page; } else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) { /* We cannot remove this page during this scan yet; maybe the system is currently reading it in, or flushing the modifications to the file */ all_freed = FALSE; + goto next_page; } else { - mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); + block_mutex = buf_page_get_mutex_enter(bpage); if (!block_mutex) { /* It may be impossible case... Something wrong, so will be scan_again */ all_freed = FALSE; - - goto next_page_no_mutex; + goto next_page; } if (bpage->buf_fix_count > 0) { + mutex_exit(block_mutex); /* We cannot remove this page during this scan yet; maybe the system is currently reading it in, or flushing @@ -432,108 +434,61 @@ scan_again: goto next_page; } + } + + ut_ad(mutex_own(block_mutex)); #ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Dropping space %lu page %lu\n", - (ulong) buf_page_get_space(bpage), - (ulong) buf_page_get_page_no(bpage)); - } + if (buf_debug_prints) { + fprintf(stderr, + "Dropping space %lu page %lu\n", + (ulong) buf_page_get_space(bpage), + (ulong) buf_page_get_page_no(bpage)); + } #endif - if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { - /* This is a compressed-only block - descriptor. Ensure that prev_bpage - cannot be relocated when bpage is freed. */ - if (UNIV_LIKELY(prev_bpage != NULL)) { - switch (buf_page_get_state( - prev_bpage)) { - case BUF_BLOCK_FILE_PAGE: - /* Descriptors of uncompressed - blocks will not be relocated, - because we are holding the - buf_pool->mutex. */ - break; - case BUF_BLOCK_ZIP_PAGE: - case BUF_BLOCK_ZIP_DIRTY: - /* Descriptors of compressed- - only blocks can be relocated, - unless they are buffer-fixed. - Because both bpage and - prev_bpage are protected by - buf_pool_zip_mutex, it is - not necessary to acquire - further mutexes. */ - ut_ad(&buf_pool->zip_mutex - == block_mutex); - ut_ad(mutex_own(block_mutex)); - prev_bpage_buf_fix = TRUE; - prev_bpage->buf_fix_count++; - break; - default: - ut_error; - } - } - } else if (((buf_block_t*) bpage)->is_hashed) { - ulint page_no; - ulint zip_size; - - //buf_pool_mutex_exit(buf_pool); - mutex_exit(&buf_pool->LRU_list_mutex); - rw_lock_x_unlock(&buf_pool->page_hash_latch); + if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { + /* This is a compressed-only block + descriptor. Do nothing. */ + } else if (((buf_block_t*) bpage)->is_hashed) { + ulint page_no; + ulint zip_size; - zip_size = buf_page_get_zip_size(bpage); - page_no = buf_page_get_page_no(bpage); + //buf_pool_mutex_exit(buf_pool); + mutex_exit(&buf_pool->LRU_list_mutex); + rw_lock_x_unlock(&buf_pool->page_hash_latch); - mutex_exit(block_mutex); + zip_size = buf_page_get_zip_size(bpage); + page_no = buf_page_get_page_no(bpage); - /* Note that the following call will acquire - an S-latch on the page */ + mutex_exit(block_mutex); - btr_search_drop_page_hash_when_freed( - id, zip_size, page_no); - goto scan_again; - } + /* Note that the following call will acquire + an S-latch on the page */ - if (bpage->oldest_modification != 0) { + btr_search_drop_page_hash_when_freed( + id, zip_size, page_no); + goto scan_again; + } - buf_flush_remove(bpage); - } + if (bpage->oldest_modification != 0) { - /* Remove from the LRU list. */ + buf_flush_remove(bpage); + } - if (buf_LRU_block_remove_hashed_page(bpage, TRUE) - != BUF_BLOCK_ZIP_FREE) { - buf_LRU_block_free_hashed_page((buf_block_t*) - bpage, TRUE); - } else { - /* The block_mutex should have been - released by buf_LRU_block_remove_hashed_page() - when it returns BUF_BLOCK_ZIP_FREE. */ - ut_ad(block_mutex == &buf_pool->zip_mutex); - ut_ad(!mutex_own(block_mutex)); - - if (prev_bpage_buf_fix) { - /* We temporarily buffer-fixed - prev_bpage, so that - buf_buddy_free() could not - relocate it, in case it was a - compressed-only block - descriptor. */ - - mutex_enter(block_mutex); - ut_ad(prev_bpage->buf_fix_count > 0); - prev_bpage->buf_fix_count--; - mutex_exit(block_mutex); - } + /* Remove from the LRU list. */ - goto next_page_no_mutex; - } -next_page: + if (buf_LRU_block_remove_hashed_page(bpage, TRUE) + != BUF_BLOCK_ZIP_FREE) { + buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE); mutex_exit(block_mutex); + } else { + /* The block_mutex should have been released + by buf_LRU_block_remove_hashed_page() when it + returns BUF_BLOCK_ZIP_FREE. */ + ut_ad(block_mutex == &buf_pool->zip_mutex); + ut_ad(!mutex_own(block_mutex)); } - -next_page_no_mutex: +next_page: bpage = prev_bpage; } @@ -587,6 +542,8 @@ buf_LRU_mark_space_was_deleted( for (i = 0; i < srv_buf_pool_instances; i++) { buf_pool_t* buf_pool; buf_page_t* bpage; + buf_chunk_t* chunk; + ulint j, k; buf_pool = buf_pool_from_array(i); @@ -602,9 +559,33 @@ buf_LRU_mark_space_was_deleted( } mutex_exit(&buf_pool->LRU_list_mutex); + + btr_search_s_lock_all(); + chunk = buf_pool->chunks; + for (j = buf_pool->n_chunks; j--; chunk++) { + buf_block_t* block = chunk->blocks; + for (k = chunk->size; k--; block++) { + if (buf_block_get_state(block) + != BUF_BLOCK_FILE_PAGE + || !block->is_hashed + || buf_page_get_space(&block->page) != id) { + continue; + } + + btr_search_s_unlock_all(); + + rw_lock_x_lock(&block->lock); + btr_search_drop_page_hash_index(block, NULL); + rw_lock_x_unlock(&block->lock); + + btr_search_s_lock_all(); + } + } + btr_search_s_unlock_all(); } } +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** Insert a compressed block into buf_pool->zip_clean in the LRU order. */ UNIV_INTERN @@ -639,6 +620,7 @@ buf_LRU_insert_zip_clean( UT_LIST_ADD_FIRST(zip_list, buf_pool->zip_clean, bpage); } } +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ /******************************************************************//** Try to free an uncompressed page of a compressed block from the unzip @@ -684,7 +666,7 @@ restart: UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0); block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) { - enum buf_lru_free_block_status freed; + ibool freed; mutex_enter(&block->mutex); if (!block->in_unzip_LRU_list || !block->page.in_LRU_list @@ -700,24 +682,9 @@ restart: freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex); mutex_exit(&block->mutex); - switch (freed) { - case BUF_LRU_FREED: + if (freed) { return(TRUE); - - case BUF_LRU_CANNOT_RELOCATE: - /* If we failed to relocate, try - regular LRU eviction. */ - return(FALSE); - - case BUF_LRU_NOT_FREED: - /* The block was buffer-fixed or I/O-fixed. - Keep looking. */ - continue; } - - /* inappropriate return value from - buf_LRU_free_block() */ - ut_error; } return(FALSE); @@ -752,10 +719,9 @@ restart: UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0); bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) { - enum buf_lru_free_block_status freed; - unsigned accessed; - mutex_t* block_mutex - = buf_page_get_mutex_enter(bpage); + ibool freed; + unsigned accessed; + mutex_t* block_mutex = buf_page_get_mutex_enter(bpage); if (!block_mutex) { goto restart; @@ -774,8 +740,7 @@ restart: freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex); mutex_exit(block_mutex); - switch (freed) { - case BUF_LRU_FREED: + if (freed) { /* Keep track of pages that are evicted without ever being accessed. This gives us a measure of the effectiveness of readahead */ @@ -783,21 +748,7 @@ restart: ++buf_pool->stat.n_ra_pages_evicted; } return(TRUE); - - case BUF_LRU_NOT_FREED: - /* The block was dirty, buffer-fixed, or I/O-fixed. - Keep looking. */ - continue; - - case BUF_LRU_CANNOT_RELOCATE: - /* This should never occur, because we - want to discard the compressed page too. */ - break; } - - /* inappropriate return value from - buf_LRU_free_block() */ - ut_error; } return(FALSE); @@ -1549,17 +1500,16 @@ buf_LRU_make_block_old( Try to free a block. If bpage is a descriptor of a compressed-only page, the descriptor object will be freed as well. -NOTE: If this function returns BUF_LRU_FREED, it will temporarily +NOTE: If this function returns TRUE, it will temporarily release buf_pool->mutex. Furthermore, the page frame will no longer be accessible via bpage. The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and release these two mutexes after the call. No other buf_page_get_mutex() may be held when calling this function. -@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or -BUF_LRU_NOT_FREED otherwise. */ +@return TRUE if freed, FALSE otherwise. */ UNIV_INTERN -enum buf_lru_free_block_status +ibool buf_LRU_free_block( /*===============*/ buf_page_t* bpage, /*!< in: block to be freed */ @@ -1586,7 +1536,7 @@ buf_LRU_free_block( if (!bpage->in_LRU_list || !block_mutex || !buf_page_can_relocate(bpage)) { /* Do not free buffer-fixed or I/O-fixed blocks. */ - return(BUF_LRU_NOT_FREED); + return(FALSE); } if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) { @@ -1602,7 +1552,7 @@ buf_LRU_free_block( /* Do not completely free dirty blocks. */ if (bpage->oldest_modification) { - return(BUF_LRU_NOT_FREED); + return(FALSE); } } else if (bpage->oldest_modification) { /* Do not completely free dirty blocks. */ @@ -1610,7 +1560,7 @@ buf_LRU_free_block( if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) { ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_DIRTY); - return(BUF_LRU_NOT_FREED); + return(FALSE); } goto alloc; @@ -1619,14 +1569,8 @@ buf_LRU_free_block( If it cannot be allocated (without freeing a block from the LRU list), refuse to free bpage. */ alloc: - //buf_pool_mutex_exit_forbid(buf_pool); - b = buf_buddy_alloc(buf_pool, sizeof *b, NULL, FALSE); - //buf_pool_mutex_exit_allow(buf_pool); - - if (UNIV_UNLIKELY(!b)) { - return(BUF_LRU_CANNOT_RELOCATE); - } - + b = buf_page_alloc_descriptor(); + ut_a(b); //memcpy(b, bpage, sizeof *b); } @@ -1656,7 +1600,7 @@ not_freed: if (!have_LRU_mutex) mutex_exit(&buf_pool->LRU_list_mutex); rw_lock_x_unlock(&buf_pool->page_hash_latch); - return(BUF_LRU_NOT_FREED); + return(FALSE); } else if (zip || !bpage->zip.data) { if (bpage->oldest_modification) goto not_freed; @@ -1768,7 +1712,9 @@ not_freed: mutex_enter(&buf_pool->zip_mutex); if (b->state == BUF_BLOCK_ZIP_PAGE) { +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG buf_LRU_insert_zip_clean(b); +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ } else { /* Relocate on buf_pool->flush_list. */ buf_flush_relocate_on_flush_list(bpage, b); @@ -1844,7 +1790,7 @@ not_freed: rw_lock_x_unlock(&buf_pool->page_hash_latch); } - return(BUF_LRU_FREED); + return(TRUE); } /******************************************************************//** @@ -2073,7 +2019,9 @@ buf_LRU_block_remove_hashed_page( ut_a(bpage->zip.data); ut_a(buf_page_get_zip_size(bpage)); +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_REMOVE(zip_list, buf_pool->zip_clean, bpage); +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ mutex_exit(&buf_pool->zip_mutex); //buf_pool_mutex_exit_forbid(buf_pool); @@ -2082,11 +2030,8 @@ buf_LRU_block_remove_hashed_page( buf_pool, bpage->zip.data, page_zip_get_size(&bpage->zip), TRUE); - bpage->state = BUF_BLOCK_ZIP_FREE; - buf_buddy_free(buf_pool, bpage, sizeof(*bpage), TRUE); //buf_pool_mutex_exit_allow(buf_pool); - - UNIV_MEM_UNDESC(bpage); + buf_page_free_descriptor(bpage); return(BUF_BLOCK_ZIP_FREE); case BUF_BLOCK_FILE_PAGE: @@ -2154,6 +2099,22 @@ buf_LRU_block_free_hashed_page( buf_LRU_block_free_non_file_page(block, have_page_hash_mutex); } +/******************************************************************//** +Remove one page from LRU list and put it to free list */ +UNIV_INTERN +void +buf_LRU_free_one_page( +/*==================*/ + buf_page_t* bpage) /*!< in/out: block, must contain a file page and + be in a state where it can be freed; there + may or may not be a hash index to the page */ +{ + if (buf_LRU_block_remove_hashed_page(bpage, TRUE) + != BUF_BLOCK_ZIP_FREE) { + buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE); + } +} + /**********************************************************************//** Updates buf_pool->LRU_old_ratio for one buffer pool instance. @return updated old_pct */ @@ -2445,6 +2406,11 @@ buf_LRU_file_restore(void) " InnoDB: cannot open %s\n", LRU_DUMP_FILE); goto end; } + + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Restoring buffer pool pages from %s\n", + LRU_DUMP_FILE); + if (size == 0 || size_high > 0 || size % 8) { fprintf(stderr, " InnoDB: broken LRU dump file\n"); goto end; @@ -2546,7 +2512,7 @@ buf_LRU_file_restore(void) ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: reading pages based on the dumped LRU list was done." + " InnoDB: Completed reading buffer pool pages" " (requested: %lu, read: %lu)\n", req, reads); ret = TRUE; end: diff --git a/buf/buf0rea.c b/buf/buf0rea.c index 587b982b3e0..645d5fdc2f3 100644 --- a/buf/buf0rea.c +++ b/buf/buf0rea.c @@ -40,8 +40,10 @@ Created 11/5/1995 Heikki Tuuri #include "mysql/plugin.h" #include "mysql/service_thd_wait.h" -/** The linear read-ahead area size */ -#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA +/** There must be at least this many pages in buf_pool in the area to start +a random read-ahead */ +#define BUF_READ_AHEAD_RANDOM_THRESHOLD(b) \ + (5 + BUF_READ_AHEAD_AREA(b) / 8) /** If there are buf_pool->curr_size per the number below pending reads, then read-ahead is not done: this is to prevent flooding the buffer pool with @@ -212,6 +214,172 @@ not_to_recover: } /********************************************************************//** +Applies a random read-ahead in buf_pool if there are at least a threshold +value of accessed pages from the random read-ahead area. Does not read any +page, not even the one at the position (space, offset), if the read-ahead +mechanism is not activated. NOTE 1: the calling thread may own latches on +pages: to avoid deadlocks this function must be written such that it cannot +end up waiting for these latches! NOTE 2: the calling thread must want +access to the page given: this rule is set to prevent unintended read-aheads +performed by ibuf routines, a situation which could result in a deadlock if +the OS does not support asynchronous i/o. +@return number of page read requests issued; NOTE that if we read ibuf +pages, it may happen that the page at the given page number does not +get read even if we return a positive value! +@return number of page read requests issued */ +UNIV_INTERN +ulint +buf_read_ahead_random( +/*==================*/ + ulint space, /*!< in: space id */ + ulint zip_size, /*!< in: compressed page size in bytes, + or 0 */ + ulint offset, /*!< in: page number of a page which + the current thread wants to access */ + ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf + routine */ + trx_t* trx) +{ + buf_pool_t* buf_pool = buf_pool_get(space, offset); + ib_int64_t tablespace_version; + ulint recent_blocks = 0; + ulint ibuf_mode; + ulint count; + ulint low, high; + ulint err; + ulint i; + const ulint buf_read_ahead_random_area + = BUF_READ_AHEAD_AREA(buf_pool); + + if (!srv_random_read_ahead) { + /* Disabled by user */ + return(0); + } + + if (srv_startup_is_before_trx_rollback_phase) { + /* No read-ahead to avoid thread deadlocks */ + return(0); + } + + if (ibuf_bitmap_page(zip_size, offset) + || trx_sys_hdr_page(space, offset)) { + + /* If it is an ibuf bitmap page or trx sys hdr, we do + no read-ahead, as that could break the ibuf page access + order */ + + return(0); + } + + /* Remember the tablespace version before we ask te tablespace size + below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we + do not try to read outside the bounds of the tablespace! */ + + tablespace_version = fil_space_get_version(space); + + low = (offset / buf_read_ahead_random_area) + * buf_read_ahead_random_area; + high = (offset / buf_read_ahead_random_area + 1) + * buf_read_ahead_random_area; + if (high > fil_space_get_size(space)) { + + high = fil_space_get_size(space); + } + + buf_pool_mutex_enter(buf_pool); + + if (buf_pool->n_pend_reads + > buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) { + buf_pool_mutex_exit(buf_pool); + + return(0); + } + + /* Count how many blocks in the area have been recently accessed, + that is, reside near the start of the LRU list. */ + + for (i = low; i < high; i++) { + const buf_page_t* bpage = + buf_page_hash_get(buf_pool, space, i); + + if (bpage + && buf_page_is_accessed(bpage) + && buf_page_peek_if_young(bpage)) { + + recent_blocks++; + + if (recent_blocks + >= BUF_READ_AHEAD_RANDOM_THRESHOLD(buf_pool)) { + + buf_pool_mutex_exit(buf_pool); + goto read_ahead; + } + } + } + + buf_pool_mutex_exit(buf_pool); + /* Do nothing */ + return(0); + +read_ahead: + /* Read all the suitable blocks within the area */ + + if (inside_ibuf) { + ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; + } else { + ibuf_mode = BUF_READ_ANY_PAGE; + } + + count = 0; + + for (i = low; i < high; i++) { + /* It is only sensible to do read-ahead in the non-sync aio + mode: hence FALSE as the first parameter */ + + if (!ibuf_bitmap_page(zip_size, i)) { + count += buf_read_page_low( + &err, FALSE, + ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, + space, zip_size, FALSE, + tablespace_version, i, trx); + if (err == DB_TABLESPACE_DELETED) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Warning: in random" + " readahead trying to access\n" + "InnoDB: tablespace %lu page %lu,\n" + "InnoDB: but the tablespace does not" + " exist or is just being dropped.\n", + (ulong) space, (ulong) i); + } + } + } + + /* In simulated aio we wake the aio handler threads only after + queuing all aio requests, in native aio the following call does + nothing: */ + + os_aio_simulated_wake_handler_threads(); + +#ifdef UNIV_DEBUG + if (buf_debug_prints && (count > 0)) { + fprintf(stderr, + "Random read-ahead space %lu offset %lu pages %lu\n", + (ulong) space, (ulong) offset, + (ulong) count); + } +#endif /* UNIV_DEBUG */ + + /* Read ahead is considered one I/O operation for the purpose of + LRU policy decision. */ + buf_LRU_stat_inc_io(); + + buf_pool->stat.n_ra_pages_read_rnd += count; + srv_buf_pool_reads += count; + return(count); +} + +/********************************************************************//** High-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock @@ -309,7 +477,7 @@ buf_read_ahead_linear( ulint err; ulint i; const ulint buf_read_ahead_linear_area - = BUF_READ_AHEAD_LINEAR_AREA(buf_pool); + = BUF_READ_AHEAD_AREA(buf_pool); ulint threshold; if (!(srv_read_ahead & 2)) { diff --git a/dict/dict0crea.c b/dict/dict0crea.c index 49c16b1daab..b67f7fdde1c 100644 --- a/dict/dict0crea.c +++ b/dict/dict0crea.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -898,7 +898,7 @@ dict_truncate_index_tree( appropriate field in the SYS_INDEXES record: this mini-transaction marks the B-tree totally truncated */ - btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr); + btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr); btr_free_root(space, zip_size, root_page_no, mtr); create: diff --git a/dict/dict0dict.c b/dict/dict0dict.c index 1ad540f47ab..edcacb5919d 100644 --- a/dict/dict0dict.c +++ b/dict/dict0dict.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -54,6 +54,7 @@ UNIV_INTERN dict_index_t* dict_ind_compact; #include "row0merge.h" #include "m_ctype.h" /* my_isspace() */ #include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/ +#include "row0upd.h" #include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */ #include <ctype.h> @@ -612,8 +613,7 @@ dict_table_get_on_id( { dict_table_t* table; - if (table_id <= DICT_FIELDS_ID - || trx->dict_operation_lock_mode == RW_X_LATCH) { + if (trx->dict_operation_lock_mode == RW_X_LATCH) { /* Note: An X latch implies that the transaction already owns the dictionary mutex. */ @@ -1777,7 +1777,8 @@ undo_size_ok: new_index->page = page_no; rw_lock_create(index_tree_rw_lock_key, &new_index->lock, - SYNC_INDEX_TREE); + dict_index_is_ibuf(index) + ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE); if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) { @@ -5522,6 +5523,189 @@ dict_close(void) } } +/**********************************************************************//** +Find a table in dict_sys->table_LRU list with specified space id +@return table if found, NULL if not */ +static +dict_table_t* +dict_find_table_by_space( +/*=====================*/ + ulint space_id) /*!< in: space ID */ +{ + dict_table_t* table; + ulint num_item; + ulint count = 0; + + ut_ad(space_id > 0); + + table = UT_LIST_GET_FIRST(dict_sys->table_LRU); + num_item = UT_LIST_GET_LEN(dict_sys->table_LRU); + + /* This function intentionally does not acquire mutex as it is used + by error handling code in deep call stack as last means to avoid + killing the server, so it worth to risk some consequencies for + the action. */ + while (table && count < num_item) { + if (table->space == space_id) { + return(table); + } + + table = UT_LIST_GET_NEXT(table_LRU, table); + count++; + } + + return(NULL); +} + +/**********************************************************************//** +Flags a table with specified space_id corrupted in the data dictionary +cache +@return TRUE if successful */ +UNIV_INTERN +ibool +dict_set_corrupted_by_space( +/*========================*/ + ulint space_id) /*!< in: space ID */ +{ + dict_table_t* table; + + table = dict_find_table_by_space(space_id); + + if (!table) { + return(FALSE); + } + + /* mark the table->corrupted bit only, since the caller + could be too deep in the stack for SYS_INDEXES update */ + table->corrupted = TRUE; + + return(TRUE); +} + +/**********************************************************************//** +Flags an index corrupted both in the data dictionary cache +and in the SYS_INDEXES */ +UNIV_INTERN +void +dict_set_corrupted( +/*===============*/ + dict_index_t* index) /*!< in/out: index */ +{ + mem_heap_t* heap; + mtr_t mtr; + dict_index_t* sys_index; + dtuple_t* tuple; + dfield_t* dfield; + byte* buf; + const char* status; + btr_cur_t cursor; + + ut_ad(index); + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(!dict_table_is_comp(dict_sys->sys_tables)); + ut_ad(!dict_table_is_comp(dict_sys->sys_indexes)); + +#ifdef UNIV_SYNC_DEBUG + ut_ad(sync_thread_levels_empty_except_dict()); +#endif + + /* Mark the table as corrupted only if the clustered index + is corrupted */ + if (dict_index_is_clust(index)) { + index->table->corrupted = TRUE; + } + + if (UNIV_UNLIKELY(dict_index_is_corrupted(index))) { + /* The index was already flagged corrupted. */ + ut_ad(index->table->corrupted); + return; + } + + heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t) + + sizeof(que_fork_t) + sizeof(upd_node_t) + + sizeof(upd_t) + 12)); + mtr_start(&mtr); + index->type |= DICT_CORRUPT; + + sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes); + + /* Find the index row in SYS_INDEXES */ + tuple = dtuple_create(heap, 2); + + dfield = dtuple_get_nth_field(tuple, 0); + buf = mem_heap_alloc(heap, 8); + mach_write_to_8(buf, index->table->id); + dfield_set_data(dfield, buf, 8); + + dfield = dtuple_get_nth_field(tuple, 1); + buf = mem_heap_alloc(heap, 8); + mach_write_to_8(buf, index->id); + dfield_set_data(dfield, buf, 8); + + dict_index_copy_types(tuple, sys_index, 2); + + btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE, + BTR_MODIFY_LEAF, + &cursor, 0, __FILE__, __LINE__, &mtr); + + if (cursor.up_match == dtuple_get_n_fields(tuple)) { + /* UPDATE SYS_INDEXES SET TYPE=index->type + WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */ + ulint len; + byte* field = rec_get_nth_field_old( + btr_cur_get_rec(&cursor), + DICT_SYS_INDEXES_TYPE_FIELD, &len); + if (len != 4) { + goto fail; + } + mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr); + status = " InnoDB: Flagged corruption of "; + } else { +fail: + status = " InnoDB: Unable to flag corruption of "; + } + + mtr_commit(&mtr); + mem_heap_free(heap); + + ut_print_timestamp(stderr); + fputs(status, stderr); + dict_index_name_print(stderr, NULL, index); + putc('\n', stderr); +} + +/**********************************************************************//** +Flags an index corrupted in the data dictionary cache only. This +is used mostly to mark a corrupted index when index's own dictionary +is corrupted, and we force to load such index for repair purpose */ +UNIV_INTERN +void +dict_set_corrupted_index_cache_only( +/*================================*/ + dict_index_t* index, /*!< in/out: index */ + dict_table_t* table) /*!< in/out: table */ +{ + ut_ad(index); + ut_ad(mutex_own(&dict_sys->mutex)); + ut_ad(!dict_table_is_comp(dict_sys->sys_tables)); + ut_ad(!dict_table_is_comp(dict_sys->sys_indexes)); + + /* Mark the table as corrupted only if the clustered index + is corrupted */ + if (dict_index_is_clust(index)) { + dict_table_t* corrupt_table; + + corrupt_table = table ? table : index->table; + ut_ad(!index->table || !table || index->table == table); + + if (corrupt_table) { + corrupt_table->corrupted = TRUE; + } + } + + index->type |= DICT_CORRUPT; +} + /************************************************************************* set is_corrupt flag by space_id*/ diff --git a/dict/dict0load.c b/dict/dict0load.c index c5bd84f84ad..20b9caf7322 100644 --- a/dict/dict0load.c +++ b/dict/dict0load.c @@ -54,6 +54,11 @@ static const char* SYSTEM_TABLE_NAME[] = { "SYS_FOREIGN_COLS", "SYS_STATS" }; + +/* If this flag is TRUE, then we will load the cluster index's (and tables') +metadata even if it is marked as "corrupted". */ +UNIV_INTERN my_bool srv_load_corrupted = FALSE; + /****************************************************************//** Compare the name of an index column. @return TRUE if the i'th column of index is 'name'. */ @@ -1396,6 +1401,9 @@ err_len: goto err_len; } type = mach_read_from_4(field); + if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) { + return("unknown SYS_INDEXES.TYPE bits"); + } field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len); if (UNIV_UNLIKELY(len != 4)) { @@ -1495,16 +1503,47 @@ dict_load_indexes( goto next_rec; } else if (err_msg) { fprintf(stderr, "InnoDB: %s\n", err_msg); + if (ignore_err & DICT_ERR_IGNORE_CORRUPT) { + goto next_rec; + } error = DB_CORRUPTION; goto func_exit; } ut_ad(index); + /* Check whether the index is corrupted */ + if (dict_index_is_corrupted(index)) { + ut_print_timestamp(stderr); + fputs(" InnoDB: ", stderr); + dict_index_name_print(stderr, NULL, index); + fputs(" is corrupted\n", stderr); + + if (!srv_load_corrupted + && !(ignore_err & DICT_ERR_IGNORE_CORRUPT) + && dict_index_is_clust(index)) { + dict_mem_index_free(index); + + error = DB_INDEX_CORRUPT; + goto func_exit; + } else { + /* We will load the index if + 1) srv_load_corrupted is TRUE + 2) ignore_err is set with + DICT_ERR_IGNORE_CORRUPT + 3) if the index corrupted is a secondary + index */ + ut_print_timestamp(stderr); + fputs(" InnoDB: load corrupted index ", stderr); + dict_index_name_print(stderr, NULL, index); + putc('\n', stderr); + } + } + /* We check for unsupported types first, so that the subsequent checks are relevant for the supported types. */ - if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) { - + if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE + | DICT_CORRUPT)) { fprintf(stderr, "InnoDB: Error: unknown type %lu" " of index %s of table %s\n", @@ -1525,9 +1564,14 @@ dict_load_indexes( /* If caller can tolerate this error, we will continue to load the index and let caller deal with this error. However - mark the index and table corrupted */ - index->corrupted = TRUE; - table->corrupted = TRUE; + mark the index and table corrupted. We + only need to mark such in the index + dictionary cache for such metadata corruption, + since we would always be able to set it + when loading the dictionary cache */ + dict_set_corrupted_index_cache_only( + index, table); + fprintf(stderr, "InnoDB: Index is corrupt but forcing" " load into data dictionary\n"); @@ -1567,9 +1611,10 @@ corrupted: index->name, table->name); /* If the force recovery flag is set, and - if the failed index is not the primary index, we - will continue and open other indexes */ - if (srv_force_recovery + if the failed index is not the clustered index, + we will continue and open other indexes */ + if ((srv_force_recovery + || srv_load_corrupted) && !dict_index_is_clust(index)) { error = DB_SUCCESS; goto next_rec; @@ -1884,6 +1929,30 @@ err_exit: err = dict_load_indexes(table, heap, ignore_err); + if (err == DB_INDEX_CORRUPT) { + /* Refuse to load the table if the table has a corrupted + cluster index */ + if (!srv_load_corrupted) { + fprintf(stderr, "InnoDB: Error: Load table "); + ut_print_name(stderr, NULL, TRUE, table->name); + fprintf(stderr, " failed, the table has corrupted" + " clustered indexes. Turn on" + " 'innodb_force_load_corrupted'" + " to drop it\n"); + + dict_table_remove_from_cache(table); + table = NULL; + goto func_exit; + } else { + dict_index_t* clust_index; + clust_index = dict_table_get_first_index(table); + + if (dict_index_is_corrupted(clust_index)) { + table->corrupted = TRUE; + } + } + } + /* Initialize table foreign_child value. Its value could be changed when dict_load_foreigns() is called below */ table->fk_max_recusive_level = 0; @@ -1910,9 +1979,15 @@ err_exit: index = dict_table_get_first_index(table); if (!srv_force_recovery || !index - || !dict_index_is_clust(index)) { + || !dict_index_is_clust(index)) { dict_table_remove_from_cache(table); table = NULL; + } else if (dict_index_is_corrupted(index)) { + + /* It is possible we force to load a corrupted + clustered index if srv_load_corrupted is set. + Mark the table as corrupted in this case */ + table->corrupted = TRUE; } } #if 0 @@ -1939,6 +2014,7 @@ err_exit: mutex_exit(&dict_foreign_err_mutex); } #endif /* 0 */ +func_exit: mem_heap_free(heap); return(table); diff --git a/fil/fil0fil.c b/fil/fil0fil.c index 0e42214aa31..380f471e67b 100644 --- a/fil/fil0fil.c +++ b/fil/fil0fil.c @@ -3541,7 +3541,7 @@ skip_info: ULINT_UNDEFINED, &heap); n_fields = rec_offs_n_fields(offsets); if (!offset) { - offset = row_get_trx_id_offset(rec, index, offsets); + offset = row_get_trx_id_offset(index, offsets); } trx_write_trx_id(rec + offset, 1); @@ -3826,7 +3826,7 @@ convert_err_exit: ULINT_UNDEFINED, &heap); n_fields = rec_offs_n_fields(offsets); if (!offset) { - offset = row_get_trx_id_offset(rec, index, offsets); + offset = row_get_trx_id_offset(index, offsets); } trx_write_trx_id(rec + offset, 1); diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 7a2d8e8fdbe..26212cca36e 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2011, MySQL AB & Innobase Oy. All Rights Reserved. +Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. @@ -193,16 +193,18 @@ static my_bool innobase_overwrite_relay_log_info = FALSE; static my_bool innobase_rollback_on_timeout = FALSE; static my_bool innobase_create_status_file = FALSE; static my_bool innobase_stats_on_metadata = TRUE; +static my_bool innobase_large_prefix = FALSE; static my_bool innobase_use_sys_stats_table = FALSE; static my_bool innobase_buffer_pool_shm_checksum = TRUE; static uint innobase_buffer_pool_shm_key = 0; -static my_bool innobase_large_prefix = FALSE; static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; +static my_bool innobase_blocking_lru_restore = FALSE; + /** Possible values for system variable "innodb_stats_method". The values are defined the same as its corresponding MyISAM system variable "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */ @@ -486,6 +488,12 @@ static MYSQL_THDVAR_ULONG(flush_log_at_trx_commit, PLUGIN_VAR_OPCMDARG, " or 2 (write at commit, flush once per second).", NULL, NULL, 1, 0, 2, 0); +static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG, + "In the transaction after enabled, UPDATE, INSERT and DELETE only move the cursor to the records " + "and do nothing other operations (no changes, no ibuf, no undo, no transaction log) in the transaction. " + "This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.", + NULL, NULL, FALSE); + static handler *innobase_create_handler(handlerton *hton, TABLE_SHARE *table, @@ -673,6 +681,8 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_buffer_pool_pages_old, SHOW_LONG}, {"buffer_pool_pages_total", (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG}, + {"buffer_pool_read_ahead_rnd", + (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG}, {"buffer_pool_read_ahead", (char*) &export_vars.innodb_buffer_pool_read_ahead, SHOW_LONG}, {"buffer_pool_read_ahead_evicted", @@ -989,6 +999,19 @@ thd_flush_log_at_trx_commit( return(THDVAR((THD*) thd, flush_log_at_trx_commit)); } +/******************************************************************//** +Returns true if expand_fast_index_creation is enabled for the current +session. +@return the value of the server's expand_fast_index_creation variable */ +extern "C" UNIV_INTERN +ibool +thd_expand_fast_index_creation( +/*================================*/ + void* thd) +{ + return((ibool) (((THD*) thd)->variables.expand_fast_index_creation)); +} + /********************************************************************//** Obtain the InnoDB transaction of a MySQL thread. @return reference to transaction pointer */ @@ -1142,7 +1165,6 @@ convert_error_code_to_mysql( misleading, a new MySQL error code should be introduced */ - case DB_COL_APPEARS_TWICE_IN_INDEX: case DB_CORRUPTION: return(HA_ERR_CRASHED); @@ -1194,6 +1216,10 @@ convert_error_code_to_mysql( #endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */ case DB_UNSUPPORTED: return(HA_ERR_UNSUPPORTED); + case DB_INDEX_CORRUPT: + return(HA_ERR_INDEX_CORRUPT); + case DB_UNDO_RECORD_TOO_BIG: + return(HA_ERR_UNDO_REC_TOO_BIG); } } @@ -1682,6 +1708,8 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); + trx->fake_changes = THDVAR(thd, fake_changes); + #ifdef EXTENDED_SLOWLOG if (thd_log_slow_verbosity(thd) & SLOG_V_INNODB) { trx->take_stats = TRUE; @@ -2265,6 +2293,29 @@ no_db_name: } +/*****************************************************************//** +A wrapper function of innobase_convert_name(), convert a table or +index name to the MySQL system_charset_info (UTF-8) and quote it if needed. +@return pointer to the end of buf */ +static inline +void +innobase_format_name( +/*==================*/ + char* buf, /*!< out: buffer for converted identifier */ + ulint buflen, /*!< in: length of buf, in bytes */ + const char* name, /*!< in: index or table name to format */ + ibool is_index_name) /*!< in: index name */ +{ + const char* bufend; + + bufend = innobase_convert_name(buf, buflen, name, strlen(name), + NULL, !is_index_name); + + ut_ad((ulint) (bufend - buf) < buflen); + + buf[bufend - buf] = '\0'; +} + /**********************************************************************//** Determines if the currently running transaction has been interrupted. @return TRUE if interrupted */ @@ -2795,6 +2846,8 @@ innobase_change_buffering_inited_ok: srv_use_checksums = (ibool) innobase_use_checksums; srv_fast_checksum = (ibool) innobase_fast_checksum; + srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore; + #ifdef HAVE_LARGE_PAGES if ((os_use_large_pages = (ibool) my_use_large_pages)) os_large_page_size = (ulint) opt_large_page_size; @@ -2828,6 +2881,10 @@ innobase_change_buffering_inited_ok: innobase_commit_concurrency_init_default(); +#ifndef EXTENDED_FOR_KILLIDLE + srv_kill_idle_transaction = 0; +#endif + #ifdef HAVE_PSI_INTERFACE /* Register keys with MySQL performance schema */ if (PSI_server) { @@ -3160,6 +3217,11 @@ innobase_commit( trx_search_latch_release_if_reserved(trx); } + if (trx->fake_changes && (all || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + innobase_rollback(hton, thd, all); /* rollback implicitly */ + thd->stmt_da->reset_diagnostics_area(); /* because debug assertion code complains, if something left */ + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } /* Transaction is deregistered only in a commit or a rollback. If it is deregistered we know there cannot be resources to be freed and we could return immediately. For the time being, we play safe @@ -4188,11 +4250,11 @@ retry: DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); } - if (share->ib_table) { - ut_a(share->ib_table == ib_table); - } else { - share->ib_table = ib_table; - } + share->ib_table = ib_table; + + + + if (NULL == ib_table) { if (is_part && retries < 10) { @@ -4493,25 +4555,6 @@ field_in_record_is_null( return(0); } -/**************************************************************//** -Sets a field in a record to SQL NULL. Uses the record format -information in table to track the null bit in record. */ -static inline -void -set_field_in_record_to_null( -/*========================*/ - TABLE* table, /*!< in: MySQL table object */ - Field* field, /*!< in: MySQL field object */ - char* record) /*!< in: a row in MySQL format */ -{ - int null_offset; - - null_offset = (uint) ((char*) field->null_ptr - - (char*) table->record[0]); - - record[null_offset] = record[null_offset] | field->null_bit; -} - /*************************************************************//** InnoDB uses this function to compare two data fields for which the data type is such that we must use MySQL code to compare them. NOTE that the prototype @@ -6160,12 +6203,14 @@ ha_innobase::index_read( index = prebuilt->index; - if (UNIV_UNLIKELY(index == NULL)) { + if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) { prebuilt->index_usable = FALSE; DBUG_RETURN(HA_ERR_CRASHED); } if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED); + DBUG_RETURN(dict_index_is_corrupted(index) + ? HA_ERR_INDEX_CORRUPT + : HA_ERR_TABLE_DEF_CHANGED); } /* Note that if the index for which the search template is built is not @@ -6233,7 +6278,7 @@ ha_innobase::index_read( table->status = 0; #ifdef EXTENDED_FOR_USERSTAT rows_read++; - if (active_index >= 0 && active_index < MAX_KEY) + if (active_index < MAX_KEY) index_rows_read[active_index]++; #endif break; @@ -6364,10 +6409,33 @@ ha_innobase::change_active_index( prebuilt->index); if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - HA_ERR_TABLE_DEF_CHANGED, - "InnoDB: insufficient history for index %u", - keynr); + if (dict_index_is_corrupted(prebuilt->index)) { + char index_name[MAX_FULL_NAME_LEN + 1]; + char table_name[MAX_FULL_NAME_LEN + 1]; + + innobase_format_name( + index_name, sizeof index_name, + prebuilt->index->name, TRUE); + + innobase_format_name( + table_name, sizeof table_name, + prebuilt->index->table->name, FALSE); + + push_warning_printf( + user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s for table %s is" + " marked as corrupted", + index_name, table_name); + DBUG_RETURN(1); + } else { + push_warning_printf( + user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: insufficient history for index %u", + keynr); + } + /* The caller seems to ignore this. Thus, we must check this again in row_search_for_mysql(). */ DBUG_RETURN(2); @@ -6459,7 +6527,7 @@ ha_innobase::general_fetch( table->status = 0; #ifdef EXTENDED_FOR_USERSTAT rows_read++; - if (active_index >= 0 && active_index < MAX_KEY) + if (active_index < MAX_KEY) index_rows_read[active_index]++; #endif break; @@ -7503,6 +7571,12 @@ ha_innobase::create( trx = innobase_trx_allocate(thd); + if (trx->fake_changes) { + innobase_commit_low(trx); + trx_free_for_mysql(trx); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + /* Latch the InnoDB data dictionary exclusively so that no deadlocks or lock waits can happen in it during a table create operation. Drop table etc. do this latching in row0mysql.c. */ @@ -7723,6 +7797,10 @@ ha_innobase::truncate(void) DBUG_RETURN(HA_ERR_CRASHED); } + if (prebuilt->trx->fake_changes) { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + /* Truncate the table in InnoDB */ error = row_truncate_table_for_mysql(prebuilt->table, prebuilt->trx); @@ -7779,6 +7857,12 @@ ha_innobase::delete_table( trx = innobase_trx_allocate(thd); + if (trx->fake_changes) { + innobase_commit_low(trx); + trx_free_for_mysql(trx); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + name_len = strlen(name); ut_a(name_len < 1000); @@ -7865,6 +7949,12 @@ innobase_drop_database( trx->mysql_thd = NULL; #else trx = innobase_trx_allocate(thd); + if (trx->fake_changes) { + my_free(namebuf); + innobase_commit_low(trx); + trx_free_for_mysql(trx); + return; /* ignore */ + } #endif row_drop_database_for_mysql(namebuf, trx); my_free(namebuf); @@ -7970,6 +8060,11 @@ ha_innobase::rename_table( trx_search_latch_release_if_reserved(parent_trx); trx = innobase_trx_allocate(thd); + if (trx->fake_changes) { + innobase_commit_low(trx); + trx_free_for_mysql(trx); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } error = innobase_rename_table(trx, from, to, TRUE); @@ -8056,6 +8151,10 @@ ha_innobase::records_in_range( n_rows = HA_POS_ERROR; goto func_exit; } + if (dict_index_is_corrupted(index)) { + n_rows = HA_ERR_INDEX_CORRUPT; + goto func_exit; + } if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) { n_rows = HA_ERR_TABLE_DEF_CHANGED; goto func_exit; @@ -8470,6 +8569,8 @@ ha_innobase::info_low( if (flag & HA_STATUS_VARIABLE) { + ulint page_size; + dict_table_stats_lock(ib_table, RW_S_LATCH); n_rows = ib_table->stat_n_rows; @@ -8512,14 +8613,19 @@ ha_innobase::info_low( prebuilt->autoinc_last_value = 0; } + page_size = dict_table_zip_size(ib_table); + if (page_size == 0) { + page_size = UNIV_PAGE_SIZE; + } + stats.records = (ha_rows)n_rows; stats.deleted = 0; - stats.data_file_length = ((ulonglong) - ib_table->stat_clustered_index_size) - * UNIV_PAGE_SIZE; - stats.index_file_length = ((ulonglong) - ib_table->stat_sum_of_other_index_sizes) - * UNIV_PAGE_SIZE; + stats.data_file_length + = ((ulonglong) ib_table->stat_clustered_index_size) + * page_size; + stats.index_file_length = + ((ulonglong) ib_table->stat_sum_of_other_index_sizes) + * page_size; dict_table_stats_unlock(ib_table, RW_S_LATCH); @@ -8757,6 +8863,7 @@ ha_innobase::check( ulint n_rows_in_table = ULINT_UNDEFINED; ibool is_ok = TRUE; ulint old_isolation_level; + ibool table_corrupted; DBUG_ENTER("ha_innobase::check"); DBUG_ASSERT(thd == ha_thd()); @@ -8798,6 +8905,14 @@ ha_innobase::check( prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; + /* Check whether the table is already marked as corrupted + before running the check table */ + table_corrupted = prebuilt->table->corrupted; + + /* Reset table->corrupted bit so that check table can proceed to + do additional check */ + prebuilt->table->corrupted = FALSE; + /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ mutex_enter(&kernel_mutex); srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ @@ -8806,6 +8921,7 @@ ha_innobase::check( for (index = dict_table_get_first_index(prebuilt->table); index != NULL; index = dict_table_get_next_index(index)) { + char index_name[MAX_FULL_NAME_LEN + 1]; #if 0 fputs("Validating index ", stderr); ut_print_name(stderr, trx, FALSE, index->name); @@ -8814,11 +8930,16 @@ ha_innobase::check( if (!btr_validate_index(index, prebuilt->trx)) { is_ok = FALSE; + + innobase_format_name( + index_name, sizeof index_name, + prebuilt->index->name, TRUE); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NOT_KEYFILE, "InnoDB: The B-tree of" - " index '%-.200s' is corrupted.", - index->name); + " index %s is corrupted.", + index_name); continue; } @@ -8831,11 +8952,26 @@ ha_innobase::check( prebuilt->trx, prebuilt->index); if (UNIV_UNLIKELY(!prebuilt->index_usable)) { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - HA_ERR_TABLE_DEF_CHANGED, - "InnoDB: Insufficient history for" - " index '%-.200s'", - index->name); + innobase_format_name( + index_name, sizeof index_name, + prebuilt->index->name, TRUE); + + if (dict_index_is_corrupted(prebuilt->index)) { + push_warning_printf( + user_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_INDEX_CORRUPT, + "InnoDB: Index %s is marked as" + " corrupted", + index_name); + is_ok = FALSE; + } else { + push_warning_printf( + thd, MYSQL_ERROR::WARN_LEVEL_WARN, + HA_ERR_TABLE_DEF_CHANGED, + "InnoDB: Insufficient history for" + " index %s", + index_name); + } continue; } @@ -8849,12 +8985,19 @@ ha_innobase::check( prebuilt->select_lock_type = LOCK_NONE; if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) { + innobase_format_name( + index_name, sizeof index_name, + index->name, TRUE); + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NOT_KEYFILE, "InnoDB: The B-tree of" - " index '%-.200s' is corrupted.", - index->name); + " index %s is corrupted.", + index_name); is_ok = FALSE; + row_mysql_lock_data_dictionary(prebuilt->trx); + dict_set_corrupted(index); + row_mysql_unlock_data_dictionary(prebuilt->trx); } if (thd_killed(user_thd)) { @@ -8881,6 +9024,20 @@ ha_innobase::check( } } + if (table_corrupted) { + /* If some previous operation has marked the table as + corrupted in memory, and has not propagated such to + clustered index, we will do so here */ + index = dict_table_get_first_index(prebuilt->table); + + if (!dict_index_is_corrupted(index)) { + mutex_enter(&dict_sys->mutex); + dict_set_corrupted(index); + mutex_exit(&dict_sys->mutex); + } + prebuilt->table->corrupted = TRUE; + } + /* Restore the original isolation level */ prebuilt->trx->isolation_level = old_isolation_level; @@ -10768,6 +10925,10 @@ innobase_xa_prepare( return(0); } + if (trx->fake_changes) { + return(0); + } + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); /* Release a possible FIFO ticket and search latch. Since we will @@ -11586,6 +11747,57 @@ innobase_index_name_is_reserved( return(false); } +/*********************************************************************** +functions for kill session of idle transaction */ +extern "C" +ibool +innobase_thd_is_idle( +/*=================*/ + const void* thd) /*!< in: thread handle (THD*) */ +{ +#ifdef EXTENDED_FOR_KILLIDLE + return(thd_command((const THD*) thd) == COM_SLEEP); +#else + return(FALSE); +#endif +} + +extern "C" +ib_int64_t +innobase_thd_get_start_time( +/*========================*/ + const void* thd) /*!< in: thread handle (THD*) */ +{ +#ifdef EXTENDED_FOR_KILLIDLE + return((ib_int64_t)thd_start_time((const THD*) thd)); +#else + return(0); /*dummy value*/ +#endif +} + +extern "C" +void +innobase_thd_kill( +/*==============*/ + ulong thd_id) +{ +#ifdef EXTENDED_FOR_KILLIDLE + thd_kill(thd_id); +#else + return; +#endif +} + +extern "C" +ulong +innobase_thd_get_thread_id( +/*=======================*/ + const void* thd) +{ + return(thd_get_thread_id((const THD*) thd)); +} + + static SHOW_VAR innodb_status_variables_export[]= { {"Innodb", (char*) &show_innodb_vars, SHOW_FUNC}, {NullS, NullS, SHOW_LONG} @@ -11731,6 +11943,11 @@ static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix, "Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Force InnoDB to load metadata of corrupted table.", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, "Force InnoDB to not use next-key locking, to use only row-level locking.", @@ -11872,6 +12089,15 @@ static MYSQL_SYSVAR_ULONG(concurrency_tickets, srv_n_free_tickets_to_enter, "Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket", NULL, NULL, 500L, 1L, ~0L, 0); +static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction, + PLUGIN_VAR_RQCMDARG, +#ifdef EXTENDED_FOR_KILLIDLE + "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.", +#else + "No effect for this build.", +#endif + NULL, NULL, 0, 0, LONG_MAX, 0); + static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR, "Number of file I/O threads in InnoDB.", @@ -12012,6 +12238,11 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, NULL, NULL, 0, 0, 1, 0); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, + PLUGIN_VAR_NOCMDARG, + "Whether to use read ahead for random access within an extent.", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold, PLUGIN_VAR_RQCMDARG, "Number of pages that must be accessed sequentially for InnoDB to " @@ -12123,6 +12354,13 @@ static MYSQL_SYSVAR_UINT(buffer_pool_restore_at_startup, srv_auto_lru_dump, "0 (the default) disables automatic dumps.", NULL, NULL, 0, 0, UINT_MAX32, 0); +static MYSQL_SYSVAR_BOOL(blocking_buffer_pool_restore, + innobase_blocking_lru_restore, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "Block XtraDB startup process until buffer pool is full restored from a " + "dump file (if present). Disabled by default.", + NULL, NULL, FALSE); + const char *corrupt_table_action_names[]= { "assert", /* 0 */ @@ -12162,6 +12400,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(fast_checksum), MYSQL_SYSVAR(commit_concurrency), MYSQL_SYSVAR(concurrency_tickets), + MYSQL_SYSVAR(kill_idle_transaction), MYSQL_SYSVAR(data_file_path), MYSQL_SYSVAR(doublewrite_file), MYSQL_SYSVAR(data_home_dir), @@ -12180,6 +12419,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(flush_method), MYSQL_SYSVAR(force_recovery), MYSQL_SYSVAR(large_prefix), + MYSQL_SYSVAR(force_load_corrupted), MYSQL_SYSVAR(locks_unsafe_for_binlog), MYSQL_SYSVAR(lock_wait_timeout), #ifdef UNIV_LOG_ARCHIVE @@ -12236,14 +12476,17 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG MYSQL_SYSVAR(change_buffering_debug), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(buffer_pool_restore_at_startup), + MYSQL_SYSVAR(blocking_buffer_pool_restore), MYSQL_SYSVAR(purge_threads), MYSQL_SYSVAR(purge_batch_size), MYSQL_SYSVAR(rollback_segments), MYSQL_SYSVAR(corrupt_table_action), MYSQL_SYSVAR(lazy_drop_table), + MYSQL_SYSVAR(fake_changes), NULL }; @@ -12260,7 +12503,8 @@ mysql_declare_plugin(innobase) INNODB_VERSION_SHORT, innodb_status_variables_export,/* status variables */ innobase_system_variables, /* system variables */ - NULL /* reserved */ + NULL, /* reserved */ + 0, /* flags */ }, i_s_innodb_rseg, i_s_innodb_trx, diff --git a/handler/handler0alter.cc b/handler/handler0alter.cc index 6d5b7b4668f..8c5783fa8b9 100644 --- a/handler/handler0alter.cc +++ b/handler/handler0alter.cc @@ -695,6 +695,10 @@ ha_innobase::add_index( possible adaptive hash latch to avoid deadlocks of threads. */ trx_search_latch_release_if_reserved(prebuilt->trx); + if (prebuilt->trx->fake_changes) { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + /* Check if the index name is reserved. */ if (innobase_index_name_is_reserved(user_thd, key_info, num_of_keys)) { DBUG_RETURN(-1); @@ -732,6 +736,13 @@ ha_innobase::add_index( /* Create a background transaction for the operations on the data dictionary tables. */ trx = innobase_trx_allocate(user_thd); + if (trx->fake_changes) { + mem_heap_free(heap); + trx_general_rollback_for_mysql(trx, NULL); + trx_free_for_mysql(trx); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + trx_start_if_not_started(trx); /* Create table containing all indexes to be built in this @@ -1092,6 +1103,10 @@ ha_innobase::prepare_drop_index( trx_search_latch_release_if_reserved(prebuilt->trx); trx = prebuilt->trx; + if (trx->fake_changes) { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + /* Test and mark all the indexes to be dropped */ row_mysql_lock_data_dictionary(trx); @@ -1296,6 +1311,12 @@ ha_innobase::final_drop_index( /* Create a background transaction for the operations on the data dictionary tables. */ trx = innobase_trx_allocate(user_thd); + if (trx->fake_changes) { + trx_general_rollback_for_mysql(trx, NULL); + trx_free_for_mysql(trx); + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + trx_start_if_not_started(trx); /* Flag this transaction as a dictionary operation, so that diff --git a/handler/i_s.cc b/handler/i_s.cc index 839dce206d3..c0ad731e336 100644 --- a/handler/i_s.cc +++ b/handler/i_s.cc @@ -645,7 +645,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */ @@ -911,7 +915,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */ @@ -1094,7 +1102,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; /*******************************************************************//** @@ -1427,7 +1439,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset = @@ -1477,7 +1493,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; /* Fields of the dynamic table information_schema.innodb_cmpmem. */ @@ -1720,7 +1740,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = @@ -1770,7 +1794,11 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = /* reserved for dependency checking */ /* void* */ - STRUCT_FLD(__reserved1, NULL) + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), }; /*******************************************************************//** diff --git a/ibuf/ibuf0ibuf.c b/ibuf/ibuf0ibuf.c index f5ed301dcf1..7def360867d 100644 --- a/ibuf/ibuf0ibuf.c +++ b/ibuf/ibuf0ibuf.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -402,7 +402,7 @@ ibuf_tree_root_get( block = buf_page_get( IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); root = buf_block_get_frame(block); @@ -590,7 +590,7 @@ ibuf_init_at_db_start(void) block = buf_page_get( IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, &mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); root = buf_block_get_frame(block); } @@ -2251,16 +2251,17 @@ ibuf_add_free_page(void) } else { buf_block_t* block = buf_page_get( IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW); - page = buf_block_get_frame(block); - } + ibuf_enter(&mtr); - ibuf_enter(&mtr); + mutex_enter(&ibuf_mutex); - mutex_enter(&ibuf_mutex); + root = ibuf_tree_root_get(&mtr); - root = ibuf_tree_root_get(&mtr); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); + + page = buf_block_get_frame(block); + } /* Add the page to the free list and update the ibuf size data */ @@ -2374,8 +2375,7 @@ ibuf_remove_free_page(void) block = buf_page_get( IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); - + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); page = buf_block_get_frame(block); } @@ -3066,7 +3066,7 @@ ibuf_get_volume_buffered( IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); prev_page = buf_block_get_frame(block); @@ -3139,7 +3139,7 @@ count_later: IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); next_page = buf_block_get_frame(block); @@ -3377,7 +3377,7 @@ ibuf_set_entry_counter( IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); prev_page = buf_block_get_frame(block); @@ -3496,6 +3496,8 @@ ibuf_insert_low( ut_a(trx_sys_multiple_tablespace_format); + ut_ad(!(thr_get_trx(thr)->fake_changes)); + do_merge = FALSE; /* Perform dirty reads of ibuf->size and ibuf->max_size, to @@ -4465,6 +4467,7 @@ ibuf_merge_or_delete_for_page( ut_ad(!block || buf_block_get_space(block) == space); ut_ad(!block || buf_block_get_page_no(block) == page_no); ut_ad(!block || buf_block_get_zip_size(block) == zip_size); + ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ); if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE || trx_sys_hdr_page(space, page_no)) { @@ -4617,7 +4620,13 @@ loop: ut_a(success); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + /* This is a user page (secondary index leaf page), + but we pretend that it is a change buffer page in + order to obey the latching order. This should be OK, + because buffered changes are applied immediately while + the block is io-fixed. Other threads must not try to + latch an io-fixed block. */ + buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); } /* Position pcur in the insert buffer at the first entry for this @@ -4721,7 +4730,12 @@ loop: __FILE__, __LINE__, &mtr); ut_a(success); - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + /* This is a user page (secondary + index leaf page), but it should be OK + to use too low latching order for it, + as the block is io-fixed. */ + buf_block_dbg_add_level( + block, SYNC_IBUF_TREE_NODE); if (!ibuf_restore_pos(space, page_no, search_tuple, diff --git a/include/btr0btr.h b/include/btr0btr.h index c632e034581..058fcfb64de 100644 --- a/include/btr0btr.h +++ b/include/btr0btr.h @@ -199,26 +199,45 @@ btr_block_get_func( ulint mode, /*!< in: latch mode */ const char* file, /*!< in: file name */ ulint line, /*!< in: line where called */ - mtr_t* mtr) /*!< in/out: mtr */ - __attribute__((nonnull)); +# ifdef UNIV_SYNC_DEBUG + const dict_index_t* index, /*!< in: index tree, may be NULL + if it is not an insert buffer tree */ +# endif /* UNIV_SYNC_DEBUG */ + mtr_t* mtr); /*!< in/out: mini-transaction */ +# ifdef UNIV_SYNC_DEBUG +/** Gets a buffer page and declares its latching order level. +@param space tablespace identifier +@param zip_size compressed page size in bytes or 0 for uncompressed pages +@param page_no page number +@param mode latch mode +@param index index tree, may be NULL if not the insert buffer tree +@param mtr mini-transaction handle +@return the block descriptor */ +# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \ + btr_block_get_func(space,zip_size,page_no,mode, \ + __FILE__,__LINE__,index,mtr) +# else /* UNIV_SYNC_DEBUG */ /** Gets a buffer page and declares its latching order level. @param space tablespace identifier @param zip_size compressed page size in bytes or 0 for uncompressed pages @param page_no page number @param mode latch mode +@param idx index tree, may be NULL if not the insert buffer tree @param mtr mini-transaction handle @return the block descriptor */ -# define btr_block_get(space,zip_size,page_no,mode,mtr) \ +# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \ btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr) +# endif /* UNIV_SYNC_DEBUG */ /** Gets a buffer page and declares its latching order level. @param space tablespace identifier @param zip_size compressed page size in bytes or 0 for uncompressed pages @param page_no page number @param mode latch mode +@param idx index tree, may be NULL if not the insert buffer tree @param mtr mini-transaction handle @return the uncompressed page frame */ -# define btr_page_get(space,zip_size,page_no,mode,mtr) \ - buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr)) +# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \ + buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr)) /**************************************************************//** Sets the index id field of a page. */ UNIV_INLINE @@ -389,8 +408,7 @@ btr_free_root( ulint zip_size, /*!< in: compressed page size in bytes or 0 for uncompressed pages */ ulint root_page_no, /*!< in: root page number */ - mtr_t* mtr); /*!< in: a mini-transaction which has already - been started */ + mtr_t* mtr); /*!< in/out: mini-transaction */ /*************************************************************//** Makes tree one level higher by splitting the root, and inserts the tuple. It is assumed that mtr contains an x-latch on the tree. diff --git a/include/btr0btr.ic b/include/btr0btr.ic index 99c02ab30dc..f446ecb69d3 100644 --- a/include/btr0btr.ic +++ b/include/btr0btr.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -48,6 +48,10 @@ btr_block_get_func( ulint mode, /*!< in: latch mode */ const char* file, /*!< in: file name */ ulint line, /*!< in: line where called */ +#ifdef UNIV_SYNC_DEBUG + const dict_index_t* index, /*!< in: index tree, may be NULL + if it is not an insert buffer tree */ +#endif /* UNIV_SYNC_DEBUG */ mtr_t* mtr) /*!< in/out: mtr */ { buf_block_t* block; @@ -59,7 +63,9 @@ btr_block_get_func( if (block && mode != RW_NO_LATCH) { - buf_block_dbg_add_level(block, SYNC_TREE_NODE); + buf_block_dbg_add_level( + block, index != NULL && dict_index_is_ibuf(index) + ? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE); } return(block); diff --git a/include/btr0pcur.h b/include/btr0pcur.h index 6c11c973fc9..f605c476844 100644 --- a/include/btr0pcur.h +++ b/include/btr0pcur.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -244,18 +244,6 @@ btr_pcur_restore_position_func( mtr_t* mtr); /*!< in: mtr */ #define btr_pcur_restore_position(l,cur,mtr) \ btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr) -/**************************************************************//** -If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY, -releases the page latch and bufferfix reserved by the cursor. -NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes -made by the current mini-transaction to the data protected by the -cursor latch, as then the latch must not be released until mtr_commit. */ -UNIV_INTERN -void -btr_pcur_release_leaf( -/*==================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr); /*!< in: mtr */ /*********************************************************//** Gets the rel_pos field for a cursor whose position has been stored. @return BTR_PCUR_ON, ... */ @@ -266,10 +254,9 @@ btr_pcur_get_rel_pos( const btr_pcur_t* cursor);/*!< in: persistent cursor */ /**************************************************************//** Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES, -that is, the cursor becomes detached. If there have been modifications -to the page where pcur is positioned, this can be used instead of -btr_pcur_release_leaf. Function btr_pcur_store_position should be used -before calling this, if restoration of cursor is wanted later. */ +that is, the cursor becomes detached. +Function btr_pcur_store_position should be used before calling this, +if restoration of cursor is wanted later. */ UNIV_INLINE void btr_pcur_commit_specify_mtr( diff --git a/include/btr0pcur.ic b/include/btr0pcur.ic index 59fdb21824b..d86601e5a32 100644 --- a/include/btr0pcur.ic +++ b/include/btr0pcur.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -369,10 +369,9 @@ btr_pcur_move_to_next( /**************************************************************//** Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES, -that is, the cursor becomes detached. If there have been modifications -to the page where pcur is positioned, this can be used instead of -btr_pcur_release_leaf. Function btr_pcur_store_position should be used -before calling this, if restoration of cursor is wanted later. */ +that is, the cursor becomes detached. +Function btr_pcur_store_position should be used before calling this, +if restoration of cursor is wanted later. */ UNIV_INLINE void btr_pcur_commit_specify_mtr( diff --git a/include/buf0buddy.h b/include/buf0buddy.h index f51b8020918..eeea8f76351 100644 --- a/include/buf0buddy.h +++ b/include/buf0buddy.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -37,39 +37,39 @@ Created December 2006 by Marko Makela /**********************************************************************//** Allocate a block. The thread calling this function must hold buf_pool->mutex and must not hold buf_pool->zip_mutex or any -block->mutex. The buf_pool->mutex may only be released and reacquired -if lru != NULL. This function should only be used for allocating -compressed page frames or control blocks (buf_page_t). Allocated -control blocks must be properly initialized immediately after -buf_buddy_alloc() has returned the memory, before releasing -buf_pool->mutex. -@return allocated block, possibly NULL if lru == NULL */ +block->mutex. The buf_pool->mutex may be released and reacquired. +This function should only be used for allocating compressed page frames. +@return allocated block, never NULL */ UNIV_INLINE -void* +byte* buf_buddy_alloc( /*============*/ - buf_pool_t* buf_pool, - /*!< buffer pool in which the block resides */ - ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */ - ibool* lru, /*!< in: pointer to a variable that will be assigned - TRUE if storage was allocated from the LRU list - and buf_pool->mutex was temporarily released, - or NULL if the LRU list should not be used */ - ibool have_page_hash_mutex) - __attribute__((malloc)); + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which + the page resides */ + ulint size, /*!< in: compressed page size + (between PAGE_ZIP_MIN_SIZE and + UNIV_PAGE_SIZE) */ + ibool* lru, /*!< in: pointer to a variable + that will be assigned TRUE if + storage was allocated from the + LRU list and buf_pool->mutex was + temporarily released */ + ibool have_page_hash_mutex) + __attribute__((malloc, nonnull)); /**********************************************************************//** -Release a block. */ +Deallocate a block. */ UNIV_INLINE void buf_buddy_free( /*===========*/ - buf_pool_t* buf_pool, - /*!< buffer pool in which the block resides */ - void* buf, /*!< in: block to be freed, must not be - pointed to by the buffer pool */ - ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */ - ibool have_page_hash_mutex) + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which + the block resides */ + void* buf, /*!< in: block to be freed, must not + be pointed to by the buffer pool */ + ulint size, /*!< in: block size, + up to UNIV_PAGE_SIZE */ + ibool have_page_hash_mutex) __attribute__((nonnull)); #ifndef UNIV_NONINL diff --git a/include/buf0buddy.ic b/include/buf0buddy.ic index 4dbfed52abe..3dd75276656 100644 --- a/include/buf0buddy.ic +++ b/include/buf0buddy.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2006, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -36,22 +36,22 @@ Created December 2006 by Marko Makela /**********************************************************************//** Allocate a block. The thread calling this function must hold buf_pool->mutex and must not hold buf_pool->zip_mutex or any block->mutex. -The buf_pool->mutex may only be released and reacquired if lru != NULL. -@return allocated block, possibly NULL if lru==NULL */ +The buf_pool_mutex may be released and reacquired. +@return allocated block, never NULL */ UNIV_INTERN void* buf_buddy_alloc_low( /*================*/ - buf_pool_t* buf_pool, - /*!< in: buffer pool in which the page resides */ - ulint i, /*!< in: index of buf_pool->zip_free[], - or BUF_BUDDY_SIZES */ - ibool* lru, /*!< in: pointer to a variable that will be assigned - TRUE if storage was allocated from the LRU list - and buf_pool->mutex was temporarily released, - or NULL if the LRU list should not be used */ - ibool have_page_hash_mutex) - __attribute__((malloc)); + buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */ + ulint i, /*!< in: index of buf_pool->zip_free[], + or BUF_BUDDY_SIZES */ + ibool* lru, /*!< in: pointer to a variable that + will be assigned TRUE if storage was + allocated from the LRU list and + buf_pool->mutex was temporarily + released */ + ibool have_page_hash_mutex) + __attribute__((malloc, nonnull)); /**********************************************************************//** Deallocate a block. */ @@ -79,6 +79,8 @@ buf_buddy_get_slot( ulint i; ulint s; + ut_ad(size >= PAGE_ZIP_MIN_SIZE); + for (i = 0, s = BUF_BUDDY_LOW; s < size; i++, s <<= 1) { } @@ -89,32 +91,32 @@ buf_buddy_get_slot( /**********************************************************************//** Allocate a block. The thread calling this function must hold buf_pool->mutex and must not hold buf_pool->zip_mutex or any -block->mutex. The buf_pool->mutex may only be released and reacquired -if lru != NULL. This function should only be used for allocating -compressed page frames or control blocks (buf_page_t). Allocated -control blocks must be properly initialized immediately after -buf_buddy_alloc() has returned the memory, before releasing -buf_pool->mutex. -@return allocated block, possibly NULL if lru == NULL */ +block->mutex. The buf_pool->mutex may be released and reacquired. +This function should only be used for allocating compressed page frames. +@return allocated block, never NULL */ UNIV_INLINE -void* +byte* buf_buddy_alloc( /*============*/ - buf_pool_t* buf_pool, /*!< in: buffer pool in which + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which the page resides */ - ulint size, /*!< in: block size, up to - UNIV_PAGE_SIZE */ + ulint size, /*!< in: compressed page size + (between PAGE_ZIP_MIN_SIZE and + UNIV_PAGE_SIZE) */ ibool* lru, /*!< in: pointer to a variable that will be assigned TRUE if storage was allocated from the LRU list and buf_pool->mutex was - temporarily released, or NULL if - the LRU list should not be used */ + temporarily released */ ibool have_page_hash_mutex) { //ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(ut_is_2pow(size)); + ut_ad(size >= PAGE_ZIP_MIN_SIZE); + ut_ad(size <= UNIV_PAGE_SIZE); - return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru, have_page_hash_mutex)); + return((byte*) buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), + lru, have_page_hash_mutex)); } /**********************************************************************//** @@ -123,14 +125,18 @@ UNIV_INLINE void buf_buddy_free( /*===========*/ - buf_pool_t* buf_pool, /*!< in: buffer pool instance */ - void* buf, /*!< in: block to be freed, must not be - pointed to by the buffer pool */ - ulint size, /*!< in: block size, up to - UNIV_PAGE_SIZE */ + buf_pool_t* buf_pool, /*!< in/out: buffer pool in which + the block resides */ + void* buf, /*!< in: block to be freed, must not + be pointed to by the buffer pool */ + ulint size, /*!< in: block size, + up to UNIV_PAGE_SIZE */ ibool have_page_hash_mutex) { //ut_ad(buf_pool_mutex_own(buf_pool)); + ut_ad(ut_is_2pow(size)); + ut_ad(size >= PAGE_ZIP_MIN_SIZE); + ut_ad(size <= UNIV_PAGE_SIZE); if (!have_page_hash_mutex) { mutex_enter(&buf_pool->LRU_list_mutex); diff --git a/include/buf0buf.h b/include/buf0buf.h index ef6a26f9459..d85dac5cc91 100644 --- a/include/buf0buf.h +++ b/include/buf0buf.h @@ -148,6 +148,8 @@ struct buf_pool_info_struct{ ulint n_pages_created; /*!< buf_pool->n_pages_created */ ulint n_pages_written; /*!< buf_pool->n_pages_written */ ulint n_page_gets; /*!< buf_pool->n_page_gets */ + ulint n_ra_pages_read_rnd; /*!< buf_pool->n_ra_pages_read_rnd, + number of pages readahead */ ulint n_ra_pages_read; /*!< buf_pool->n_ra_pages_read, number of pages readahead */ ulint n_ra_pages_evicted; /*!< buf_pool->n_ra_pages_evicted, @@ -172,6 +174,8 @@ struct buf_pool_info_struct{ last printout */ /* Statistics about read ahead algorithm. */ + double pages_readahead_rnd_rate;/*!< random readahead rate in pages per + second */ double pages_readahead_rate; /*!< readahead rate in pages per second */ double pages_evicted_rate; /*!< rate of readahead page evicted @@ -261,12 +265,6 @@ buf_relocate( BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */ buf_page_t* dpage) /*!< in/out: destination control block */ __attribute__((nonnull)); -/********************************************************************//** -Resizes the buffer pool. */ -UNIV_INTERN -void -buf_pool_resize(void); -/*=================*/ /*********************************************************************//** Gets the current size of buffer buf_pool in bytes. @return size in bytes */ @@ -290,6 +288,23 @@ ib_uint64_t buf_pool_get_oldest_modification(void); /*==================================*/ /********************************************************************//** +Allocates a buf_page_t descriptor. This function must succeed. In case +of failure we assert in this function. */ +UNIV_INLINE +buf_page_t* +buf_page_alloc_descriptor(void) +/*===========================*/ + __attribute__((malloc)); +/********************************************************************//** +Free a buf_page_t descriptor. */ +UNIV_INLINE +void +buf_page_free_descriptor( +/*=====================*/ + buf_page_t* bpage) /*!< in: bpage descriptor to free. */ + __attribute__((nonnull)); + +/********************************************************************//** Allocates a buffer block. @return own: the allocated block, in state BUF_BLOCK_MEMORY */ UNIV_INTERN @@ -546,6 +561,18 @@ buf_block_get_freed_page_clock( __attribute__((pure)); /********************************************************************//** +Tells if a block is still close enough to the MRU end of the LRU list +meaning that it is not in danger of getting evicted and also implying +that it has been accessed recently. +Note that this is for heuristics only and does not reserve buffer pool +mutex. +@return TRUE if block is close to MRU end of LRU */ +UNIV_INLINE +ibool +buf_page_peek_if_young( +/*===================*/ + const buf_page_t* bpage); /*!< in: block */ +/********************************************************************//** Recommends a move of a block to the start of the LRU list if there is danger of dropping from the buffer pool. NOTE: does not reserve the buffer pool mutex. @@ -1233,7 +1260,7 @@ ulint buf_get_free_list_len(void); /*=======================*/ -/******************************************************************** +/********************************************************************//** Determine if a block is a sentinel for a buffer pool watch. @return TRUE if a sentinel for a buffer pool watch, FALSE if not */ UNIV_INTERN @@ -1622,6 +1649,8 @@ struct buf_pool_stat_struct{ ulint n_pages_written;/*!< number write operations */ ulint n_pages_created;/*!< number of pages created in the pool with no read */ + ulint n_ra_pages_read_rnd;/*!< number of pages read in + as part of random read ahead */ ulint n_ra_pages_read;/*!< number of pages read in as part of read ahead */ ulint n_ra_pages_evicted;/*!< number of read ahead @@ -1766,7 +1795,7 @@ struct buf_pool_struct{ UT_LIST_BASE_NODE_T(buf_page_t) LRU; /*!< base node of the LRU list */ buf_page_t* LRU_old; /*!< pointer to the about - buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV + LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV oldest blocks in the LRU list; NULL if LRU length less than BUF_LRU_OLD_MIN_LEN; @@ -1790,8 +1819,10 @@ struct buf_pool_struct{ frames and buf_page_t descriptors of blocks that exist in the buffer pool only in compressed form. */ /* @{ */ +#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_BASE_NODE_T(buf_page_t) zip_clean; /*!< unmodified compressed pages */ +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX]; /*!< buddy free lists */ diff --git a/include/buf0buf.ic b/include/buf0buf.ic index 1a96b575d9b..98d575075ba 100644 --- a/include/buf0buf.ic +++ b/include/buf0buf.ic @@ -125,6 +125,29 @@ buf_block_get_freed_page_clock( } /********************************************************************//** +Tells if a block is still close enough to the MRU end of the LRU list +meaning that it is not in danger of getting evicted and also implying +that it has been accessed recently. +Note that this is for heuristics only and does not reserve buffer pool +mutex. +@return TRUE if block is close to MRU end of LRU */ +UNIV_INLINE +ibool +buf_page_peek_if_young( +/*===================*/ + const buf_page_t* bpage) /*!< in: block */ +{ + buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); + + /* FIXME: bpage->freed_page_clock is 31 bits */ + return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) + < ((ulint) bpage->freed_page_clock + + (buf_pool->curr_size + * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio) + / (BUF_LRU_OLD_RATIO_DIV * 4)))); +} + +/********************************************************************//** Recommends a move of a block to the start of the LRU list if there is danger of dropping from the buffer pool. NOTE: does not reserve the buffer pool mutex. @@ -154,12 +177,7 @@ buf_page_peek_if_too_old( buf_pool->stat.n_pages_not_made_young++; return(FALSE); } else { - /* FIXME: bpage->freed_page_clock is 31 bits */ - return((buf_pool->freed_page_clock & ((1UL << 31) - 1)) - > ((ulint) bpage->freed_page_clock - + (buf_pool->curr_size - * (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio) - / (BUF_LRU_OLD_RATIO_DIV * 4)))); + return(!buf_page_peek_if_young(bpage)); } } @@ -792,6 +810,35 @@ buf_block_get_lock_hash_val( } /********************************************************************//** +Allocates a buf_page_t descriptor. This function must succeed. In case +of failure we assert in this function. +@return: the allocated descriptor. */ +UNIV_INLINE +buf_page_t* +buf_page_alloc_descriptor(void) +/*===========================*/ +{ + buf_page_t* bpage; + + bpage = (buf_page_t*) ut_malloc(sizeof *bpage); + ut_d(memset(bpage, 0, sizeof *bpage)); + UNIV_MEM_ALLOC(bpage, sizeof *bpage); + + return(bpage); +} + +/********************************************************************//** +Free a buf_page_t descriptor. */ +UNIV_INLINE +void +buf_page_free_descriptor( +/*=====================*/ + buf_page_t* bpage) /*!< in: bpage descriptor to free. */ +{ + ut_free(bpage); +} + +/********************************************************************//** Frees a buffer block which does not contain a file page. */ UNIV_INLINE void diff --git a/include/buf0lru.h b/include/buf0lru.h index 5d004ec4bb7..700136ec488 100644 --- a/include/buf0lru.h +++ b/include/buf0lru.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,18 +30,6 @@ Created 11/5/1995 Heikki Tuuri #include "ut0byte.h" #include "buf0types.h" -/** The return type of buf_LRU_free_block() */ -enum buf_lru_free_block_status { - /** freed */ - BUF_LRU_FREED = 0, - /** not freed because the caller asked to remove the - uncompressed frame but the control block cannot be - relocated */ - BUF_LRU_CANNOT_RELOCATE, - /** not freed because of some other reason */ - BUF_LRU_NOT_FREED -}; - /******************************************************************//** Tries to remove LRU flushed blocks from the end of the LRU list and put them to the free list. This is beneficial for the efficiency of the insert buffer @@ -85,6 +73,7 @@ void buf_LRU_invalidate_tablespace( /*==========================*/ ulint id); /*!< in: space id */ + /******************************************************************//** */ UNIV_INTERN @@ -92,6 +81,7 @@ 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. */ UNIV_INTERN @@ -99,22 +89,22 @@ void buf_LRU_insert_zip_clean( /*=====================*/ buf_page_t* bpage); /*!< in: pointer to the block in question */ +#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ /******************************************************************//** Try to free a block. If bpage is a descriptor of a compressed-only page, the descriptor object will be freed as well. -NOTE: If this function returns BUF_LRU_FREED, it will temporarily +NOTE: If this function returns TRUE, it will temporarily release buf_pool->mutex. Furthermore, the page frame will no longer be accessible via bpage. The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and release these two mutexes after the call. No other buf_page_get_mutex() may be held when calling this function. -@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or -BUF_LRU_NOT_FREED otherwise. */ +@return TRUE if freed, FALSE otherwise. */ UNIV_INTERN -enum buf_lru_free_block_status +ibool buf_LRU_free_block( /*===============*/ buf_page_t* bpage, /*!< in: block to be freed */ @@ -204,7 +194,7 @@ buf_LRU_make_block_old( /*===================*/ buf_page_t* bpage); /*!< in: control block */ /**********************************************************************//** -Updates buf_LRU_old_ratio. +Updates buf_pool->LRU_old_ratio. @return updated old_pct */ UNIV_INTERN ulint @@ -213,7 +203,7 @@ buf_LRU_old_ratio_update( uint old_pct,/*!< in: Reserve this percentage of the buffer pool for "old" blocks. */ ibool adjust);/*!< in: TRUE=adjust the LRU list; - FALSE=just assign buf_LRU_old_ratio + FALSE=just assign buf_pool->LRU_old_ratio during the initialization of InnoDB */ /********************************************************************//** Update the historical stats that we are collecting for LRU eviction @@ -235,6 +225,17 @@ ibool buf_LRU_file_restore(void); /*======================*/ +/******************************************************************//** +Remove one page from LRU list and put it to free list */ +UNIV_INTERN +void +buf_LRU_free_one_page( +/*==================*/ + buf_page_t* bpage) /*!< in/out: block, must contain a file page and + be in a state where it can be freed; there + may or may not be a hash index to the page */ + __attribute__((nonnull)); + #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /**********************************************************************//** Validates the LRU list. @@ -254,18 +255,15 @@ buf_LRU_print(void); #endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ /** @name Heuristics for detecting index scan @{ */ -/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for -"old" blocks. Protected by buf_pool->mutex. */ -extern uint buf_LRU_old_ratio; -/** The denominator of buf_LRU_old_ratio. */ +/** The denominator of buf_pool->LRU_old_ratio. */ #define BUF_LRU_OLD_RATIO_DIV 1024 -/** Maximum value of buf_LRU_old_ratio. +/** Maximum value of buf_pool->LRU_old_ratio. @see buf_LRU_old_adjust_len -@see buf_LRU_old_ratio_update */ +@see buf_pool->LRU_old_ratio_update */ #define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV -/** Minimum value of buf_LRU_old_ratio. +/** Minimum value of buf_pool->LRU_old_ratio. @see buf_LRU_old_adjust_len -@see buf_LRU_old_ratio_update +@see buf_pool->LRU_old_ratio_update The minimum must exceed (BUF_LRU_OLD_TOLERANCE + 5) * BUF_LRU_OLD_RATIO_DIV / BUF_LRU_OLD_MIN_LEN. */ #define BUF_LRU_OLD_RATIO_MIN 51 diff --git a/include/buf0rea.h b/include/buf0rea.h index 4910c1e2aca..dedd1904d31 100644 --- a/include/buf0rea.h +++ b/include/buf0rea.h @@ -76,6 +76,32 @@ buf_read_page( ulint offset, /*!< in: page number */ trx_t* trx); /********************************************************************//** +Applies a random read-ahead in buf_pool if there are at least a threshold +value of accessed pages from the random read-ahead area. Does not read any +page, not even the one at the position (space, offset), if the read-ahead +mechanism is not activated. NOTE 1: the calling thread may own latches on +pages: to avoid deadlocks this function must be written such that it cannot +end up waiting for these latches! NOTE 2: the calling thread must want +access to the page given: this rule is set to prevent unintended read-aheads +performed by ibuf routines, a situation which could result in a deadlock if +the OS does not support asynchronous i/o. +@return number of page read requests issued; NOTE that if we read ibuf +pages, it may happen that the page at the given page number does not +get read even if we return a positive value! +@return number of page read requests issued */ +UNIV_INTERN +ulint +buf_read_ahead_random( +/*==================*/ + ulint space, /*!< in: space id */ + ulint zip_size, /*!< in: compressed page size in bytes, + or 0 */ + ulint offset, /*!< in: page number of a page which + the current thread wants to access */ + ibool inside_ibuf, /*!< in: TRUE if we are inside ibuf + routine */ + trx_t* trx); +/********************************************************************//** Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. Does not read any page if the read-ahead mechanism is not activated. Note diff --git a/include/buf0types.h b/include/buf0types.h index 888be86e332..156093aad01 100644 --- a/include/buf0types.h +++ b/include/buf0types.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -26,6 +26,8 @@ Created 11/17/1995 Heikki Tuuri #ifndef buf0types_h #define buf0types_h +#include "page0types.h" + /** Buffer page (uncompressed or compressed) */ typedef struct buf_page_struct buf_page_t; /** Buffer block for which an uncompressed page exists */ @@ -60,17 +62,10 @@ enum buf_io_fix { /** Parameters of binary buddy system for compressed pages (buf0buddy.h) */ /* @{ */ -#if UNIV_WORD_SIZE <= 4 /* 32-bit system */ -/** Base-2 logarithm of the smallest buddy block size */ -# define BUF_BUDDY_LOW_SHIFT 6 -#else /* 64-bit system */ -/** Base-2 logarithm of the smallest buddy block size */ -# define BUF_BUDDY_LOW_SHIFT 7 -#endif +#define BUF_BUDDY_LOW_SHIFT PAGE_ZIP_MIN_SIZE_SHIFT + #define BUF_BUDDY_LOW (1 << BUF_BUDDY_LOW_SHIFT) - /*!< minimum block size in the binary - buddy system; must be at least - sizeof(buf_page_t) */ + #define BUF_BUDDY_SIZES (UNIV_PAGE_SIZE_SHIFT - BUF_BUDDY_LOW_SHIFT) #define BUF_BUDDY_SIZES_MAX (UNIV_PAGE_SIZE_SHIFT_MAX - BUF_BUDDY_LOW_SHIFT) /*!< number of buddy sizes */ diff --git a/include/db0err.h b/include/db0err.h index 74a2354bce3..e0952f0709d 100644 --- a/include/db0err.h +++ b/include/db0err.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -64,8 +64,6 @@ enum db_err { DB_CANNOT_ADD_CONSTRAINT, /* adding a foreign key constraint to a table failed */ DB_CORRUPTION, /* data structure corruption noticed */ - DB_COL_APPEARS_TWICE_IN_INDEX, /* InnoDB cannot handle an index - where same column appears twice */ DB_CANNOT_DROP_CONSTRAINT, /* dropping a foreign key constraint from a table failed */ DB_NO_SAVEPOINT, /* no savepoint exists with the given @@ -112,6 +110,8 @@ enum db_err { foreign keys as its prefix columns */ DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum limit */ + DB_INDEX_CORRUPT, /* we have corrupted index */ + DB_UNDO_RECORD_TOO_BIG, /* the undo log record is too big */ /* The following are partial failure codes */ DB_FAIL = 1000, diff --git a/include/dict0boot.h b/include/dict0boot.h index c8a09ca7de4..a817775c93c 100644 --- a/include/dict0boot.h +++ b/include/dict0boot.h @@ -141,8 +141,10 @@ dict_create(void); #define DICT_HDR_XTRADB_MARK 256 /* Flag to distinguish expansion of XtraDB */ /*-------------------------------------------------------------*/ -/* The field number of the page number field in the sys_indexes table -clustered index */ +/* The field numbers in the SYS_TABLES clustered index */ +#define DICT_SYS_TABLES_TYPE_FIELD 5 + +/* The field numbers in the SYS_INDEXES clustered index */ #define DICT_SYS_INDEXES_PAGE_NO_FIELD 8 #define DICT_SYS_INDEXES_SPACE_NO_FIELD 7 #define DICT_SYS_INDEXES_TYPE_FIELD 6 diff --git a/include/dict0dict.h b/include/dict0dict.h index d99177e0330..fb5285fae0b 100644 --- a/include/dict0dict.h +++ b/include/dict0dict.h @@ -585,6 +585,20 @@ dict_table_get_next_index( # define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index) #endif /* UNIV_DEBUG */ #endif /* !UNIV_HOTBACKUP */ + +/* Skip corrupted index */ +#define dict_table_skip_corrupt_index(index) \ + while (index && dict_index_is_corrupted(index)) { \ + index = dict_table_get_next_index(index); \ + } + +/* Get the next non-corrupt index */ +#define dict_table_next_uncorrupted_index(index) \ +do { \ + index = dict_table_get_next_index(index); \ + dict_table_skip_corrupt_index(index); \ +} while (0) + /********************************************************************//** Check whether the index is the clustered index. @return nonzero for clustered index, zero for other indexes */ @@ -593,7 +607,7 @@ ulint dict_index_is_clust( /*================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is unique. @return nonzero for unique index, zero for other indexes */ @@ -602,7 +616,7 @@ ulint dict_index_is_unique( /*=================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is the insert buffer tree. @return nonzero for insert buffer, zero for other indexes */ @@ -611,7 +625,7 @@ ulint dict_index_is_ibuf( /*===============*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Check whether the index is a secondary index or the insert buffer tree. @return nonzero for insert buffer, zero for other indexes */ @@ -620,7 +634,7 @@ ulint dict_index_is_sec_or_ibuf( /*======================*/ const dict_index_t* index) /*!< in: index */ - __attribute__((pure)); + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of user-defined columns in a table in the dictionary @@ -630,7 +644,8 @@ UNIV_INLINE ulint dict_table_get_n_user_cols( /*=======================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of system columns in a table in the dictionary cache. @return number of system (e.g., ROW_ID) columns of a table */ @@ -638,7 +653,8 @@ UNIV_INLINE ulint dict_table_get_n_sys_cols( /*======================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); /********************************************************************//** Gets the number of all columns (also system) in a table in the dictionary cache. @@ -647,7 +663,8 @@ UNIV_INLINE ulint dict_table_get_n_cols( /*==================*/ - const dict_table_t* table); /*!< in: table */ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); #ifdef UNIV_DEBUG /********************************************************************//** Gets the nth column of a table. @@ -1258,6 +1275,57 @@ void dict_close(void); /*============*/ +/**********************************************************************//** +Check whether the table is corrupted. +@return nonzero for corrupted table, zero for valid tables */ +UNIV_INLINE +ulint +dict_table_is_corrupted( +/*====================*/ + const dict_table_t* table) /*!< in: table */ + __attribute__((nonnull, pure, warn_unused_result)); + +/**********************************************************************//** +Check whether the index is corrupted. +@return nonzero for corrupted index, zero for valid indexes */ +UNIV_INLINE +ulint +dict_index_is_corrupted( +/*====================*/ + const dict_index_t* index) /*!< in: index */ + __attribute__((nonnull, pure, warn_unused_result)); + +/**********************************************************************//** +Flags an index and table corrupted both in the data dictionary cache +and in the system table SYS_INDEXES. */ +UNIV_INTERN +void +dict_set_corrupted( +/*===============*/ + dict_index_t* index) /*!< in/out: index */ + UNIV_COLD __attribute__((nonnull)); + +/**********************************************************************//** +Flags an index corrupted in the data dictionary cache only. This +is used mostly to mark a corrupted index when index's own dictionary +is corrupted, and we force to load such index for repair purpose */ +UNIV_INTERN +void +dict_set_corrupted_index_cache_only( +/*================================*/ + dict_index_t* index, /*!< in/out: index */ + dict_table_t* table); /*!< in/out: table */ + +/**********************************************************************//** +Flags a table with specified space_id corrupted in the table dictionary +cache. +@return TRUE if successful */ +UNIV_INTERN +ibool +dict_set_corrupted_by_space( +/*========================*/ + ulint space_id); /*!< in: space ID */ + /************************************************************************* set is_corrupt flag by space_id*/ diff --git a/include/dict0dict.ic b/include/dict0dict.ic index b03f5117295..ecb5ec0a408 100644 --- a/include/dict0dict.ic +++ b/include/dict0dict.ic @@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri #ifndef UNIV_HOTBACKUP #include "dict0load.h" #include "rem0types.h" +#include "srv0srv.h" /*********************************************************************//** Gets the minimum number of bytes per character. @@ -835,7 +836,7 @@ dict_table_check_if_in_cache_low( } /**********************************************************************//** -load a table into dictionary cache, ignore any error specified during load; +load a table into dictionary cache, ignore any error specified during load; @return table, NULL if not found */ UNIV_INLINE dict_table_t* @@ -879,6 +880,18 @@ dict_table_get_low( table = dict_table_check_if_in_cache_low(table_name); + if (table && table->corrupted) { + fprintf(stderr, "InnoDB: table"); + ut_print_name(stderr, NULL, TRUE, table->name); + if (srv_load_corrupted) { + fputs(" is corrupted, but" + " innodb_force_load_corrupted is set\n", stderr); + } else { + fputs(" is corrupted\n", stderr); + return(NULL); + } + } + if (table == NULL) { table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE); } @@ -950,4 +963,35 @@ dict_max_field_len_store_undo( return(prefix_len); } +/********************************************************************//** +Check whether the table is corrupted. +@return nonzero for corrupted table, zero for valid tables */ +UNIV_INLINE +ulint +dict_table_is_corrupted( +/*====================*/ + const dict_table_t* table) /*!< in: table */ +{ + ut_ad(table); + ut_ad(table->magic_n == DICT_TABLE_MAGIC_N); + + return(UNIV_UNLIKELY(table->corrupted)); +} + +/********************************************************************//** +Check whether the index is corrupted. +@return nonzero for corrupted index, zero for valid indexes */ +UNIV_INLINE +ulint +dict_index_is_corrupted( +/*====================*/ + const dict_index_t* index) /*!< in: index */ +{ + ut_ad(index); + ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); + + return(UNIV_UNLIKELY((index->type & DICT_CORRUPT) + || (index->table && index->table->corrupted))); +} + #endif /* !UNIV_HOTBACKUP */ diff --git a/include/dict0mem.h b/include/dict0mem.h index 71af9ce2f0c..4701fcd87f9 100644 --- a/include/dict0mem.h +++ b/include/dict0mem.h @@ -51,7 +51,12 @@ combination of types */ #define DICT_UNIQUE 2 /*!< unique index */ #define DICT_UNIVERSAL 4 /*!< index which can contain records from any other index */ -#define DICT_IBUF 8 /*!< insert buffer tree */ +#define DICT_IBUF 8 /*!< insert buffer tree */ +#define DICT_CORRUPT 16 /*!< bit to store the corrupted flag + in SYS_INDEXES.TYPE */ + +#define DICT_IT_BITS 5 /*!< number of bits used for + SYS_INDEXES.TYPE */ /* @} */ /** Types for a table object */ @@ -369,8 +374,9 @@ struct dict_index_struct{ /*!< space where the index tree is placed */ unsigned page:32;/*!< index tree root page number */ #endif /* !UNIV_HOTBACKUP */ - unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE, - DICT_UNIVERSAL, DICT_IBUF) */ + unsigned type:DICT_IT_BITS; + /*!< index type (DICT_CLUSTERED, DICT_UNIQUE, + DICT_UNIVERSAL, DICT_IBUF, DICT_CORRUPT) */ unsigned trx_id_offset:10;/*!< position of the trx id column in a clustered index record, if the fields before it are known to be of a fixed size, @@ -391,8 +397,6 @@ struct dict_index_struct{ /*!< TRUE if this index is marked to be dropped in ha_innobase::prepare_drop_index(), otherwise FALSE */ - unsigned corrupted:1; - /*!< TRUE if the index object is corrupted */ dict_field_t* fields; /*!< array of field descriptions */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) diff --git a/include/dict0types.h b/include/dict0types.h index 8cbd7cd5783..f0a05a38070 100644 --- a/include/dict0types.h +++ b/include/dict0types.h @@ -51,7 +51,8 @@ be or-ed together */ enum dict_err_ignore { DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */ DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root - page is FIL_NUL or incorrect value */ + page is FIL_NULL or incorrect value */ + DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */ DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */ }; diff --git a/include/ha_prototypes.h b/include/ha_prototypes.h index 02e7712df58..8dc968baebe 100644 --- a/include/ha_prototypes.h +++ b/include/ha_prototypes.h @@ -303,4 +303,15 @@ ulint innobase_get_lower_case_table_names(void); /*=====================================*/ +/******************************************************************//** +Returns true if innodb_expand_fast_index_creation is enabled for the current +session. +@return the value of the server's innodb_expand_fast_index_creation variable */ + +ibool +thd_expand_fast_index_creation( +/*==================*/ + void* thd); /*!< in: thread handle (THD*) */ + + #endif diff --git a/include/mtr0mtr.h b/include/mtr0mtr.h index 5582ad63039..7f608546cc2 100644 --- a/include/mtr0mtr.h +++ b/include/mtr0mtr.h @@ -213,16 +213,6 @@ ulint mtr_set_savepoint( /*==============*/ mtr_t* mtr); /*!< in: mtr */ -/**********************************************************//** -Releases the latches stored in an mtr memo down to a savepoint. -NOTE! The mtr must not have made changes to buffer pages after the -savepoint, as these can be handled only by mtr_commit. */ -UNIV_INTERN -void -mtr_rollback_to_savepoint( -/*======================*/ - mtr_t* mtr, /*!< in: mtr */ - ulint savepoint); /*!< in: savepoint */ #ifndef UNIV_HOTBACKUP /**********************************************************//** Releases the (index tree) s-latch stored in an mtr memo after a diff --git a/include/os0file.h b/include/os0file.h index b778adaa809..366a2862e99 100644 --- a/include/os0file.h +++ b/include/os0file.h @@ -290,7 +290,8 @@ The wrapper functions have the prefix of "innodb_". */ __FILE__, __LINE__) # define os_file_read_trx(file, buf, offset, offset_high, n, trx) \ - os_file_read_func(file, buf, offset, offset_high, n, trx) + pfs_os_file_read_func(file, buf, offset, offset_high, n, trx, \ + __FILE__, __LINE__) # define os_file_read_no_error_handling(file, buf, offset, \ offset_high, n) \ diff --git a/include/page0page.h b/include/page0page.h index d4b90078029..3647dc57235 100644 --- a/include/page0page.h +++ b/include/page0page.h @@ -68,10 +68,7 @@ typedef byte page_header_t; #define PAGE_MAX_TRX_ID 18 /* highest id of a trx which may have modified a record on the page; trx_id_t; defined only in secondary indexes and in the insert buffer - tree; NOTE: this may be modified only - when the thread has an x-latch to the page, - and ALSO an x-latch to btr_search_latch - if there is a hash index to the page! */ + tree */ #define PAGE_HEADER_PRIV_END 26 /* end of private data structure of the page header which are set in a page create */ /*----*/ diff --git a/include/row0row.h b/include/row0row.h index 75e15d67246..c2849be7c3e 100644 --- a/include/row0row.h +++ b/include/row0row.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -38,27 +38,16 @@ Created 4/20/1996 Heikki Tuuri #include "btr0types.h" /*********************************************************************//** -Gets the offset of the trx id field, in bytes relative to the origin of +Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of a clustered index record. @return offset of DATA_TRX_ID */ UNIV_INLINE ulint -row_get_trx_id_offset_func( -/*=======================*/ -#ifdef UNIV_DEBUG - const rec_t* rec, /*!< in: record */ -#endif /* UNIV_DEBUG */ +row_get_trx_id_offset( +/*==================*/ const dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + const ulint* offsets)/*!< in: record offsets */ __attribute__((nonnull, warn_unused_result)); -#ifdef UNIV_DEBUG -# define row_get_trx_id_offset(rec, index, offsets) \ - row_get_trx_id_offset_func(rec, index, offsets) -#else /* UNIV_DEBUG */ -# define row_get_trx_id_offset(rec, index, offsets) \ - row_get_trx_id_offset_func(index, offsets) -#endif /* UNIV_DEBUG */ - /*********************************************************************//** Reads the trx id field from a clustered index record. @return value of the field */ @@ -77,9 +66,10 @@ UNIV_INLINE roll_ptr_t row_get_rec_roll_ptr( /*=================*/ - const rec_t* rec, /*!< in: record */ - dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets);/*!< in: rec_get_offsets(rec, index) */ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + __attribute__((nonnull, warn_unused_result)); /*****************************************************************//** When an insert or purge to a table is performed, this function builds the entry to be inserted into or purged from an index on the table. diff --git a/include/row0row.ic b/include/row0row.ic index 9d19e430e16..0b9ca982af8 100644 --- a/include/row0row.ic +++ b/include/row0row.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,25 +28,22 @@ Created 4/20/1996 Heikki Tuuri #include "trx0undo.h" /*********************************************************************//** -Gets the offset of trx id field, in bytes relative to the origin of +Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of a clustered index record. @return offset of DATA_TRX_ID */ UNIV_INLINE ulint -row_get_trx_id_offset_func( -/*=======================*/ -#ifdef UNIV_DEBUG - const rec_t* rec, /*!< in: record */ -#endif /* UNIV_DEBUG */ +row_get_trx_id_offset( +/*==================*/ const dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + const ulint* offsets)/*!< in: record offsets */ { ulint pos; ulint offset; ulint len; ut_ad(dict_index_is_clust(index)); - ut_ad(rec_offs_validate(rec, index, offsets)); + ut_ad(rec_offs_validate(NULL, index, offsets)); pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); @@ -76,7 +73,7 @@ row_get_rec_trx_id( offset = index->trx_id_offset; if (!offset) { - offset = row_get_trx_id_offset(rec, index, offsets); + offset = row_get_trx_id_offset(index, offsets); } return(trx_read_trx_id(rec + offset)); @@ -89,9 +86,9 @@ UNIV_INLINE roll_ptr_t row_get_rec_roll_ptr( /*=================*/ - const rec_t* rec, /*!< in: record */ - dict_index_t* index, /*!< in: clustered index */ - const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ + const rec_t* rec, /*!< in: record */ + const dict_index_t* index, /*!< in: clustered index */ + const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */ { ulint offset; @@ -101,7 +98,7 @@ row_get_rec_roll_ptr( offset = index->trx_id_offset; if (!offset) { - offset = row_get_trx_id_offset(rec, index, offsets); + offset = row_get_trx_id_offset(index, offsets); } return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN)); diff --git a/include/row0upd.ic b/include/row0upd.ic index 2968a548b34..11db82f64da 100644 --- a/include/row0upd.ic +++ b/include/row0upd.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -157,11 +157,6 @@ row_upd_rec_sys_fields( { ut_ad(dict_index_is_clust(index)); ut_ad(rec_offs_validate(rec, index, offsets)); -#ifdef UNIV_SYNC_DEBUG - if (!rw_lock_own(btr_search_get_latch(index->id), RW_LOCK_EX)) { - ut_ad(!buf_block_align(rec)->is_hashed); - } -#endif /* UNIV_SYNC_DEBUG */ if (UNIV_LIKELY_NULL(page_zip)) { ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); @@ -171,7 +166,7 @@ row_upd_rec_sys_fields( ulint offset = index->trx_id_offset; if (!offset) { - offset = row_get_trx_id_offset(rec, index, offsets); + offset = row_get_trx_id_offset(index, offsets); } #if DATA_TRX_ID + 1 != DATA_ROLL_PTR diff --git a/include/srv0srv.h b/include/srv0srv.h index 6277439694f..a36ee77929a 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -149,6 +149,10 @@ extern ulint srv_log_buffer_size; extern char srv_use_global_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +/* If this flag is TRUE, then we will load the indexes' (and tables') metadata +even if they are marked as "corrupted". Mostly it is for DBA to process +corrupted index and table */ +extern my_bool srv_load_corrupted; extern ulint srv_show_locks_held; extern ulint srv_show_verbose_locks; @@ -171,6 +175,7 @@ extern ulint srv_lock_table_size; extern ibool srv_thread_concurrency_timer_based; extern ulint srv_n_file_io_threads; +extern my_bool srv_random_read_ahead; extern ulong srv_read_ahead_threshold; extern ulint srv_n_read_io_threads; extern ulint srv_n_write_io_threads; @@ -291,6 +296,7 @@ extern ibool srv_print_latch_waits; extern ulint srv_activity_count; extern ulint srv_fatal_semaphore_wait_threshold; extern ulint srv_dml_needed_delay; +extern lint srv_kill_idle_transaction; extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, query threads, and lock table: we allocate @@ -365,6 +371,9 @@ extern ulint srv_buf_pool_reads; /** Time in seconds between automatic buffer pool dumps */ extern uint srv_auto_lru_dump; +/** Whether startup should be blocked until buffer pool is fully restored */ +extern ibool srv_blocking_lru_restore; + /** Status variables to be passed to MySQL */ typedef struct export_var_struct export_struc; @@ -762,6 +771,7 @@ struct export_var_struct{ ulint innodb_buffer_pool_pages_flushed; /*!< srv_buf_pool_flushed */ ulint innodb_buffer_pool_pages_LRU_flushed; /*!< buf_lru_flush_page_count */ ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */ + ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */ ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */ ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/ ulint innodb_checkpoint_age; diff --git a/include/sync0sync.h b/include/sync0sync.h index 32a20807ba0..d32c872c407 100644 --- a/include/sync0sync.h +++ b/include/sync0sync.h @@ -640,10 +640,6 @@ or row lock! */ #define SYNC_DICT_HEADER 995 #define SYNC_IBUF_HEADER 914 #define SYNC_IBUF_PESS_INSERT_MUTEX 912 -#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below - SYNC_FSP_PAGE: we assign a value this - high only to make the program to pass - the debug checks */ /*-------------------------------*/ #define SYNC_INDEX_TREE 900 #define SYNC_TREE_NODE_NEW 892 @@ -659,8 +655,11 @@ or row lock! */ #define SYNC_FSP 400 #define SYNC_FSP_PAGE 395 /*------------------------------------- Insert buffer headers */ -/*------------------------------------- ibuf_mutex */ +#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */ /*------------------------------------- Insert buffer tree */ +#define SYNC_IBUF_INDEX_TREE 360 +#define SYNC_IBUF_TREE_NODE_NEW 359 +#define SYNC_IBUF_TREE_NODE 358 #define SYNC_IBUF_BITMAP_MUTEX 351 #define SYNC_IBUF_BITMAP 350 /*------------------------------------- MySQL query cache mutex */ @@ -693,7 +692,6 @@ or row lock! */ #define SYNC_DOUBLEWRITE 140 #define SYNC_OUTER_ANY_LATCH 136 #define SYNC_ANY_LATCH 135 -#define SYNC_THR_LOCAL 133 #define SYNC_MEM_HASH 131 #define SYNC_MEM_POOL 130 diff --git a/include/sync0sync.ic b/include/sync0sync.ic index 1d9c8d59b12..aa54226be5d 100644 --- a/include/sync0sync.ic +++ b/include/sync0sync.ic @@ -272,11 +272,10 @@ pfs_mutex_enter_nowait_func( ulint ret; struct PSI_mutex_locker* locker = NULL; PSI_mutex_locker_state state; - int result = 0; if (UNIV_LIKELY(PSI_server && mutex->pfs_psi)) { locker = PSI_server->get_thread_mutex_locker( - &state, mutex->pfs_psi, PSI_MUTEX_LOCK); + &state, mutex->pfs_psi, PSI_MUTEX_TRYLOCK); if (locker) { PSI_server->start_mutex_wait(locker, file_name, line); } @@ -285,7 +284,7 @@ pfs_mutex_enter_nowait_func( ret = mutex_enter_nowait_func(mutex, file_name, line); if (locker) { - PSI_server->end_mutex_wait(locker, result); + PSI_server->end_mutex_wait(locker, ret); } return(ret); diff --git a/include/trx0sys.h b/include/trx0sys.h index db7bf68deae..495ce0e1184 100644 --- a/include/trx0sys.h +++ b/include/trx0sys.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2011, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -304,6 +304,17 @@ ibool trx_in_trx_list( /*============*/ trx_t* in_trx);/*!< in: trx */ +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG +/***********************************************************//** +Assert that a transaction has been recovered. +@return TRUE */ +UNIV_INLINE +ibool +trx_assert_recovered( +/*=================*/ + trx_id_t trx_id) /*!< in: transaction identifier */ + __attribute__((warn_unused_result)); +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ /*****************************************************************//** Updates the offset information about the end of the MySQL binlog entry which corresponds to the transaction just being committed. In a MySQL diff --git a/include/trx0sys.ic b/include/trx0sys.ic index aa2d2ea26b0..af05ab2f5ed 100644 --- a/include/trx0sys.ic +++ b/include/trx0sys.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -311,6 +311,28 @@ trx_get_on_id( return(NULL); } +#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG +/***********************************************************//** +Assert that a transaction has been recovered. +@return TRUE */ +UNIV_INLINE +ibool +trx_assert_recovered( +/*=================*/ + trx_id_t trx_id) /*!< in: transaction identifier */ +{ + trx_t* trx; + + mutex_enter(&kernel_mutex); + trx = trx_get_on_id(trx_id); + ut_a(trx); + ut_a(trx->is_recovered); + mutex_exit(&kernel_mutex); + + return(TRUE); +} +#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ + /****************************************************************//** Returns the minumum trx id in trx list. This is the smallest id for which the trx can possibly be active. (But, you must look at the trx->conc_state to diff --git a/include/trx0trx.h b/include/trx0trx.h index ab7404c5eff..4e010592e5a 100644 --- a/include/trx0trx.h +++ b/include/trx0trx.h @@ -512,6 +512,7 @@ struct trx_struct{ FALSE, one can save CPU time and about 150 bytes in the undo log size as then we skip XA steps */ + ulint fake_changes; ulint flush_log_later;/* In 2PC, we hold the prepare_commit mutex across both phases. In that case, we @@ -594,6 +595,8 @@ struct trx_struct{ replication has processed */ const char* mysql_relay_log_file_name; ib_int64_t mysql_relay_log_pos; + time_t idle_start; + ib_int64_t last_stmt_start; /*------------------------------*/ ulint n_mysql_tables_in_use; /* number of Innobase tables used in the processing of the current diff --git a/include/trx0undo.h b/include/trx0undo.h index df16c939070..50aa6d0ac09 100644 --- a/include/trx0undo.h +++ b/include/trx0undo.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -204,17 +204,51 @@ trx_undo_add_page( mtr_t* mtr); /*!< in: mtr which does not have a latch to any undo log page; the caller must have reserved the rollback segment mutex */ +/********************************************************************//** +Frees the last undo log page. +The caller must hold the rollback segment mutex. */ +UNIV_INTERN +void +trx_undo_free_last_page_func( +/*==========================*/ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction */ +#endif /* UNIV_DEBUG */ + trx_undo_t* undo, /*!< in/out: undo log memory copy */ + mtr_t* mtr) /*!< in/out: mini-transaction which does not + have a latch to any undo log page or which + has allocated the undo log page */ + __attribute__((nonnull)); +#ifdef UNIV_DEBUG +# define trx_undo_free_last_page(trx,undo,mtr) \ + trx_undo_free_last_page_func(trx,undo,mtr) +#else /* UNIV_DEBUG */ +# define trx_undo_free_last_page(trx,undo,mtr) \ + trx_undo_free_last_page_func(undo,mtr) +#endif /* UNIV_DEBUG */ + /***********************************************************************//** Truncates an undo log from the end. This function is used during a rollback to free space from an undo log. */ UNIV_INTERN void -trx_undo_truncate_end( -/*==================*/ - trx_t* trx, /*!< in: transaction whose undo log it is */ - trx_undo_t* undo, /*!< in: undo log */ - undo_no_t limit); /*!< in: all undo records with undo number +trx_undo_truncate_end_func( +/*=======================*/ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction whose undo log it is */ +#endif /* UNIV_DEBUG */ + trx_undo_t* undo, /*!< in/out: undo log */ + undo_no_t limit) /*!< in: all undo records with undo number >= this value should be truncated */ + __attribute__((nonnull)); +#ifdef UNIV_DEBUG +# define trx_undo_truncate_end(trx,undo,limit) \ + trx_undo_truncate_end_func(trx,undo,limit) +#else /* UNIV_DEBUG */ +# define trx_undo_truncate_end(trx,undo,limit) \ + trx_undo_truncate_end_func(undo,limit) +#endif /* UNIV_DEBUG */ + /***********************************************************************//** Truncates an undo log from the start. This function is used during a purge operation. */ diff --git a/include/ut0mem.h b/include/ut0mem.h index 57dfb08f41c..faf6f242883 100644 --- a/include/ut0mem.h +++ b/include/ut0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -210,43 +210,6 @@ ut_strlcpy_rev( ulint size); /*!< in: size of destination buffer */ /**********************************************************************//** -Compute strlen(ut_strcpyq(str, q)). -@return length of the string when quoted */ -UNIV_INLINE -ulint -ut_strlenq( -/*=======*/ - const char* str, /*!< in: null-terminated string */ - char q); /*!< in: the quote character */ - -/**********************************************************************//** -Make a quoted copy of a NUL-terminated string. Leading and trailing -quotes will not be included; only embedded quotes will be escaped. -See also ut_strlenq() and ut_memcpyq(). -@return pointer to end of dest */ -UNIV_INTERN -char* -ut_strcpyq( -/*=======*/ - char* dest, /*!< in: output buffer */ - char q, /*!< in: the quote character */ - const char* src); /*!< in: null-terminated string */ - -/**********************************************************************//** -Make a quoted copy of a fixed-length string. Leading and trailing -quotes will not be included; only embedded quotes will be escaped. -See also ut_strlenq() and ut_strcpyq(). -@return pointer to end of dest */ -UNIV_INTERN -char* -ut_memcpyq( -/*=======*/ - char* dest, /*!< in: output buffer */ - char q, /*!< in: the quote character */ - const char* src, /*!< in: string to be quoted */ - ulint len); /*!< in: length of src */ - -/**********************************************************************//** Return the number of times s2 occurs in s1. Overlapping instances of s2 are only counted once. @return the number of times s2 occurs in s1 */ diff --git a/include/ut0mem.ic b/include/ut0mem.ic index f36c28f1989..c06e2b3ae81 100644 --- a/include/ut0mem.ic +++ b/include/ut0mem.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -99,27 +99,6 @@ ut_strcmp(const char* str1, const char* str2) } /**********************************************************************//** -Compute strlen(ut_strcpyq(str, q)). -@return length of the string when quoted */ -UNIV_INLINE -ulint -ut_strlenq( -/*=======*/ - const char* str, /*!< in: null-terminated string */ - char q) /*!< in: the quote character */ -{ - ulint len; - - for (len = 0; *str; len++, str++) { - if (*str == q) { - len++; - } - } - - return(len); -} - -/**********************************************************************//** Converts a raw binary data to a NUL-terminated hex string. The output is truncated if there is not enough space in "hex", make sure "hex_size" is at least (2 * raw_size + 1) if you do not want this to happen. Returns the diff --git a/lock/lock0lock.c b/lock/lock0lock.c index 0fcbee32454..5fce345d0fe 100644 --- a/lock/lock0lock.c +++ b/lock/lock0lock.c @@ -3912,6 +3912,10 @@ lock_table( trx = thr_get_trx(thr); + if (trx->fake_changes && mode == LOCK_IX) { + mode = LOCK_IS; + } + lock_mutex_enter_kernel(); /* Look for stronger locks the same trx already has on the table */ @@ -5114,6 +5118,11 @@ lock_rec_insert_check_and_lock( } trx = thr_get_trx(thr); + + if (trx->fake_changes) { + return(DB_SUCCESS); + } + next_rec = page_rec_get_next_const(rec); next_rec_heap_no = page_rec_get_heap_no(next_rec); @@ -5282,6 +5291,10 @@ lock_clust_rec_modify_check_and_lock( return(DB_SUCCESS); } + if (thr && thr_get_trx(thr)->fake_changes) { + return(DB_SUCCESS); + } + heap_no = rec_offs_comp(offsets) ? rec_get_heap_no_new(rec) : rec_get_heap_no_old(rec); @@ -5340,6 +5353,10 @@ lock_sec_rec_modify_check_and_lock( return(DB_SUCCESS); } + if (thr && thr_get_trx(thr)->fake_changes) { + return(DB_SUCCESS); + } + heap_no = page_rec_get_heap_no(rec); /* Another transaction cannot have an implicit lock on the record, @@ -5427,6 +5444,10 @@ lock_sec_rec_read_check_and_lock( return(DB_SUCCESS); } + if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) { + mode = LOCK_S; + } + heap_no = page_rec_get_heap_no(rec); lock_mutex_enter_kernel(); @@ -5503,6 +5524,10 @@ lock_clust_rec_read_check_and_lock( return(DB_SUCCESS); } + if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) { + mode = LOCK_S; + } + heap_no = page_rec_get_heap_no(rec); lock_mutex_enter_kernel(); diff --git a/mtr/mtr0mtr.c b/mtr/mtr0mtr.c index 439b429db43..08234609ff0 100644 --- a/mtr/mtr0mtr.c +++ b/mtr/mtr0mtr.c @@ -282,44 +282,6 @@ mtr_commit( } #ifndef UNIV_HOTBACKUP -/**********************************************************//** -Releases the latches stored in an mtr memo down to a savepoint. -NOTE! The mtr must not have made changes to buffer pages after the -savepoint, as these can be handled only by mtr_commit. */ -UNIV_INTERN -void -mtr_rollback_to_savepoint( -/*======================*/ - mtr_t* mtr, /*!< in: mtr */ - ulint savepoint) /*!< in: savepoint */ -{ - mtr_memo_slot_t* slot; - dyn_array_t* memo; - ulint offset; - - ut_ad(mtr); - ut_ad(mtr->magic_n == MTR_MAGIC_N); - ut_ad(mtr->state == MTR_ACTIVE); - - memo = &(mtr->memo); - - offset = dyn_array_get_data_size(memo); - ut_ad(offset >= savepoint); - - while (offset > savepoint) { - offset -= sizeof(mtr_memo_slot_t); - - slot = dyn_array_get_element(memo, offset); - - ut_ad(slot->type != MTR_MEMO_MODIFY); - - /* We do not call mtr_memo_slot_note_modification() - because there MUST be no changes made to the buffer - pages after the savepoint */ - mtr_memo_slot_release(mtr, slot); - } -} - /***************************************************//** Releases an object in the memo stack. */ UNIV_INTERN diff --git a/os/os0file.c b/os/os0file.c index 835210140f8..0b1294a169e 100644 --- a/os/os0file.c +++ b/os/os0file.c @@ -4161,7 +4161,7 @@ os_aio_func( and os_file_write_func() */ if (type == OS_FILE_READ) { - return(os_file_read_trx(file, buf, offset, + return(os_file_read_func(file, buf, offset, offset_high, n, trx)); } diff --git a/page/page0zip.c b/page/page0zip.c index b81cba4826a..fc9f30ed94e 100644 --- a/page/page0zip.c +++ b/page/page0zip.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2005, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -151,6 +151,20 @@ page_zip_empty_size( #endif /* !UNIV_HOTBACKUP */ /*************************************************************//** +Gets the number of elements in the dense page directory, +including deleted records (the free list). +@return number of elements in the dense page directory */ +UNIV_INLINE +ulint +page_zip_dir_elems( +/*===============*/ + const page_zip_des_t* page_zip) /*!< in: compressed page */ +{ + /* Exclude the page infimum and supremum from the record count. */ + return(page_dir_get_n_heap(page_zip->data) - PAGE_HEAP_NO_USER_LOW); +} + +/*************************************************************//** Gets the size of the compressed page trailer (the dense page directory), including deleted records (the free list). @return length of dense page directory, in bytes */ @@ -160,14 +174,42 @@ page_zip_dir_size( /*==============*/ const page_zip_des_t* page_zip) /*!< in: compressed page */ { - /* Exclude the page infimum and supremum from the record count. */ - ulint size = PAGE_ZIP_DIR_SLOT_SIZE - * (page_dir_get_n_heap(page_zip->data) - - PAGE_HEAP_NO_USER_LOW); - return(size); + return(PAGE_ZIP_DIR_SLOT_SIZE * page_zip_dir_elems(page_zip)); +} + +/*************************************************************//** +Gets an offset to the compressed page trailer (the dense page directory), +including deleted records (the free list). +@return offset of the dense page directory */ +UNIV_INLINE +ulint +page_zip_dir_start_offs( +/*====================*/ + const page_zip_des_t* page_zip, /*!< in: compressed page */ + ulint n_dense) /*!< in: directory size */ +{ + ut_ad(n_dense * PAGE_ZIP_DIR_SLOT_SIZE < page_zip_get_size(page_zip)); + + return(page_zip_get_size(page_zip) - n_dense * PAGE_ZIP_DIR_SLOT_SIZE); } /*************************************************************//** +Gets a pointer to the compressed page trailer (the dense page directory), +including deleted records (the free list). +@param[in] page_zip compressed page +@param[in] n_dense number of entries in the directory +@return pointer to the dense page directory */ +#define page_zip_dir_start_low(page_zip, n_dense) \ + ((page_zip)->data + page_zip_dir_start_offs(page_zip, n_dense)) +/*************************************************************//** +Gets a pointer to the compressed page trailer (the dense page directory), +including deleted records (the free list). +@param[in] page_zip compressed page +@return pointer to the dense page directory */ +#define page_zip_dir_start(page_zip) \ + page_zip_dir_start_low(page_zip, page_zip_dir_elems(page_zip)) + +/*************************************************************//** Gets the size of the compressed page trailer (the dense page directory), only including user records (excluding the free list). @return length of dense page directory comprising existing records, in bytes */ @@ -2246,8 +2288,7 @@ zlib_done: } /* Restore the uncompressed columns in heap_no order. */ - storage = page_zip->data + page_zip_get_size(page_zip) - - n_dense * PAGE_ZIP_DIR_SLOT_SIZE; + storage = page_zip_dir_start_low(page_zip, n_dense); for (slot = 0; slot < n_dense; slot++) { rec_t* rec = recs[slot]; @@ -2732,8 +2773,7 @@ zlib_done: return(FALSE); } - storage = page_zip->data + page_zip_get_size(page_zip) - - n_dense * PAGE_ZIP_DIR_SLOT_SIZE; + storage = page_zip_dir_start_low(page_zip, n_dense); externs = storage - n_dense * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); @@ -3461,9 +3501,7 @@ page_zip_write_rec( } /* Write the data bytes. Store the uncompressed bytes separately. */ - storage = page_zip->data + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE; + storage = page_zip_dir_start(page_zip); if (page_is_leaf(page)) { ulint len; @@ -3759,9 +3797,7 @@ corrupt: field = page + offset; storage = page_zip->data + z_offset; - storage_end = page_zip->data + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE; + storage_end = page_zip_dir_start(page_zip); heap_no = 1 + (storage_end - storage) / REC_NODE_PTR_SIZE; @@ -3797,7 +3833,9 @@ page_zip_write_node_ptr( { byte* field; byte* storage; +#ifdef UNIV_DEBUG page_t* page = page_align(rec); +#endif /* UNIV_DEBUG */ ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); ut_ad(page_simple_validate_new(page)); @@ -3814,9 +3852,7 @@ page_zip_write_node_ptr( UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); UNIV_MEM_ASSERT_RW(rec, size); - storage = page_zip->data + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE + storage = page_zip_dir_start(page_zip) - (rec_get_heap_no_new(rec) - 1) * REC_NODE_PTR_SIZE; field = rec + size - REC_NODE_PTR_SIZE; @@ -3865,7 +3901,9 @@ page_zip_write_trx_id_and_roll_ptr( { byte* field; byte* storage; +#ifdef UNIV_DEBUG page_t* page = page_align(rec); +#endif /* UNIV_DEBUG */ ulint len; ut_ad(PAGE_ZIP_MATCH(rec, page_zip)); @@ -3883,9 +3921,7 @@ page_zip_write_trx_id_and_roll_ptr( UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); - storage = page_zip->data + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE + storage = page_zip_dir_start(page_zip) - (rec_get_heap_no_new(rec) - 1) * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); @@ -3916,17 +3952,9 @@ page_zip_write_trx_id_and_roll_ptr( UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); } -#ifdef UNIV_ZIP_DEBUG -/** Set this variable in a debugger to disable page_zip_clear_rec(). -The only observable effect should be the compression ratio due to -deleted records not being zeroed out. In rare cases, there can be -page_zip_validate() failures on the node_ptr, trx_id and roll_ptr -columns if the space is reallocated for a smaller record. */ -UNIV_INTERN ibool page_zip_clear_rec_disable; -#endif /* UNIV_ZIP_DEBUG */ - /**********************************************************************//** -Clear an area on the uncompressed and compressed page, if possible. */ +Clear an area on the uncompressed and compressed page. +Do not clear the data payload, as that would grow the modification log. */ static void page_zip_clear_rec( @@ -3938,6 +3966,9 @@ page_zip_clear_rec( { ulint heap_no; page_t* page = page_align(rec); + byte* storage; + byte* field; + ulint len; /* page_zip_validate() would fail here if a record containing externally stored columns is being deleted. */ ut_ad(rec_offs_validate(rec, index, offsets)); @@ -3953,60 +3984,38 @@ page_zip_clear_rec( UNIV_MEM_ASSERT_RW(rec - rec_offs_extra_size(offsets), rec_offs_extra_size(offsets)); - if ( -#ifdef UNIV_ZIP_DEBUG - !page_zip_clear_rec_disable && -#endif /* UNIV_ZIP_DEBUG */ - page_zip->m_end - + 1 + ((heap_no - 1) >= 64)/* size of the log entry */ - + page_zip_get_trailer_len(page_zip, - dict_index_is_clust(index), NULL) - < page_zip_get_size(page_zip)) { - byte* data; - - /* Clear only the data bytes, because the allocator and - the decompressor depend on the extra bytes. */ - memset(rec, 0, rec_offs_data_size(offsets)); - - if (!page_is_leaf(page)) { - /* Clear node_ptr on the compressed page. */ - byte* storage = page_zip->data - + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE; - - memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE, - 0, REC_NODE_PTR_SIZE); - } else if (dict_index_is_clust(index)) { - /* Clear trx_id and roll_ptr on the compressed page. */ - byte* storage = page_zip->data - + page_zip_get_size(page_zip) - - (page_dir_get_n_heap(page) - - PAGE_HEAP_NO_USER_LOW) - * PAGE_ZIP_DIR_SLOT_SIZE; - - memset(storage - (heap_no - 1) - * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN), - 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); - } + if (!page_is_leaf(page)) { + /* Clear node_ptr. On the compressed page, + there is an array of node_ptr immediately before the + dense page directory, at the very end of the page. */ + storage = page_zip_dir_start(page_zip); + ut_ad(dict_index_get_n_unique_in_tree(index) == + rec_offs_n_fields(offsets) - 1); + field = rec_get_nth_field(rec, offsets, + rec_offs_n_fields(offsets) - 1, + &len); + ut_ad(len == REC_NODE_PTR_SIZE); - /* Log that the data was zeroed out. */ - data = page_zip->data + page_zip->m_end; - ut_ad(!*data); - if (UNIV_UNLIKELY(heap_no - 1 >= 64)) { - *data++ = (byte) (0x80 | (heap_no - 1) >> 7); - ut_ad(!*data); - } - *data++ = (byte) ((heap_no - 1) << 1 | 1); - ut_ad(!*data); - ut_ad((ulint) (data - page_zip->data) - < page_zip_get_size(page_zip)); - page_zip->m_end = data - page_zip->data; - page_zip->m_nonempty = TRUE; - } else if (page_is_leaf(page) && dict_index_is_clust(index)) { - /* Do not clear the record, because there is not enough space - to log the operation. */ + ut_ad(!rec_offs_any_extern(offsets)); + memset(field, 0, REC_NODE_PTR_SIZE); + memset(storage - (heap_no - 1) * REC_NODE_PTR_SIZE, + 0, REC_NODE_PTR_SIZE); + } else if (dict_index_is_clust(index)) { + /* Clear trx_id and roll_ptr. On the compressed page, + there is an array of these fields immediately before the + dense page directory, at the very end of the page. */ + const ulint trx_id_pos + = dict_col_get_clust_pos( + dict_table_get_sys_col( + index->table, DATA_TRX_ID), index); + storage = page_zip_dir_start(page_zip); + field = rec_get_nth_field(rec, offsets, trx_id_pos, &len); + ut_ad(len == DATA_TRX_ID_LEN); + + memset(field, 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); + memset(storage - (heap_no - 1) + * (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN), + 0, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN); if (rec_offs_any_extern(offsets)) { ulint i; @@ -4015,15 +4024,18 @@ page_zip_clear_rec( /* Clear all BLOB pointers in order to make page_zip_validate() pass. */ if (rec_offs_nth_extern(offsets, i)) { - ulint len; - byte* field = rec_get_nth_field( + field = rec_get_nth_field( rec, offsets, i, &len); + ut_ad(len + == BTR_EXTERN_FIELD_REF_SIZE); memset(field + len - BTR_EXTERN_FIELD_REF_SIZE, 0, BTR_EXTERN_FIELD_REF_SIZE); } } } + } else { + ut_ad(!rec_offs_any_extern(offsets)); } #ifdef UNIV_ZIP_DEBUG diff --git a/pars/pars0opt.c b/pars/pars0opt.c index 2e392ba4836..d992805d9ef 100644 --- a/pars/pars0opt.c +++ b/pars/pars0opt.c @@ -568,7 +568,7 @@ opt_search_plan_for_table( best_last_op = last_op; } - index = dict_table_get_next_index(index); + dict_table_next_uncorrupted_index(index); } plan->index = best_index; diff --git a/percona-suite/percona_innodb_expand_fast_index_creation.result b/percona-suite/percona_innodb_expand_fast_index_creation.result new file mode 100644 index 00000000000..b8cec3d4398 --- /dev/null +++ b/percona-suite/percona_innodb_expand_fast_index_creation.result @@ -0,0 +1,64 @@ +CREATE TABLE t1( +id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +a CHAR(1) NOT NULL, +b CHAR(36) NOT NULL) ENGINE=InnoDB; +INSERT INTO t1(a,b) VALUES ('a','b'); +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; +ALTER TABLE t1 ADD KEY (a); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b; +id 1 +select_type SIMPLE +table t1 +type ALL +possible_keys a +key NULL +key_len NULL +ref NULL +rows 16 +Extra +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys a +key a +key_len 1 +ref test.t1.a +rows 1 +Extra Using where +ALTER TABLE t1 DROP KEY a; +SET expand_fast_index_creation = 1; +SELECT @@expand_fast_index_creation; +@@expand_fast_index_creation +1 +ALTER TABLE t1 ADD KEY (a); +affected rows: 0 +info: Records: 0 Duplicates: 0 Warnings: 0 +EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b; +id 1 +select_type SIMPLE +table t1 +type ALL +possible_keys a +key NULL +key_len NULL +ref NULL +rows 16 +Extra +id 1 +select_type SIMPLE +table t2 +type ALL +possible_keys a +key NULL +key_len NULL +ref NULL +rows 16 +Extra Using where; Using join buffer +SET expand_fast_index_creation = 0; +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_expand_fast_index_creation.test b/percona-suite/percona_innodb_expand_fast_index_creation.test new file mode 100644 index 00000000000..06e6c719c17 --- /dev/null +++ b/percona-suite/percona_innodb_expand_fast_index_creation.test @@ -0,0 +1,45 @@ +--source include/have_innodb.inc + +######################################################################## +# Bug #857590: Fast index creation does not update index statistics +######################################################################## + +CREATE TABLE t1( + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + a CHAR(1) NOT NULL, + b CHAR(36) NOT NULL) ENGINE=InnoDB; + +INSERT INTO t1(a,b) VALUES ('a','b'); +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; +INSERT INTO t1(a,b) SELECT a,b FROM t1; + +# Check that fast index creation is used +--enable_info +ALTER TABLE t1 ADD KEY (a); +--disable_info + +# The default (wrong) plan due to bogus statistics +--vertical_results +EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b; +--horizontal_results + +ALTER TABLE t1 DROP KEY a; + +SET expand_fast_index_creation = 1; +SELECT @@expand_fast_index_creation; + +# Check that stats are updated with the option enabled + +--enable_info +ALTER TABLE t1 ADD KEY (a); +--disable_info + +--vertical_results +EXPLAIN SELECT COUNT(*) FROM t1, t1 t2 WHERE t1.a = t2.a AND t1.b = t2.b; +--horizontal_results + +SET expand_fast_index_creation = 0; + +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_fake_changes.result b/percona-suite/percona_innodb_fake_changes.result new file mode 100644 index 00000000000..7f00c687c54 --- /dev/null +++ b/percona-suite/percona_innodb_fake_changes.result @@ -0,0 +1,55 @@ +DROP TABLE IF EXISTS t1; +# Checking variables +SHOW VARIABLES LIKE 'innodb_fake_changes'; +Variable_name Value +innodb_fake_changes OFF +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; +VARIABLE_VALUE +OFF +SET innodb_fake_changes=1; +SHOW VARIABLES LIKE 'innodb_fake_changes'; +Variable_name Value +innodb_fake_changes ON +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; +VARIABLE_VALUE +ON +SET innodb_fake_changes=default; +SHOW VARIABLES LIKE 'innodb_fake_changes'; +Variable_name Value +innodb_fake_changes OFF +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; +VARIABLE_VALUE +OFF +# Explicit COMMIT should fail when innodb_fake_changes is enabled +# DML should be fine +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +INSERT INTO t1 VALUES (2); +UPDATE t1 SET a=0; +DELETE FROM t1 LIMIT 1; +SELECT * FROM t1; +a +1 +COMMIT; +ERROR HY000: Got error 131 during COMMIT +SET innodb_fake_changes=default; +DROP TABLE t1; +# DDL must result in error +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +ERROR HY000: Can't create table 'test.t2' (errno: 131) +DROP TABLE t1; +ERROR 42S02: Unknown table 't1' +TRUNCATE TABLE t1; +ERROR HY000: Got error 131 during COMMIT +ALTER TABLE t1 ENGINE=MyISAM; +ERROR HY000: Got error 131 during COMMIT +ROLLBACK; +SET innodb_fake_changes=default; +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_fake_changes.test b/percona-suite/percona_innodb_fake_changes.test new file mode 100644 index 00000000000..fd231ae096f --- /dev/null +++ b/percona-suite/percona_innodb_fake_changes.test @@ -0,0 +1,49 @@ +--source include/have_innodb.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + + +--echo # Checking variables +SHOW VARIABLES LIKE 'innodb_fake_changes'; +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; +SET innodb_fake_changes=1; +SHOW VARIABLES LIKE 'innodb_fake_changes'; +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; +SET innodb_fake_changes=default; +SHOW VARIABLES LIKE 'innodb_fake_changes'; +SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='innodb_fake_changes'; + +--echo # Explicit COMMIT should fail when innodb_fake_changes is enabled +--echo # DML should be fine +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +INSERT INTO t1 VALUES (2); +UPDATE t1 SET a=0; +DELETE FROM t1 LIMIT 1; +SELECT * FROM t1; +--error 1180 +COMMIT; +SET innodb_fake_changes=default; +DROP TABLE t1; + +--echo # DDL must result in error +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +--error 1005 +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +--error 1051 +DROP TABLE t1; +--error 1180 +TRUNCATE TABLE t1; +--error 1180 +ALTER TABLE t1 ENGINE=MyISAM; +ROLLBACK; +SET innodb_fake_changes=default; +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_fake_changes_locks.result b/percona-suite/percona_innodb_fake_changes_locks.result new file mode 100644 index 00000000000..c2b533ca9f3 --- /dev/null +++ b/percona-suite/percona_innodb_fake_changes_locks.result @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS t1; +# Verifying that X_LOCK not acquired +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +SELECT * FROM t1 FOR UPDATE; +a +1 +SET innodb_lock_wait_timeout=3; +UPDATE t1 SET a=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1 LOCK IN SHARE MODE; +a +1 +ROLLBACK; +SET innodb_fake_changes=default; +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_fake_changes_locks.test b/percona-suite/percona_innodb_fake_changes_locks.test new file mode 100644 index 00000000000..e298405cd43 --- /dev/null +++ b/percona-suite/percona_innodb_fake_changes_locks.test @@ -0,0 +1,24 @@ +--source include/have_innodb.inc + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # Verifying that X_LOCK not acquired +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +--connect (conn1,localhost,root,,) +--connection conn1 +SET autocommit=0; +SET innodb_fake_changes=1; +BEGIN; +SELECT * FROM t1 FOR UPDATE; +--connection default +SET innodb_lock_wait_timeout=3; +--error 1205 +UPDATE t1 SET a=2; +SELECT * FROM t1 LOCK IN SHARE MODE; +--connection conn1 +ROLLBACK; +SET innodb_fake_changes=default; +DROP TABLE t1; diff --git a/percona-suite/percona_innodb_kill_idle_trx.result b/percona-suite/percona_innodb_kill_idle_trx.result new file mode 100644 index 00000000000..a05b5a912fe --- /dev/null +++ b/percona-suite/percona_innodb_kill_idle_trx.result @@ -0,0 +1,41 @@ +DROP TABLE IF EXISTS t1; +SET autocommit=0; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 0 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 0 +SET GLOBAL innodb_kill_idle_transaction=1; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 1 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 1 +BEGIN; +INSERT INTO t1 VALUES (1),(2),(3); +COMMIT; +SELECT * FROM t1; +a +1 +2 +3 +BEGIN; +INSERT INTO t1 VALUES (4),(5),(6); +SELECT * FROM t1; +ERROR HY000: MySQL server has gone away +SELECT * FROM t1; +a +1 +2 +3 +DROP TABLE t1; +SET GLOBAL innodb_kill_idle_transaction=0; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 0 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 0 diff --git a/percona-suite/percona_innodb_kill_idle_trx.test b/percona-suite/percona_innodb_kill_idle_trx.test new file mode 100644 index 00000000000..908f313752e --- /dev/null +++ b/percona-suite/percona_innodb_kill_idle_trx.test @@ -0,0 +1,28 @@ +--source include/have_innodb.inc +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +SET autocommit=0; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +--source include/percona_innodb_kill_idle_trx_show.inc +SET GLOBAL innodb_kill_idle_transaction=1; +--source include/percona_innodb_kill_idle_trx_show.inc + +BEGIN; +INSERT INTO t1 VALUES (1),(2),(3); +COMMIT; +SELECT * FROM t1; + +BEGIN; +INSERT INTO t1 VALUES (4),(5),(6); +sleep 3; + +--enable_reconnect +--error 2006 --error CR_SERVER_GONE_ERROR +SELECT * FROM t1; +SELECT * FROM t1; +DROP TABLE t1; +SET GLOBAL innodb_kill_idle_transaction=0; +--source include/percona_innodb_kill_idle_trx_show.inc diff --git a/percona-suite/percona_innodb_kill_idle_trx_locks.result b/percona-suite/percona_innodb_kill_idle_trx_locks.result new file mode 100644 index 00000000000..6bdd2617805 --- /dev/null +++ b/percona-suite/percona_innodb_kill_idle_trx_locks.result @@ -0,0 +1,45 @@ +DROP TABLE IF EXISTS t1; +SET autocommit=0; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 0 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 0 +SET GLOBAL innodb_kill_idle_transaction=5; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 5 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 5 +BEGIN; +INSERT INTO t1 VALUES (1),(2),(3); +COMMIT; +SELECT * FROM t1; +a +1 +2 +3 +### Locking rows. Lock should be released when idle trx is killed. +BEGIN; +SELECT * FROM t1 FOR UPDATE; +a +1 +2 +3 +UPDATE t1 set a=4; +SELECT * FROM t1; +a +4 +4 +4 +DROP TABLE t1; +SET GLOBAL innodb_kill_idle_transaction=0; +SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction'; +Variable_name Value +innodb_kill_idle_transaction 0 +SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_KILL_IDLE_TRANSACTION 0 diff --git a/percona-suite/percona_innodb_kill_idle_trx_locks.test b/percona-suite/percona_innodb_kill_idle_trx_locks.test new file mode 100644 index 00000000000..20e2cc54a84 --- /dev/null +++ b/percona-suite/percona_innodb_kill_idle_trx_locks.test @@ -0,0 +1,31 @@ +--source include/have_innodb.inc +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +SET autocommit=0; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +--source include/percona_innodb_kill_idle_trx_show.inc +SET GLOBAL innodb_kill_idle_transaction=5; +--source include/percona_innodb_kill_idle_trx_show.inc + +connect (conn1,localhost,root,,); +connection conn1; + +BEGIN; +INSERT INTO t1 VALUES (1),(2),(3); +COMMIT; +SELECT * FROM t1; + +--echo ### Locking rows. Lock should be released when idle trx is killed. +BEGIN; +SELECT * FROM t1 FOR UPDATE; + +connection default; +UPDATE t1 set a=4; + +SELECT * FROM t1; +DROP TABLE t1; +SET GLOBAL innodb_kill_idle_transaction=0; +--source include/percona_innodb_kill_idle_trx_show.inc diff --git a/percona-suite/percona_log_connection_error.result b/percona-suite/percona_log_connection_error.result index 3c6c67f770c..352c9ca2a99 100644 --- a/percona-suite/percona_log_connection_error.result +++ b/percona-suite/percona_log_connection_error.result @@ -12,4 +12,5 @@ connect(localhost,root,,test,port,socket); ERROR HY000: Too many connections SET GLOBAL max_connections = @old_max_connections; SET GLOBAL log_warnings = @old_log_warnings; -1 +[log_grep.inc] file: percona.log_connection_error.err pattern: Too many connections +[log_grep.inc] lines: 1 diff --git a/percona-suite/percona_log_connection_error.test b/percona-suite/percona_log_connection_error.test index b1c03bfebc4..84af364cc96 100644 --- a/percona-suite/percona_log_connection_error.test +++ b/percona-suite/percona_log_connection_error.test @@ -45,10 +45,10 @@ if(!`select LENGTH('$log_error_')`) # does not know the location of its .err log, use default location let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err; } -# Assign env variable LOG_ERROR -let LOG_ERROR=$log_error_; ---let grep_file = $log_error ---let grep_pattern = Too many connections ---source include/grep.inc -exec $cmd; +--let log_error=$log_error_ +--let log_file=percona.log_connection_error.err +--let log_file_full_path=$log_error +--let grep_pattern= Too many connections +--source include/log_grep.inc + diff --git a/percona-suite/percona_processlist_row_stats.result b/percona-suite/percona_processlist_row_stats.result index e9b07b2eaea..109b6a912d9 100644 --- a/percona-suite/percona_processlist_row_stats.result +++ b/percona-suite/percona_processlist_row_stats.result @@ -6,69 +6,65 @@ INSERT INTO t2 VALUES(10); INSERT INTO t2 VALUES(20); INSERT INTO t2 VALUES(10); INSERT INTO t2 VALUES(20); -Issuing operation that should not return any rows and stopping the thread #1 SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped'; CREATE TABLE t1 (a INT); SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; -Thread #1 stopped -Issuing row-returning query and stopping the thread #2 at the end of query SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped'; SELECT a FROM t2 WHERE a > 15; SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; -Thread #2 stopped -Look at thread states SHOW PROCESSLIST; Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read ### root ### test Query ### ### SHOW PROCESSLIST 0 0 2 ### root ### test Query ### ### CREATE TABLE t1 (a INT) 0 0 1 ### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 2 5 6 -SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist -ORDER BY id; +SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; id info rows_sent rows_examined rows_read -### SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist -ORDER BY id 0 0 1 +### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1 ### CREATE TABLE t1 (a INT) 0 0 1 ### SELECT a FROM t2 WHERE a > 15 2 5 6 -Let threads #1 and #2 finish their job SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; a 20 20 -Issuing row-returning query and stopping the thread #2 in the middle of query +SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped'; +SELECT a FROM t2 WHERE a < 15; +SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped'; SELECT a FROM t2 WHERE a > 15; SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; -Thread #2 stopped, look at its state SHOW PROCESSLIST; Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read ### root ### test Query ### ### SHOW PROCESSLIST 0 0 4 -### root ### test Sleep ### ### NULL 0 0 1 +### root ### test Query ### ### SELECT a FROM t2 WHERE a < 15 1 0 1 ### root ### test Query ### ### SELECT a FROM t2 WHERE a > 15 1 0 3 -SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id; -id rows_sent rows_examined rows_read -### 0 0 1 -### 0 0 1 -### 1 0 3 +SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; +id info rows_sent rows_examined rows_read +### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1 +### SELECT a FROM t2 WHERE a < 15 1 0 1 +### SELECT a FROM t2 WHERE a > 15 1 0 3 SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; -Let thread #2 finish its job +a +10 +10 +10 a 20 20 -Issuing an UPDATE and stopping thread #2 +SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped'; +UPDATE t2 SET a = 15 WHERE a = 20; +SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped'; UPDATE t2 SET a = 15 WHERE a = 10; SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; -Thread #2 stopped, look at its state SHOW PROCESSLIST; Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read ### root ### test Query ### ### SHOW PROCESSLIST 0 0 4 -### root ### test Sleep ### ### NULL 0 0 1 +### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6 ### root ### test Query ### ### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6 -SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id; -id rows_sent rows_examined rows_read -### 0 0 1 -### 0 0 1 -### 0 5 6 +SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; +id info rows_sent rows_examined rows_read +### SELECT id, info, rows_sent, rows_examined, rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id 0 0 1 +### UPDATE t2 SET a = 15 WHERE a = 20 0 5 6 +### UPDATE t2 SET a = 15 WHERE a = 10 0 5 6 SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; -Let thread #2 finish its job DROP TABLES t1, t2; diff --git a/percona-suite/percona_processlist_row_stats.test b/percona-suite/percona_processlist_row_stats.test index 230a9f4c311..17ebfedfa40 100644 --- a/percona-suite/percona_processlist_row_stats.test +++ b/percona-suite/percona_processlist_row_stats.test @@ -13,76 +13,63 @@ INSERT INTO t2 VALUES(20); INSERT INTO t2 VALUES(10); INSERT INTO t2 VALUES(20); -connect (conn1, localhost, root, ,); -connect (conn2, localhost, root, ,); +--connect (conn1, localhost, root, ,) +--connect (conn2, localhost, root, ,) --connection conn1 -echo Issuing operation that should not return any rows and stopping the thread #1; SET DEBUG_SYNC= 'locked_table_name SIGNAL thread1_ready WAIT_FOR threads_dumped'; send CREATE TABLE t1 (a INT); - --connection default SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; ---echo Thread #1 stopped --connection conn2 -echo Issuing row-returning query and stopping the thread #2 at the end of query; SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped'; send SELECT a FROM t2 WHERE a > 15; - --connection default SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; ---echo Thread #2 stopped ---echo Look at thread states - ---replace_column 1 ### 3 ### 6 ### 7 ### -SHOW PROCESSLIST; -# The running threads are different between SHOW above and SELECT below. Thus select info too to -# show the difference. Results are in the same order as in SHOW. ---replace_column 1 ### -SELECT id, info, rows_sent, rows_examined, rows_read FROM information_schema.processlist -ORDER BY id; -echo Let threads #1 and #2 finish their job; -SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; +--source include/percona_processlist_row_stats_show.inc --connection conn1 reap; - --connection conn2 reap; -echo Issuing row-returning query and stopping the thread #2 in the middle of query; + +--connection conn1 +SET DEBUG_SYNC= 'sent_row SIGNAL thread1_ready WAIT_FOR threads_dumped'; +send SELECT a FROM t2 WHERE a < 15; +--connection default +SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; + +--connection conn2 SET DEBUG_SYNC= 'sent_row SIGNAL thread2_ready WAIT_FOR threads_dumped'; send SELECT a FROM t2 WHERE a > 15; - --connection default SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; -echo Thread #2 stopped, look at its state; ---replace_column 1 ### 3 ### 6 ### 7 ### -SHOW PROCESSLIST; ---replace_column 1 ### -SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id; -SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; -echo Let thread #2 finish its job; +--source include/percona_processlist_row_stats_show.inc +--connection conn1 +reap; --connection conn2 reap; -echo Issuing an UPDATE and stopping thread #2; + +--connection conn1 +SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread1_ready WAIT_FOR threads_dumped'; +send UPDATE t2 SET a = 15 WHERE a = 20; +--connection default +SET DEBUG_SYNC= 'now WAIT_FOR thread1_ready'; + +--connection conn2 SET DEBUG_SYNC= 'execute_command_after_close_tables SIGNAL thread2_ready WAIT_FOR threads_dumped'; send UPDATE t2 SET a = 15 WHERE a = 10; - --connection default SET DEBUG_SYNC= 'now WAIT_FOR thread2_ready'; -echo Thread #2 stopped, look at its state; ---replace_column 1 ### 3 ### 6 ### 7 ### -SHOW PROCESSLIST; ---replace_column 1 ### -SELECT id,rows_sent,rows_examined,rows_read FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY Id; -SET DEBUG_SYNC= 'now SIGNAL threads_dumped'; -echo Let thread #2 finish its job; +--source include/percona_processlist_row_stats_show.inc +--connection conn1 +reap; --connection conn2 reap; diff --git a/percona-suite/percona_query_response_time-replication.result b/percona-suite/percona_query_response_time-replication.result index fd06d07b4d8..c00520110c2 100644 --- a/percona-suite/percona_query_response_time-replication.result +++ b/percona-suite/percona_query_response_time-replication.result @@ -1,66 +1,727 @@ +SET GLOBAL query_exec_time=0.1; include/master-slave.inc [connection master] -DROP TABLE IF EXISTS t; CREATE TABLE t(id INT); -SELECT * from t; -id -SELECT * from t; -id -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1; Warnings: Warning 1292 Truncated incorrect query_response_time_range_base value: '1' +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +Variable_name Value +query_response_time_range_base 2 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 1 0.100000 + 0.250000 0 0.000000 + 0.500000 30 10.650000 + 1.000000 3 1.500000 + 2.000000 15 19.500000 + 4.000000 12 30.000000 + 8.000000 6 27.599997 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 1 0.100000 + 0.250000 0 0.000000 + 0.500000 30 10.650000 + 1.000000 3 1.500000 + 2.000000 15 19.500000 + 4.000000 12 30.000000 + 8.000000 6 27.599997 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2; +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 2 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 1 0.100000 + 0.250000 0 0.000000 + 0.500000 30 10.650000 + 1.000000 3 1.500000 + 2.000000 15 19.500000 + 4.000000 12 30.000000 + 8.000000 6 27.599997 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 1 0.100000 + 0.250000 0 0.000000 + 0.500000 30 10.650000 + 1.000000 3 1.500000 + 2.000000 15 19.500000 + 4.000000 12 30.000000 + 8.000000 6 27.599997 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10; +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 10 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 34 12.250000 + 10.000000 33 77.099997 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 34 12.250000 + 10.000000 33 77.099997 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7; FLUSH QUERY_RESPONSE_TIME; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=ON; -INSERT INTO t SELECT SLEEP(0.4); -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -0 -INSERT INTO t SELECT SLEEP(0.4); -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -0 -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -2 -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -3 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value -query_response_time_range_base 2 +query_response_time_range_base 7 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 1 0.100000 + 1.000000 33 12.150000 + 7.000000 33 77.099997 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 1 0.100000 + 1.000000 33 12.150000 + 7.000000 33 77.099997 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156; FLUSH QUERY_RESPONSE_TIME; -INSERT INTO t SELECT SLEEP(0.4); -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -0 -INSERT INTO t SELECT SLEEP(0.4); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +Variable_name Value +query_response_time_range_base 156 +SHOW QUERY_RESPONSE_TIME; + + 0.000041 1 0.000000 + 0.006410 0 0.000000 + 1.000000 34 12.250000 + 156.000000 33 77.099997 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000041 1 0.000000 + 0.006410 0 0.000000 + 1.000000 34 12.250000 + 156.000000 33 77.099997 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000; +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +Variable_name Value +query_response_time_range_base 1000 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.001000 0 0.000000 + 1.000000 34 12.250000 + 1000.000000 33 77.099997 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.001000 0 0.000000 + 1.000000 34 12.250000 + 1000.000000 33 77.099997 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +CREATE TABLE t(id INT); +SET GLOBAL query_exec_time = 0.1; +include/restart_slave.inc +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001; Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -0 -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -2 -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) -3 -DROP TABLE IF EXISTS t; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=OFF; -STOP SLAVE; -include/wait_for_slave_to_stop.inc +Warning 1292 Truncated incorrect query_response_time_range_base value: '1001' +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time = 0.31; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; +INSERT INTO t VALUES(1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +Variable_name Value +query_response_time_range_base 1000 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 1 0.000000 + 0.001000 0 0.000000 + 1.000000 34 12.250000 + 1000.000000 33 77.099997 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 1 0.000000 + 0.001000 0 0.000000 + 1.000000 34 12.250000 + 1000.000000 33 77.099997 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP TABLE t; +include/rpl_end.inc +SET GLOBAL query_exec_time=default; +SET GLOBAL query_exec_time=default; diff --git a/percona-suite/percona_query_response_time-replication.test b/percona-suite/percona_query_response_time-replication.test index 199ecce0977..1207e5d1c3d 100644 --- a/percona-suite/percona_query_response_time-replication.test +++ b/percona-suite/percona_query_response_time-replication.test @@ -1,61 +1,28 @@ +SET GLOBAL query_exec_time=0.1; + --source include/have_response_time_distribution.inc ---source include/master-slave.inc ---source include/have_binlog_format_statement.inc --source include/have_debug.inc ---disable_query_log -call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement:"); ---enable_query_log - -connection master; --- disable_warnings -DROP TABLE IF EXISTS t; --- enable_warnings -CREATE TABLE t(id INT); -SELECT * from t; - -sync_slave_with_master; - -connection slave; -SELECT * from t; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=ON; - -connection master; -INSERT INTO t SELECT SLEEP(0.4); -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -INSERT INTO t SELECT SLEEP(0.4); -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -sync_slave_with_master; - -connection slave; -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; - -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -source include/percona_query_response_time_flush.inc; - -connection master; -INSERT INTO t SELECT SLEEP(0.4); -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -INSERT INTO t SELECT SLEEP(0.4); -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -sync_slave_with_master; +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc -connection slave; -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -SELECT SUM(INFORMATION_SCHEMA.QUERY_RESPONSE_TIME.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +--let base=1 +--source include/query_response_time-replication.inc +--let base=2 +--source include/query_response_time-replication.inc +--let base=10 +--source include/query_response_time-replication.inc +--let base=7 +--source include/query_response_time-replication.inc +--let base=156 +--source include/query_response_time-replication.inc +--let base=1000 +--source include/query_response_time-replication.inc +--let base=1001 +--source include/query_response_time-replication.inc + +--source include/rpl_end.inc + +SET GLOBAL query_exec_time=default; -connection master; -DROP TABLE IF EXISTS t; -sync_slave_with_master; connection slave; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=OFF; - -STOP SLAVE; --- source include/wait_for_slave_to_stop.inc +SET GLOBAL query_exec_time=default; diff --git a/percona-suite/percona_query_response_time-stored.result b/percona-suite/percona_query_response_time-stored.result index 0168c4630be..7385231241e 100644 --- a/percona-suite/percona_query_response_time-stored.result +++ b/percona-suite/percona_query_response_time-stored.result @@ -1,306 +1,544 @@ -SET GLOBAL debug="d,query_exec_time_debug"; -CREATE FUNCTION test_f() -RETURNS CHAR(30) DETERMINISTIC +CREATE TABLE t(a INT); +CREATE PROCEDURE test_f(t DECIMAL(3,2)) BEGIN -SET SESSION debug="+d,query_exec_time_1.1"; -RETURN 'Hello, world!'; -END/ -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; +SET SESSION query_exec_time=t; +INSERT INTO t VALUES(1); +SET SESSION query_exec_time=0.1; +DELETE FROM t; +END^ +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1; Warnings: Warning 1292 Truncated incorrect query_response_time_range_base value: '1' +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 2 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 2 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 44 4.400000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 44 4.400000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2; FLUSH QUERY_RESPONSE_TIME; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -44 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000003 - 0.000007 - 0.000015 - 0.000030 - 0.000061 - 0.000122 - 0.000244 - 0.000488 - 0.000976 - 0.001953 - 0.003906 - 0.007812 - 0.015625 - 0.031250 - 0.062500 - 0.125000 - 0.250000 - 0.500000 - 1.000000 - 2.000000 - 4.000000 - 8.000000 - 16.000000 - 32.000000 - 64.000000 - 128.000000 - 256.000000 - 512.000000 - 1024.000000 - 2048.000000 - 4096.000000 - 8192.000000 - 16384.000000 - 32768.000000 - 65536.000000 - 131072.000000 - 262144.000000 - 524288.000000 - 1048576.00000 - 2097152.00000 - 4194304.00000 - 8388608.00000 -TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -test_f() -Hello, world! -SELECT test_f(); -test_f() -Hello, world! -SELECT test_f(); -test_f() -Hello, world! -SELECT test_f(); -test_f() -Hello, world! +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -4 4 4 1 44 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -44 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000003 - 0.000007 - 0.000015 - 0.000030 - 0.000061 - 0.000122 - 0.000244 - 0.000488 - 0.000976 - 0.001953 - 0.003906 - 0.007812 - 0.015625 - 0.031250 - 0.062500 - 0.125000 - 0.250000 - 0.500000 - 1.000000 - 2.000000 - 4.000000 - 8.000000 - 16.000000 - 32.000000 - 64.000000 - 128.000000 - 256.000000 - 512.000000 - 1024.000000 - 2048.000000 - 4096.000000 - 8192.000000 - 16384.000000 - 32768.000000 - 65536.000000 - 131072.000000 - 262144.000000 - 524288.000000 - 1048576.00000 - 2097152.00000 - 4194304.00000 - 8388608.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 2 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 10 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 44 4.400000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 44 4.400000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10; FLUSH QUERY_RESPONSE_TIME; SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -test_f() -Hello, world! +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -1 1 1 1 14 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -14 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000010 - 0.000100 - 0.001000 - 0.010000 - 0.100000 - 1.000000 - 10.000000 - 100.000000 - 1000.000000 - 10000.000000 - 100000.000000 - 1000000.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 10 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 7 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 55 8.450000 + 10.000000 11 25.699999 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 55 8.450000 + 10.000000 11 25.699999 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7; FLUSH QUERY_RESPONSE_TIME; SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -test_f() -Hello, world! +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -1 1 1 1 17 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -17 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000008 - 0.000059 - 0.000416 - 0.002915 - 0.020408 - 0.142857 - 1.000000 - 7.000000 - 49.000000 - 343.000000 - 2401.000000 - 16807.000000 - 117649.000000 - 823543.000000 - 5764801.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 7 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 156 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 44 4.400000 + 1.000000 11 4.050000 + 7.000000 11 25.699999 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 44 4.400000 + 1.000000 11 4.050000 + 7.000000 11 25.699999 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156; FLUSH QUERY_RESPONSE_TIME; SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -test_f() -Hello, world! +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -1 1 1 1 7 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -7 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000041 - 0.006410 - 1.000000 - 156.000000 - 24336.000000 - 3796416.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 156 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 1000 +SHOW QUERY_RESPONSE_TIME; + + 0.000041 45 0.000000 + 0.006410 0 0.000000 + 1.000000 55 8.450000 + 156.000000 11 25.699999 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000041 45 0.000000 + 0.006410 0 0.000000 + 1.000000 55 8.450000 + 156.000000 11 25.699999 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000; FLUSH QUERY_RESPONSE_TIME; SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -test_f() -Hello, world! +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -1 1 1 1 6 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -6 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.001000 - 1.000000 - 1000.000000 - 1000000.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 1000 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.001000 0 0.000000 + 1.000000 55 8.450000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.001000 0 0.000000 + 1.000000 55 8.450000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001; Warnings: Warning 1292 Truncated incorrect query_response_time_range_base value: '1001' +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 1000 -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10; -DROP FUNCTION test_f; -SET GLOBAL debug=default; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 45 0.000000 + 0.001000 0 0.000000 + 1.000000 55 8.450000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 45 0.000000 + 0.001000 0 0.000000 + 1.000000 55 8.450000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; +DROP PROCEDURE test_f; +DROP TABLE t; diff --git a/percona-suite/percona_query_response_time-stored.test b/percona-suite/percona_query_response_time-stored.test index e80fc3dd3c0..847ff223b3f 100644 --- a/percona-suite/percona_query_response_time-stored.test +++ b/percona-suite/percona_query_response_time-stored.test @@ -1,85 +1,36 @@ --source include/have_response_time_distribution.inc --source include/have_debug.inc -SET GLOBAL debug="d,query_exec_time_debug"; +CREATE TABLE t(a INT); -delimiter /; -CREATE FUNCTION test_f() -RETURNS CHAR(30) DETERMINISTIC +delimiter ^; +CREATE PROCEDURE test_f(t DECIMAL(3,2)) BEGIN - SET SESSION debug="+d,query_exec_time_1.1"; - RETURN 'Hello, world!'; -END/ -delimiter ;/ - -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -source include/percona_query_response_time_show.inc; - -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -SELECT test_f(); -SELECT test_f(); -SELECT test_f(); -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SELECT test_f(); -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10; - -DROP FUNCTION test_f; - -SET GLOBAL debug=default; + SET SESSION query_exec_time=t; + INSERT INTO t VALUES(1); + SET SESSION query_exec_time=0.1; + DELETE FROM t; +END^ +delimiter ;^ + +--let base=1 +--source include/query_response_time-stored.inc +--let base=2 +--source include/query_response_time-stored.inc +--let base=10 +--source include/query_response_time-stored.inc +--let base=7 +--source include/query_response_time-stored.inc +--let base=156 +--source include/query_response_time-stored.inc +--let base=1000 +--source include/query_response_time-stored.inc +--let base=1001 +--source include/query_response_time-stored.inc + +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; + +DROP PROCEDURE test_f; + +DROP TABLE t; diff --git a/percona-suite/percona_query_response_time.result b/percona-suite/percona_query_response_time.result index 2243c155e39..4c4d50319c0 100644 --- a/percona-suite/percona_query_response_time.result +++ b/percona-suite/percona_query_response_time.result @@ -1,377 +1,1307 @@ -SET GLOBAL debug="d,query_exec_time_debug"; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1; Warnings: Warning 1292 Truncated incorrect query_response_time_range_base value: '1' +FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 0 0.000000 + 1.000000 0 0.000000 + 2.000000 0 0.000000 + 4.000000 0 0.000000 + 8.000000 0 0.000000 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 0 0.000000 + 1.000000 0 0.000000 + 2.000000 0 0.000000 + 4.000000 0 0.000000 + 8.000000 0 0.000000 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 2 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 2 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=2; FLUSH QUERY_RESPONSE_TIME; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -44 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000003 - 0.000007 - 0.000015 - 0.000030 - 0.000061 - 0.000122 - 0.000244 - 0.000488 - 0.000976 - 0.001953 - 0.003906 - 0.007812 - 0.015625 - 0.031250 - 0.062500 - 0.125000 - 0.250000 - 0.500000 - 1.000000 - 2.000000 - 4.000000 - 8.000000 - 16.000000 - 32.000000 - 64.000000 - 128.000000 - 256.000000 - 512.000000 - 1024.000000 - 2048.000000 - 4096.000000 - 8192.000000 - 16384.000000 - 32768.000000 - 65536.000000 - 131072.000000 - 262144.000000 - 524288.000000 - 1048576.00000 - 2097152.00000 - 4194304.00000 - 8388608.00000 -TOO LONG +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 0 0.000000 + 1.000000 0 0.000000 + 2.000000 0 0.000000 + 4.000000 0 0.000000 + 8.000000 0 0.000000 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 0 0.000000 + 1.000000 0 0.000000 + 2.000000 0 0.000000 + 4.000000 0 0.000000 + 8.000000 0 0.000000 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SET SESSION debug="+d,query_exec_time_0.31"; -SET SESSION debug="+d,query_exec_time_0.32"; -SET SESSION debug="+d,query_exec_time_0.33"; -SET SESSION debug="+d,query_exec_time_0.34"; -SET SESSION debug="+d,query_exec_time_0.35"; -SET SESSION debug="+d,query_exec_time_0.36"; -SET SESSION debug="+d,query_exec_time_0.37"; -SET SESSION debug="+d,query_exec_time_0.38"; -SET SESSION debug="+d,query_exec_time_0.39"; -SET SESSION debug="+d,query_exec_time_0.4"; -SET SESSION debug="+d,query_exec_time_1.1"; -SET SESSION debug="+d,query_exec_time_1.2"; -SET SESSION debug="+d,query_exec_time_1.3"; -SET SESSION debug="+d,query_exec_time_1.5"; -SET SESSION debug="+d,query_exec_time_1.4"; -SET SESSION debug="+d,query_exec_time_0.5"; -SET SESSION debug="+d,query_exec_time_2.1"; -SET SESSION debug="+d,query_exec_time_2.3"; -SET SESSION debug="+d,query_exec_time_2.5"; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -10 19 15 4 44 -1 19 15 4 44 -5 19 15 4 44 -3 19 15 4 44 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -44 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000003 - 0.000007 - 0.000015 - 0.000030 - 0.000061 - 0.000122 - 0.000244 - 0.000488 - 0.000976 - 0.001953 - 0.003906 - 0.007812 - 0.015625 - 0.031250 - 0.062500 - 0.125000 - 0.250000 - 0.500000 - 1.000000 - 2.000000 - 4.000000 - 8.000000 - 16.000000 - 32.000000 - 64.000000 - 128.000000 - 256.000000 - 512.000000 - 1024.000000 - 2048.000000 - 4096.000000 - 8192.000000 - 16384.000000 - 32768.000000 - 65536.000000 - 131072.000000 - 262144.000000 - 524288.000000 - 1048576.00000 - 2097152.00000 - 4194304.00000 - 8388608.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 2 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 10 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.000003 0 0.000000 + 0.000007 0 0.000000 + 0.000015 0 0.000000 + 0.000030 0 0.000000 + 0.000061 0 0.000000 + 0.000122 0 0.000000 + 0.000244 0 0.000000 + 0.000488 0 0.000000 + 0.000976 0 0.000000 + 0.001953 0 0.000000 + 0.003906 0 0.000000 + 0.007812 0 0.000000 + 0.015625 0 0.000000 + 0.031250 0 0.000000 + 0.062500 0 0.000000 + 0.125000 0 0.000000 + 0.250000 0 0.000000 + 0.500000 10 3.550000 + 1.000000 1 0.500000 + 2.000000 5 6.500000 + 4.000000 4 10.000000 + 8.000000 2 9.199999 + 16.000000 0 0.000000 + 32.000000 0 0.000000 + 64.000000 0 0.000000 + 128.000000 0 0.000000 + 256.000000 0 0.000000 + 512.000000 0 0.000000 + 1024.000000 0 0.000000 + 2048.000000 0 0.000000 + 4096.000000 0 0.000000 + 8192.000000 0 0.000000 + 16384.000000 0 0.000000 + 32768.000000 0 0.000000 + 65536.000000 0 0.000000 + 131072.000000 0 0.000000 + 262144.000000 0 0.000000 + 524288.000000 0 0.000000 + 1048576.00000 0 0.000000 + 2097152.00000 0 0.000000 + 4194304.00000 0 0.000000 + 8388608.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=10; FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 0 0.000000 + 10.000000 0 0.000000 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 0 0.000000 + 10.000000 0 0.000000 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SET SESSION debug="+d,query_exec_time_0.31"; -SET SESSION debug="+d,query_exec_time_0.32"; -SET SESSION debug="+d,query_exec_time_0.33"; -SET SESSION debug="+d,query_exec_time_0.34"; -SET SESSION debug="+d,query_exec_time_0.35"; -SET SESSION debug="+d,query_exec_time_0.36"; -SET SESSION debug="+d,query_exec_time_0.37"; -SET SESSION debug="+d,query_exec_time_0.38"; -SET SESSION debug="+d,query_exec_time_0.39"; -SET SESSION debug="+d,query_exec_time_0.4"; -SET SESSION debug="+d,query_exec_time_1.1"; -SET SESSION debug="+d,query_exec_time_1.2"; -SET SESSION debug="+d,query_exec_time_1.3"; -SET SESSION debug="+d,query_exec_time_1.5"; -SET SESSION debug="+d,query_exec_time_1.4"; -SET SESSION debug="+d,query_exec_time_0.5"; -SET SESSION debug="+d,query_exec_time_2.1"; -SET SESSION debug="+d,query_exec_time_2.3"; -SET SESSION debug="+d,query_exec_time_2.5"; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -11 19 17 2 14 -8 19 17 2 14 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -14 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000010 - 0.000100 - 0.001000 - 0.010000 - 0.100000 - 1.000000 - 10.000000 - 100.000000 - 1000.000000 - 10000.000000 - 100000.000000 - 1000000.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 10 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 7 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 11 4.050000 + 10.000000 11 25.699999 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.000010 0 0.000000 + 0.000100 0 0.000000 + 0.001000 0 0.000000 + 0.010000 0 0.000000 + 0.100000 0 0.000000 + 1.000000 11 4.050000 + 10.000000 11 25.699999 + 100.000000 0 0.000000 + 1000.000000 0 0.000000 + 10000.000000 0 0.000000 + 100000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=7; FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 0 0.000000 + 1.000000 0 0.000000 + 7.000000 0 0.000000 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 0 0.000000 + 1.000000 0 0.000000 + 7.000000 0 0.000000 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SET SESSION debug="+d,query_exec_time_0.31"; -SET SESSION debug="+d,query_exec_time_0.32"; -SET SESSION debug="+d,query_exec_time_0.33"; -SET SESSION debug="+d,query_exec_time_0.34"; -SET SESSION debug="+d,query_exec_time_0.35"; -SET SESSION debug="+d,query_exec_time_0.36"; -SET SESSION debug="+d,query_exec_time_0.37"; -SET SESSION debug="+d,query_exec_time_0.38"; -SET SESSION debug="+d,query_exec_time_0.39"; -SET SESSION debug="+d,query_exec_time_0.4"; -SET SESSION debug="+d,query_exec_time_1.1"; -SET SESSION debug="+d,query_exec_time_1.2"; -SET SESSION debug="+d,query_exec_time_1.3"; -SET SESSION debug="+d,query_exec_time_1.5"; -SET SESSION debug="+d,query_exec_time_1.4"; -SET SESSION debug="+d,query_exec_time_0.5"; -SET SESSION debug="+d,query_exec_time_2.1"; -SET SESSION debug="+d,query_exec_time_2.3"; -SET SESSION debug="+d,query_exec_time_2.5"; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -11 19 17 2 17 -8 19 17 2 17 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -17 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.000008 - 0.000059 - 0.000416 - 0.002915 - 0.020408 - 0.142857 - 1.000000 - 7.000000 - 49.000000 - 343.000000 - 2401.000000 - 16807.000000 - 117649.000000 - 823543.000000 - 5764801.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 7 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 156 +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 0 0.000000 + 1.000000 11 4.050000 + 7.000000 11 25.699999 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.000008 0 0.000000 + 0.000059 0 0.000000 + 0.000416 0 0.000000 + 0.002915 0 0.000000 + 0.020408 0 0.000000 + 0.142857 0 0.000000 + 1.000000 11 4.050000 + 7.000000 11 25.699999 + 49.000000 0 0.000000 + 343.000000 0 0.000000 + 2401.000000 0 0.000000 + 16807.000000 0 0.000000 + 117649.000000 0 0.000000 + 823543.000000 0 0.000000 + 5764801.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=156; FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000041 0 0.000000 + 0.006410 0 0.000000 + 1.000000 0 0.000000 + 156.000000 0 0.000000 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000041 0 0.000000 + 0.006410 0 0.000000 + 1.000000 0 0.000000 + 156.000000 0 0.000000 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SET SESSION debug="+d,query_exec_time_0.31"; -SET SESSION debug="+d,query_exec_time_0.32"; -SET SESSION debug="+d,query_exec_time_0.33"; -SET SESSION debug="+d,query_exec_time_0.34"; -SET SESSION debug="+d,query_exec_time_0.35"; -SET SESSION debug="+d,query_exec_time_0.36"; -SET SESSION debug="+d,query_exec_time_0.37"; -SET SESSION debug="+d,query_exec_time_0.38"; -SET SESSION debug="+d,query_exec_time_0.39"; -SET SESSION debug="+d,query_exec_time_0.4"; -SET SESSION debug="+d,query_exec_time_1.1"; -SET SESSION debug="+d,query_exec_time_1.2"; -SET SESSION debug="+d,query_exec_time_1.3"; -SET SESSION debug="+d,query_exec_time_1.5"; -SET SESSION debug="+d,query_exec_time_1.4"; -SET SESSION debug="+d,query_exec_time_0.5"; -SET SESSION debug="+d,query_exec_time_2.1"; -SET SESSION debug="+d,query_exec_time_2.3"; -SET SESSION debug="+d,query_exec_time_2.5"; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -11 19 17 2 7 -8 19 17 2 7 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -7 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000041 - 0.006410 - 1.000000 - 156.000000 - 24336.000000 - 3796416.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 156 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -Variable_name Value -query_response_time_range_base 1000 +SHOW QUERY_RESPONSE_TIME; + + 0.000041 24 0.000000 + 0.006410 0 0.000000 + 1.000000 11 4.050000 + 156.000000 11 25.699999 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000041 24 0.000000 + 0.006410 0 0.000000 + 1.000000 11 4.050000 + 156.000000 11 25.699999 + 24336.000000 0 0.000000 + 3796416.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1000; FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.001000 0 0.000000 + 1.000000 0 0.000000 + 1000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.001000 0 0.000000 + 1.000000 0 0.000000 + 1000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -SET SESSION debug="+d,query_exec_time_0.31"; -SET SESSION debug="+d,query_exec_time_0.32"; -SET SESSION debug="+d,query_exec_time_0.33"; -SET SESSION debug="+d,query_exec_time_0.34"; -SET SESSION debug="+d,query_exec_time_0.35"; -SET SESSION debug="+d,query_exec_time_0.36"; -SET SESSION debug="+d,query_exec_time_0.37"; -SET SESSION debug="+d,query_exec_time_0.38"; -SET SESSION debug="+d,query_exec_time_0.39"; -SET SESSION debug="+d,query_exec_time_0.4"; -SET SESSION debug="+d,query_exec_time_1.1"; -SET SESSION debug="+d,query_exec_time_1.2"; -SET SESSION debug="+d,query_exec_time_1.3"; -SET SESSION debug="+d,query_exec_time_1.5"; -SET SESSION debug="+d,query_exec_time_1.4"; -SET SESSION debug="+d,query_exec_time_0.5"; -SET SESSION debug="+d,query_exec_time_2.1"; -SET SESSION debug="+d,query_exec_time_2.3"; -SET SESSION debug="+d,query_exec_time_2.5"; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SELECT d.count, -(SELECT SUM(a.count) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a WHERE a.count != 0) as query_count, -(SELECT SUM((b.total * 1000000) DIV 1000000) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as b WHERE b.count != 0) as query_total, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c WHERE c.count != 0) as not_zero_region_count, -(SELECT COUNT(*) FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME) as region_count -FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as d WHERE d.count > 0; -count query_count query_total not_zero_region_count region_count -11 19 17 2 6 -8 19 17 2 6 -SELECT COUNT(*) as region_count FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -region_count -6 -SELECT time FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; -time - 0.000001 - 0.001000 - 1.000000 - 1000.000000 - 1000000.00000 -TOO LONG SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 1000 -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.001000 0 0.000000 + 1.000000 11 4.050000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.001000 0 0.000000 + 1.000000 11 4.050000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=1001; Warnings: Warning 1292 Truncated incorrect query_response_time_range_base value: '1001' +FLUSH QUERY_RESPONSE_TIME; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 0 0.000000 + 0.001000 0 0.000000 + 1.000000 0 0.000000 + 1000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 0 0.000000 + 0.001000 0 0.000000 + 1.000000 0 0.000000 + 1000.000000 0 0.000000 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; +SET SESSION query_exec_time=0.31; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.32; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.33; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.34; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.35; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.36; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.37; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.38; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.39; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.2; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=1.4; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.3; +SELECT 1; +1 +1 +SET SESSION query_exec_time=2.5; +SELECT 1; +1 +1 +SET SESSION query_exec_time=3.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=4.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=5.1; +SELECT 1; +1 +1 +SET SESSION query_exec_time=0.1; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; Variable_name Value query_response_time_range_base 1000 -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10; -SET GLOBAL debug=default; +SHOW QUERY_RESPONSE_TIME; + + 0.000001 24 0.000000 + 0.001000 0 0.000000 + 1.000000 11 4.050000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +time count total + 0.000001 24 0.000000 + 0.001000 0 0.000000 + 1.000000 11 4.050000 + 1000.000000 11 25.699999 + 1000000.00000 0 0.000000 +TOO LONG 0 TOO LONG +SET SESSION query_exec_time=default; +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; diff --git a/percona-suite/percona_query_response_time.test b/percona-suite/percona_query_response_time.test index f2df156b13d..d4fb9c61388 100644 --- a/percona-suite/percona_query_response_time.test +++ b/percona-suite/percona_query_response_time.test @@ -1,71 +1,20 @@ --source include/have_response_time_distribution.inc --source include/have_debug.inc -SET GLOBAL debug="d,query_exec_time_debug"; - -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 2; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -source include/percona_query_response_time_show.inc; - -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -source include/percona_query_response_time_sleep.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 10; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -source include/percona_query_response_time_sleep.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 7; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -source include/percona_query_response_time_sleep.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 156; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -source include/percona_query_response_time_sleep.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1000; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -source include/percona_query_response_time_flush.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; -source include/percona_query_response_time_sleep.inc; -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; - -source include/percona_query_response_time_show.inc; - -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE = 1001; -SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; - -SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; -SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE =10; - -SET GLOBAL debug=default; +--let base=1 +--source include/query_response_time.inc +--let base=2 +--source include/query_response_time.inc +--let base=10 +--source include/query_response_time.inc +--let base=7 +--source include/query_response_time.inc +--let base=156 +--source include/query_response_time.inc +--let base=1000 +--source include/query_response_time.inc +--let base=1001 +--source include/query_response_time.inc + +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; diff --git a/percona-suite/percona_server_variables_debug.result b/percona-suite/percona_server_variables_debug.result index 1ffaa6a7704..ea1c02e7716 100644 --- a/percona-suite/percona_server_variables_debug.result +++ b/percona-suite/percona_server_variables_debug.result @@ -41,6 +41,7 @@ DIV_PRECISION_INCREMENT ENGINE_CONDITION_PUSHDOWN ERROR_COUNT EVENT_SCHEDULER +EXPAND_FAST_INDEX_CREATION EXPIRE_LOGS_DAYS EXTERNAL_USER FAST_INDEX_CREATION @@ -83,6 +84,7 @@ INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS INNODB_ADDITIONAL_MEM_POOL_SIZE INNODB_AUTOEXTEND_INCREMENT INNODB_AUTOINC_LOCK_MODE +INNODB_BLOCKING_BUFFER_POOL_RESTORE INNODB_BUFFER_POOL_INSTANCES INNODB_BUFFER_POOL_RESTORE_AT_STARTUP INNODB_BUFFER_POOL_SHM_CHECKSUM @@ -100,6 +102,7 @@ INNODB_DATA_HOME_DIR INNODB_DICT_SIZE_LIMIT INNODB_DOUBLEWRITE INNODB_DOUBLEWRITE_FILE +INNODB_FAKE_CHANGES INNODB_FAST_CHECKSUM INNODB_FAST_SHUTDOWN INNODB_FILE_FORMAT @@ -109,12 +112,15 @@ INNODB_FILE_PER_TABLE INNODB_FLUSH_LOG_AT_TRX_COMMIT INNODB_FLUSH_METHOD INNODB_FLUSH_NEIGHBOR_PAGES +INNODB_FORCE_LOAD_CORRUPTED INNODB_FORCE_RECOVERY INNODB_IBUF_ACCEL_RATE INNODB_IBUF_ACTIVE_CONTRACT INNODB_IBUF_MAX_SIZE INNODB_IMPORT_TABLE_FROM_XTRABACKUP INNODB_IO_CAPACITY +INNODB_KILL_IDLE_TRANSACTION +INNODB_LARGE_PREFIX INNODB_LAZY_DROP_TABLE INNODB_LOCKS_UNSAFE_FOR_BINLOG INNODB_LOCK_WAIT_TIMEOUT @@ -132,6 +138,7 @@ INNODB_OPEN_FILES INNODB_PAGE_SIZE INNODB_PURGE_BATCH_SIZE INNODB_PURGE_THREADS +INNODB_RANDOM_READ_AHEAD INNODB_READ_AHEAD INNODB_READ_AHEAD_THRESHOLD INNODB_READ_IO_THREADS @@ -187,6 +194,7 @@ LOG_ERROR LOG_OUTPUT LOG_QUERIES_NOT_USING_INDEXES LOG_SLAVE_UPDATES +LOG_SLOW_ADMIN_STATEMENTS LOG_SLOW_FILTER LOG_SLOW_QUERIES LOG_SLOW_RATE_LIMIT @@ -275,6 +283,7 @@ QUERY_CACHE_SIZE QUERY_CACHE_STRIP_COMMENTS QUERY_CACHE_TYPE QUERY_CACHE_WLOCK_INVALIDATE +QUERY_EXEC_TIME QUERY_PREALLOC_SIZE QUERY_RESPONSE_TIME_RANGE_BASE QUERY_RESPONSE_TIME_STATS diff --git a/percona-suite/percona_server_variables_release.result b/percona-suite/percona_server_variables_release.result index cabd69b19a6..e5965cf7e5e 100644 --- a/percona-suite/percona_server_variables_release.result +++ b/percona-suite/percona_server_variables_release.result @@ -39,6 +39,7 @@ DIV_PRECISION_INCREMENT ENGINE_CONDITION_PUSHDOWN ERROR_COUNT EVENT_SCHEDULER +EXPAND_FAST_INDEX_CREATION EXPIRE_LOGS_DAYS EXTERNAL_USER FAST_INDEX_CREATION @@ -81,6 +82,7 @@ INNODB_ADAPTIVE_HASH_INDEX_PARTITIONS INNODB_ADDITIONAL_MEM_POOL_SIZE INNODB_AUTOEXTEND_INCREMENT INNODB_AUTOINC_LOCK_MODE +INNODB_BLOCKING_BUFFER_POOL_RESTORE INNODB_BUFFER_POOL_INSTANCES INNODB_BUFFER_POOL_RESTORE_AT_STARTUP INNODB_BUFFER_POOL_SHM_CHECKSUM @@ -97,6 +99,7 @@ INNODB_DATA_HOME_DIR INNODB_DICT_SIZE_LIMIT INNODB_DOUBLEWRITE INNODB_DOUBLEWRITE_FILE +INNODB_FAKE_CHANGES INNODB_FAST_CHECKSUM INNODB_FAST_SHUTDOWN INNODB_FILE_FORMAT @@ -106,12 +109,15 @@ INNODB_FILE_PER_TABLE INNODB_FLUSH_LOG_AT_TRX_COMMIT INNODB_FLUSH_METHOD INNODB_FLUSH_NEIGHBOR_PAGES +INNODB_FORCE_LOAD_CORRUPTED INNODB_FORCE_RECOVERY INNODB_IBUF_ACCEL_RATE INNODB_IBUF_ACTIVE_CONTRACT INNODB_IBUF_MAX_SIZE INNODB_IMPORT_TABLE_FROM_XTRABACKUP INNODB_IO_CAPACITY +INNODB_KILL_IDLE_TRANSACTION +INNODB_LARGE_PREFIX INNODB_LAZY_DROP_TABLE INNODB_LOCKS_UNSAFE_FOR_BINLOG INNODB_LOCK_WAIT_TIMEOUT @@ -129,6 +135,7 @@ INNODB_OPEN_FILES INNODB_PAGE_SIZE INNODB_PURGE_BATCH_SIZE INNODB_PURGE_THREADS +INNODB_RANDOM_READ_AHEAD INNODB_READ_AHEAD INNODB_READ_AHEAD_THRESHOLD INNODB_READ_IO_THREADS @@ -184,6 +191,7 @@ LOG_ERROR LOG_OUTPUT LOG_QUERIES_NOT_USING_INDEXES LOG_SLAVE_UPDATES +LOG_SLOW_ADMIN_STATEMENTS LOG_SLOW_FILTER LOG_SLOW_QUERIES LOG_SLOW_RATE_LIMIT diff --git a/percona-suite/percona_show_slave_status_nolock.result b/percona-suite/percona_show_slave_status_nolock.result index 1d6114a001e..b98e4a93953 100644 --- a/percona-suite/percona_show_slave_status_nolock.result +++ b/percona-suite/percona_show_slave_status_nolock.result @@ -1,21 +1,69 @@ include/master-slave.inc [connection master] +call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes"); +include/rpl_connect.inc [creating slave_lock] +include/rpl_connect.inc [creating slave_nolock] +[master] DROP TABLE IF EXISTS t; CREATE TABLE t(id INT); -INSERT INTO t SELECT SLEEP(10); +[slave] +SET DEBUG_SYNC='RESET'; +SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status"; +[master] +INSERT INTO t VALUES(0); +[slave] +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine + +[slave_lock] +SHOW SLAVE STATUS; +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; +SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status' +[slave] +SET DEBUG_SYNC='now SIGNAL signal.empty'; +[slave_nolock] +SHOW SLAVE STATUS NOLOCK; +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; +# should be 'signal.after_show_slave_status' +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' +[slave] +SET DEBUG_SYNC='now SIGNAL signal.continue'; +[slave] +SET DEBUG_SYNC='now SIGNAL signal.empty'; + +[master] +INSERT INTO t VALUES(1); +[slave] +include/rpl_connect.inc [creating slave_stop] +[slave_stop] STOP SLAVE; -Warnings: -Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. -master count(*) -master 1 -slave count(*) -slave 0 +[slave] +check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine + +[slave_lock] +SHOW SLAVE STATUS; +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; +SIGNAL after SHOW SLAVE STATUS is 'signal.empty' +[slave] +SET DEBUG_SYNC='now SIGNAL signal.empty'; +[slave_nolock] SHOW SLAVE STATUS NOLOCK; +SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1'; +# should be 'signal.after_show_slave_status' +SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status' +[slave] +SET DEBUG_SYNC='now SIGNAL signal.continue'; +[slave] +SET DEBUG_SYNC='now SIGNAL signal.empty'; + +[slave_stop] include/wait_for_slave_to_stop.inc START SLAVE; include/wait_for_slave_to_start.inc -slave count(*) -slave 1 +[master] +SET DEBUG_SYNC='RESET'; +[slave] +SET GLOBAL DEBUG=''; +SET DEBUG_SYNC='RESET'; +[master] DROP TABLE t; -STOP SLAVE; -include/wait_for_slave_to_stop.inc +include/rpl_end.inc diff --git a/percona-suite/percona_show_slave_status_nolock.test b/percona-suite/percona_show_slave_status_nolock.test index d26b5332fe8..df595214ff7 100644 --- a/percona-suite/percona_show_slave_status_nolock.test +++ b/percona-suite/percona_show_slave_status_nolock.test @@ -1,53 +1,90 @@ --source include/master-slave.inc +--source include/have_debug_sync.inc --source include/have_binlog_format_statement.inc ---disable_query_log -call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement:"); -call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group"); ---enable_query_log + +call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes"); + +--let $rpl_connection_name=slave_lock +--let $rpl_server_number=2 +--source include/rpl_connect.inc + +--let $rpl_connection_name=slave_nolock +--let $rpl_server_number=2 +--source include/rpl_connect.inc + +--let $show_statement= SHOW PROCESSLIST +--let $field= Info + connection master; - --disable_warnings - DROP TABLE IF EXISTS t; - --enable_warnings - CREATE TABLE t(id INT); - sync_slave_with_master; +--echo [master] +--disable_warnings +DROP TABLE IF EXISTS t; +--enable_warnings +CREATE TABLE t(id INT); +sync_slave_with_master; + +connection slave; +--echo [slave] +SET DEBUG_SYNC='RESET'; +SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status"; connection master; - send INSERT INTO t SELECT SLEEP(10); +--echo [master] +INSERT INTO t VALUES(0); connection slave; - sleep 15; - send STOP SLAVE; +--echo [slave] +--let $condition= 'INSERT INTO t VALUES(0)' +--source include/wait_show_condition.inc + +--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine +--source include/percona_show_slave_status_nolock.inc connection master; - reap; +--echo [master] +INSERT INTO t VALUES(1); - --disable_query_log - select "master",count(*) from t; - --enable_query_log +connection slave; +--echo [slave] +--let $condition= 'INSERT INTO t VALUES(1)' +--source include/wait_show_condition.inc -connection slave1; - --disable_query_log - select "slave",count(*) from t; - --enable_query_log +--let $rpl_connection_name=slave_stop +--let $rpl_server_number=2 +--source include/rpl_connect.inc - --disable_result_log - SHOW SLAVE STATUS NOLOCK; - --enable_result_log +connection slave_stop; +--echo [slave_stop] +send STOP SLAVE; connection slave; - reap; +--echo [slave] +--let $condition= 'STOP SLAVE' +--source include/wait_show_condition.inc + +--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine +--source include/percona_show_slave_status_nolock.inc - --source include/wait_for_slave_to_stop.inc - START SLAVE; - --source include/wait_for_slave_to_start.inc - --disable_query_log - select "slave",count(*) from t; - --enable_query_log +connection slave_stop; +--echo [slave_stop] +reap; +--source include/wait_for_slave_to_stop.inc +START SLAVE; +--source include/wait_for_slave_to_start.inc connection master; - DROP TABLE t; +--echo [master] +SET DEBUG_SYNC='RESET'; + +connection slave; +--echo [slave] +SET GLOBAL DEBUG=''; +SET DEBUG_SYNC='RESET'; + +connection master; +--echo [master] +DROP TABLE t; sync_slave_with_master; -STOP SLAVE; ---source include/wait_for_slave_to_stop.inc -
\ No newline at end of file + +--source include/rpl_end.inc diff --git a/percona-suite/percona_status_wait_query_cache_mutex.result b/percona-suite/percona_status_wait_query_cache_mutex.result index f951428abc7..678ed685a5b 100644 --- a/percona-suite/percona_status_wait_query_cache_mutex.result +++ b/percona-suite/percona_status_wait_query_cache_mutex.result @@ -1,4 +1,4 @@ -set GLOBAL query_cache_size=1355776; +SET GLOBAL query_cache_size=1355776; flush query cache; flush query cache; reset query cache; @@ -8,20 +8,16 @@ CREATE TABLE t(id INT, number INT); INSERT INTO t VALUES (0,1); INSERT INTO t VALUES (1,2); INSERT INTO t VALUES (2,3); +SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep"; +SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready'; SELECT number from t where id > 0; -number -2 -3 -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; -SELECT number from t where id > 0; -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; -SELECT number from t where id > 0; -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; SHOW PROCESSLIST; Id User Host db Command Time State Info Rows_sent Rows_examined Rows_read -Id root localhost test Sleep Time NULL Rows_sent Rows_examined Rows_read -Id root localhost test Query Time Waiting on query cache mutex SELECT number from t where id > 0 Rows_sent Rows_examined Rows_read -Id root localhost test Query Time Waiting on query cache mutex SELECT number from t where id > 0 Rows_sent Rows_examined Rows_read -Id root localhost test Query Time NULL SHOW PROCESSLIST Rows_sent Rows_examined Rows_read +### root ### test Query ### NULL SHOW PROCESSLIST ### ### ### +### root ### test Query ### Waiting on query cache mutex SELECT number from t where id > 0 ### ### ### +SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; +id info state +### SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id executing +### SELECT number from t where id > 0 Waiting on query cache mutex DROP TABLE t; -set GLOBAL query_cache_size=0; +SET GLOBAL query_cache_size=0; diff --git a/percona-suite/percona_status_wait_query_cache_mutex.test b/percona-suite/percona_status_wait_query_cache_mutex.test index 35e2d0ac549..1e586ca4e7a 100644 --- a/percona-suite/percona_status_wait_query_cache_mutex.test +++ b/percona-suite/percona_status_wait_query_cache_mutex.test @@ -1,6 +1,7 @@ --source include/have_query_cache.inc --source include/have_debug.inc -set GLOBAL query_cache_size=1355776; +--source include/have_debug_sync.inc +SET GLOBAL query_cache_size=1355776; --source include/percona_query_cache_with_comments_clear.inc -- disable_warnings @@ -10,28 +11,21 @@ CREATE TABLE t(id INT, number INT); INSERT INTO t VALUES (0,1); INSERT INTO t VALUES (1,2); INSERT INTO t VALUES (2,3); -SELECT number from t where id > 0; ---connect (conn0,localhost,root,,) ---connect (conn1,localhost,root,,) ---connect (conn2,localhost,root,,) ---connection conn0 ---error 0, ER_UNKNOWN_SYSTEM_VARIABLE -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; -SEND SELECT number from t where id > 0; -SLEEP 1.0; +--connect (conn,localhost,root,,) ---connection conn1 ---error 0, ER_UNKNOWN_SYSTEM_VARIABLE -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; +--connection conn +SET SESSION debug="+d,status_waiting_on_query_cache_mutex_sleep"; +SET DEBUG_SYNC='status_waiting_on_query_cache_mutex SIGNAL thread_ready'; SEND SELECT number from t where id > 0; -SLEEP 1.0; ---connection conn2 ---error 0, ER_UNKNOWN_SYSTEM_VARIABLE -SET SESSION debug="+d,status_wait_query_cache_mutex_sleep"; ---replace_column 1 Id 6 Time 9 Rows_sent 10 Rows_examined 11 Rows_read +--connection default +--replace_column 1 ### 3 ### 6 ### 9 ### 10 ### 11 ### SHOW PROCESSLIST; +--replace_column 1 ### +SELECT id, info, state FROM INFORMATION_SCHEMA.PROCESSLIST ORDER BY id; + +--disconnect conn DROP TABLE t; -set GLOBAL query_cache_size=0; +SET GLOBAL query_cache_size=0; diff --git a/percona-suite/query_response_time-replication.inc b/percona-suite/query_response_time-replication.inc new file mode 100644 index 00000000000..9bd811a9a1b --- /dev/null +++ b/percona-suite/query_response_time-replication.inc @@ -0,0 +1,57 @@ +connection master; + +CREATE TABLE t(id INT); + +connection slave; +SET GLOBAL query_exec_time = 0.1; +--source include/restart_slave_sql.inc + +connection slave; + +SET SESSION query_exec_time=0.1; + +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +--eval SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; + +connection master; + +SET SESSION query_exec_time = 0.31; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.32; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.33; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.34; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.35; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.36; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.37; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.38; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.39; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.4; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.1; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.2; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.3; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.5; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 1.4; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 0.5; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.1; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.3; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 2.5; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 3.1; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 4.1; INSERT INTO t VALUES(1); +SET SESSION query_exec_time = 5.1; INSERT INTO t VALUES(1); + +sync_slave_with_master; + +connection slave; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +SHOW QUERY_RESPONSE_TIME; +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; + +SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=default; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=default; + +connection master; +DROP TABLE t; + +sync_slave_with_master; diff --git a/percona-suite/query_response_time-stored.inc b/percona-suite/query_response_time-stored.inc new file mode 100644 index 00000000000..a1fc8912aab --- /dev/null +++ b/percona-suite/query_response_time-stored.inc @@ -0,0 +1,37 @@ +SET SESSION query_exec_time=0.1; + +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base; +FLUSH QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; + +CALL test_f(0.31); +CALL test_f(0.32); +CALL test_f(0.33); +CALL test_f(0.34); +CALL test_f(0.35); +CALL test_f(0.36); +CALL test_f(0.37); +CALL test_f(0.38); +CALL test_f(0.39); +CALL test_f(0.4); +CALL test_f(1.1); +CALL test_f(1.2); +CALL test_f(1.3); +CALL test_f(1.5); +CALL test_f(1.4); +CALL test_f(0.5); +CALL test_f(2.1); +CALL test_f(2.3); +CALL test_f(2.5); +CALL test_f(3.1); +CALL test_f(4.1); +CALL test_f(5.1); + +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; + +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +SHOW QUERY_RESPONSE_TIME; +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; + +SET SESSION query_exec_time=default; diff --git a/percona-suite/query_response_time.inc b/percona-suite/query_response_time.inc new file mode 100644 index 00000000000..734d3f5a262 --- /dev/null +++ b/percona-suite/query_response_time.inc @@ -0,0 +1,43 @@ +SET SESSION query_exec_time=0.1; + +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; +EVAL SET GLOBAL QUERY_RESPONSE_TIME_RANGE_BASE=$base; +FLUSH QUERY_RESPONSE_TIME; +# Following two queries check works of FLUSH and +# respecting of "QUERY_RESPONSE_TIME_STATS" variable (see launchpad bug #855312) +SHOW QUERY_RESPONSE_TIME; +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; +SET GLOBAL QUERY_RESPONSE_TIME_STATS=1; + +SET SESSION query_exec_time=0.31; SELECT 1; +SET SESSION query_exec_time=0.32; SELECT 1; +SET SESSION query_exec_time=0.33; SELECT 1; +SET SESSION query_exec_time=0.34; SELECT 1; +SET SESSION query_exec_time=0.35; SELECT 1; +SET SESSION query_exec_time=0.36; SELECT 1; +SET SESSION query_exec_time=0.37; SELECT 1; +SET SESSION query_exec_time=0.38; SELECT 1; +SET SESSION query_exec_time=0.39; SELECT 1; +SET SESSION query_exec_time=0.4; SELECT 1; +SET SESSION query_exec_time=1.1; SELECT 1; +SET SESSION query_exec_time=1.2; SELECT 1; +SET SESSION query_exec_time=1.3; SELECT 1; +SET SESSION query_exec_time=1.5; SELECT 1; +SET SESSION query_exec_time=1.4; SELECT 1; +SET SESSION query_exec_time=0.5; SELECT 1; +SET SESSION query_exec_time=2.1; SELECT 1; +SET SESSION query_exec_time=2.3; SELECT 1; +SET SESSION query_exec_time=2.5; SELECT 1; +SET SESSION query_exec_time=3.1; SELECT 1; +SET SESSION query_exec_time=4.1; SELECT 1; +SET SESSION query_exec_time=5.1; SELECT 1; + +SET SESSION query_exec_time=0.1; + +SET GLOBAL QUERY_RESPONSE_TIME_STATS=0; + +SHOW GLOBAL VARIABLES where Variable_name like 'QUERY_RESPONSE_TIME_RANGE_BASE'; +SHOW QUERY_RESPONSE_TIME; +SELECT * FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME; + +SET SESSION query_exec_time=default; diff --git a/que/que0que.c b/que/que0que.c index d704e0cd1fc..0d13491f25a 100644 --- a/que/que0que.c +++ b/que/que0que.c @@ -1417,6 +1417,12 @@ que_eval_sql( ut_a(trx->error_state == DB_SUCCESS); + if (trx->fake_changes) { + /* fake_changes should not access to system tables */ + fprintf(stderr, "InnoDB: ERROR: innodb_fake_changes tried to access to system tables.\n"); + return(DB_ERROR); + } + if (reserve_dict_mutex) { mutex_enter(&dict_sys->mutex); } diff --git a/rem/rem0rec.c b/rem/rem0rec.c index 5a96e608ab5..30fc28561fa 100644 --- a/rem/rem0rec.c +++ b/rem/rem0rec.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -408,7 +408,7 @@ rec_init_offsets( do { ulint len; if (UNIV_UNLIKELY(i == n_node_ptr_field)) { - len = offs += 4; + len = offs += REC_NODE_PTR_SIZE; goto resolved; } @@ -640,7 +640,7 @@ rec_get_offsets_reverse( do { ulint len; if (UNIV_UNLIKELY(i == n_node_ptr_field)) { - len = offs += 4; + len = offs += REC_NODE_PTR_SIZE; goto resolved; } @@ -1131,9 +1131,9 @@ rec_convert_dtuple_to_rec_comp( if (UNIV_UNLIKELY(i == n_node_ptr_field)) { ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL); - ut_ad(len == 4); + ut_ad(len == REC_NODE_PTR_SIZE); memcpy(end, dfield_get_data(field), len); - end += 4; + end += REC_NODE_PTR_SIZE; break; } diff --git a/row/row0ins.c b/row/row0ins.c index b4e66a16b5f..da035421ab9 100644 --- a/row/row0ins.c +++ b/row/row0ins.c @@ -118,6 +118,9 @@ ins_node_create_entry_list( node->entry_sys_heap); UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry); + /* We will include all indexes (include those corrupted + secondary indexes) in the entry list. Filteration of + these corrupted index will be done in row_ins() */ index = dict_table_get_next_index(index); } } @@ -1499,6 +1502,11 @@ exit_func: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } + + if (trx->fake_changes) { + err = DB_SUCCESS; + } + return(err); } @@ -2004,7 +2012,7 @@ row_ins_index_entry_low( } btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, - search_mode, + thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : search_mode, &cursor, 0, __FILE__, __LINE__, &mtr); if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) { @@ -2053,7 +2061,6 @@ row_ins_index_entry_low( mtr_start(&mtr); if (err != DB_SUCCESS) { - goto function_exit; } @@ -2065,7 +2072,7 @@ row_ins_index_entry_low( btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, - mode | BTR_INSERT, + thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : (mode | BTR_INSERT), &cursor, 0, __FILE__, __LINE__, &mtr); } @@ -2119,6 +2126,22 @@ function_exit: if (UNIV_LIKELY_NULL(big_rec)) { rec_t* rec; ulint* offsets; + + if (thr_get_trx(thr)->fake_changes) { + /* skip store extern */ + if (modify) { + dtuple_big_rec_free(big_rec); + } else { + dtuple_convert_back_big_rec(index, entry, big_rec); + } + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + return(err); + } + mtr_start(&mtr); btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, @@ -2403,6 +2426,13 @@ row_ins( node->index = dict_table_get_next_index(node->index); node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); + + /* Skip corrupted secondar index and its entry */ + while (node->index && dict_index_is_corrupted(node->index)) { + + node->index = dict_table_get_next_index(node->index); + node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry); + } } ut_ad(node->entry == NULL); diff --git a/row/row0merge.c b/row/row0merge.c index 7d4716cb623..ed5c0abc884 100644 --- a/row/row0merge.c +++ b/row/row0merge.c @@ -56,6 +56,7 @@ Completed by Sunny Bains and Marko Makela #include "log0log.h" #include "ut0sort.h" #include "handler0alter.h" +#include "ha_prototypes.h" /* Ignore posix_fadvise() on those platforms where it does not exist */ #if defined __WIN__ @@ -2563,8 +2564,9 @@ row_merge_is_index_usable( const trx_t* trx, /*!< in: transaction */ const dict_index_t* index) /*!< in: index to check */ { - return(!trx->read_view - || read_view_sees_trx_id(trx->read_view, index->trx_id)); + return(!dict_index_is_corrupted(index) + && (!trx->read_view + || read_view_sees_trx_id(trx->read_view, index->trx_id))); } /*********************************************************************//** @@ -2672,6 +2674,9 @@ row_merge_build_indexes( } } + if (trx->mysql_thd && thd_expand_fast_index_creation(trx->mysql_thd)) + dict_update_statistics(new_table, FALSE, TRUE); + func_exit: row_merge_file_destroy_low(tmpfd); diff --git a/row/row0mysql.c b/row/row0mysql.c index d9107d942f6..7ffccf35371 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -577,6 +577,7 @@ handle_new_error: case DB_DUPLICATE_KEY: case DB_FOREIGN_DUPLICATE_KEY: case DB_TOO_BIG_RECORD: + case DB_UNDO_RECORD_TOO_BIG: case DB_ROW_IS_REFERENCED: case DB_NO_REFERENCED_ROW: case DB_CANNOT_ADD_CONSTRAINT: @@ -1245,6 +1246,7 @@ run_again: prebuilt->table->stat_n_rows--; } + if (!(trx->fake_changes)) row_update_statistics_if_needed(prebuilt->table); trx->op_info = ""; @@ -1504,6 +1506,7 @@ run_again: that changes indexed columns, UPDATEs that change only non-indexed columns would not affect statistics. */ if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { + if (!(trx->fake_changes)) row_update_statistics_if_needed(prebuilt->table); } @@ -1721,6 +1724,7 @@ run_again: srv_n_rows_updated++; } + if (!(trx->fake_changes)) row_update_statistics_if_needed(table); return(err); @@ -2026,41 +2030,13 @@ row_create_index_for_mysql( trx_start_if_not_started(trx); - /* Check that the same column does not appear twice in the index. - Starting from 4.0.14, InnoDB should be able to cope with that, but - safer not to allow them. */ - - for (i = 0; i < dict_index_get_n_fields(index); i++) { - ulint j; - - for (j = 0; j < i; j++) { - if (0 == ut_strcmp( - dict_index_get_nth_field(index, j)->name, - dict_index_get_nth_field(index, i)->name)) { - ut_print_timestamp(stderr); - - fputs(" InnoDB: Error: column ", stderr); - ut_print_name(stderr, trx, FALSE, - dict_index_get_nth_field( - index, i)->name); - fputs(" appears twice in ", stderr); - dict_index_name_print(stderr, trx, index); - fputs("\n" - "InnoDB: This is not allowed" - " in InnoDB.\n", stderr); - - err = DB_COL_APPEARS_TWICE_IN_INDEX; - - goto error_handling; - } - } - - /* Check also that prefix_len and actual length - is less than that from DICT_MAX_FIELD_LEN_BY_FORMAT() */ + for (i = 0; i < index->n_def; i++) { + /* Check that prefix_len and actual length + < DICT_MAX_INDEX_COL_LEN */ len = dict_index_get_nth_field(index, i)->prefix_len; - if (field_lengths) { + if (field_lengths && field_lengths[i]) { len = ut_max(len, field_lengths[i]); } @@ -2068,6 +2044,7 @@ row_create_index_for_mysql( if (len > (ulint) DICT_MAX_FIELD_LEN_BY_FORMAT(table)) { err = DB_TOO_BIG_INDEX_COL; + dict_mem_index_free(index); goto error_handling; } } @@ -2610,10 +2587,29 @@ row_discard_tablespace_for_mysql( err = DB_ERROR; } else { + dict_index_t* index; + /* Set the flag which tells that now it is legal to IMPORT a tablespace for this table */ table->tablespace_discarded = TRUE; table->ibd_file_missing = TRUE; + + /* check adaptive hash entries */ + index = dict_table_get_first_index(table); + while (index) { + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id); + if (ref_count) { + fprintf(stderr, "InnoDB: Warning:" + " hash index ref_count (%lu) is not zero" + " after fil_discard_tablespace().\n" + "index: \"%s\"" + " table: \"%s\"\n", + ref_count, + index->name, + table->name); + } + index = dict_table_get_next_index(index); + } } } @@ -2962,6 +2958,19 @@ row_truncate_table_for_mysql( table->space = space; index = dict_table_get_first_index(table); do { + ulint ref_count = btr_search_info_get_ref_count(index->search_info, index->id); + /* check adaptive hash entries */ + if (ref_count) { + fprintf(stderr, "InnoDB: Warning:" + " hash index ref_count (%lu) is not zero" + " after fil_discard_tablespace().\n" + "index: \"%s\"" + " table: \"%s\"\n", + ref_count, + index->name, + table->name); + } + index->space = space; index = dict_table_get_next_index(index); } while (index); @@ -3211,7 +3220,8 @@ row_drop_table_for_mysql( ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX)); #endif /* UNIV_SYNC_DEBUG */ - table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT); + table = dict_table_get_low_ignore_err( + name, DICT_ERR_IGNORE_INDEX_ROOT | DICT_ERR_IGNORE_CORRUPT); if (!table) { err = DB_TABLE_NOT_FOUND; @@ -3358,6 +3368,19 @@ check_next_foreign: "index_id CHAR;\n" "foreign_id CHAR;\n" "found INT;\n" + + "DECLARE CURSOR cur_fk IS\n" + "SELECT ID FROM SYS_FOREIGN\n" + "WHERE FOR_NAME = :table_name\n" + "AND TO_BINARY(FOR_NAME)\n" + " = TO_BINARY(:table_name)\n" + "LOCK IN SHARE MODE;\n" + + "DECLARE CURSOR cur_idx IS\n" + "SELECT ID FROM SYS_INDEXES\n" + "WHERE TABLE_ID = table_id\n" + "LOCK IN SHARE MODE;\n" + "BEGIN\n" "SELECT ID INTO table_id\n" "FROM SYS_TABLES\n" @@ -3380,13 +3403,9 @@ check_next_foreign: "IF (:table_name = 'SYS_FOREIGN_COLS') THEN\n" " found := 0;\n" "END IF;\n" + "OPEN cur_fk;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO foreign_id\n" - " FROM SYS_FOREIGN\n" - " WHERE FOR_NAME = :table_name\n" - " AND TO_BINARY(FOR_NAME)\n" - " = TO_BINARY(:table_name)\n" - " LOCK IN SHARE MODE;\n" + " FETCH cur_fk INTO foreign_id;\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -3396,12 +3415,11 @@ check_next_foreign: " WHERE ID = foreign_id;\n" " END IF;\n" "END LOOP;\n" + "CLOSE cur_fk;\n" "found := 1;\n" + "OPEN cur_idx;\n" "WHILE found = 1 LOOP\n" - " SELECT ID INTO index_id\n" - " FROM SYS_INDEXES\n" - " WHERE TABLE_ID = table_id\n" - " LOCK IN SHARE MODE;\n" + " FETCH cur_idx INTO index_id;\n" " IF (SQL % NOTFOUND) THEN\n" " found := 0;\n" " ELSE\n" @@ -3414,6 +3432,7 @@ check_next_foreign: " AND TABLE_ID = table_id;\n" " END IF;\n" "END LOOP;\n" + "CLOSE cur_idx;\n" "DELETE FROM SYS_COLUMNS\n" "WHERE TABLE_ID = table_id;\n" "DELETE FROM SYS_TABLES\n" diff --git a/row/row0purge.c b/row/row0purge.c index 83e7c9e4857..efcfdc3bac5 100644 --- a/row/row0purge.c +++ b/row/row0purge.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -469,6 +469,13 @@ row_purge_del_mark( heap = mem_heap_create(1024); while (node->index != NULL) { + /* skip corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; /* Build the index entry */ @@ -508,7 +515,8 @@ row_purge_upd_exist_or_extern_func( ut_ad(node); - if (node->rec_type == TRX_UNDO_UPD_DEL_REC) { + if (node->rec_type == TRX_UNDO_UPD_DEL_REC + || (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { goto skip_secondaries; } @@ -516,6 +524,12 @@ row_purge_upd_exist_or_extern_func( heap = mem_heap_create(1024); while (node->index != NULL) { + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; if (row_upd_changes_ord_field_binary(node->index, node->update, @@ -632,14 +646,14 @@ row_purge_parse_undo_rec( roll_ptr_t roll_ptr; ulint info_bits; ulint type; - ulint cmpl_info; ut_ad(node && thr); trx = thr_get_trx(thr); - ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, - updated_extern, &undo_no, &table_id); + ptr = trx_undo_rec_get_pars( + node->undo_rec, &type, &node->cmpl_info, + updated_extern, &undo_no, &table_id); node->rec_type = type; if (type == TRX_UNDO_UPD_DEL_REC && !(*updated_extern)) { @@ -652,7 +666,8 @@ row_purge_parse_undo_rec( node->table = NULL; if (type == TRX_UNDO_UPD_EXIST_REC - && cmpl_info & UPD_NODE_NO_ORD_CHANGE && !(*updated_extern)) { + && node->cmpl_info & UPD_NODE_NO_ORD_CHANGE + && !(*updated_extern)) { /* Purge requires no changes to indexes: we may return */ @@ -702,7 +717,7 @@ err_exit: /* Read to the partial row the fields that occur in indexes */ - if (!(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { + if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ptr = trx_undo_rec_get_partial_row( ptr, clust_index, &node->row, type == TRX_UNDO_UPD_DEL_REC, diff --git a/row/row0row.c b/row/row0row.c index 2882af00f30..0462f280858 100644 --- a/row/row0row.c +++ b/row/row0row.c @@ -101,12 +101,27 @@ row_build_index_entry( dfield_copy(dfield, dfield2); - if (dfield_is_null(dfield) || ind_field->prefix_len == 0) { + if (dfield_is_null(dfield)) { continue; } - /* If a column prefix index, take only the prefix. - Prefix-indexed columns may be externally stored. */ + if (ind_field->prefix_len == 0 + && (!dfield_is_ext(dfield) + || dict_index_is_clust(index))) { + /* The dfield_copy() above suffices for + columns that are stored in-page, or for + clustered index record columns that are not + part of a column prefix in the PRIMARY KEY. */ + continue; + } + + /* If the column is stored externally (off-page) in + the clustered index, it must be an ordering field in + the secondary index. In the Antelope format, only + prefix-indexed columns may be stored off-page in the + clustered index record. In the Barracuda format, also + fully indexed long CHAR or VARCHAR columns may be + stored off-page. */ ut_ad(col->ord_part); if (UNIV_LIKELY_NULL(ext)) { @@ -119,15 +134,41 @@ row_build_index_entry( } dfield_set_data(dfield, buf, len); } + + if (ind_field->prefix_len == 0) { + /* In the Barracuda format + (ROW_FORMAT=DYNAMIC or + ROW_FORMAT=COMPRESSED), we can have a + secondary index on an entire column + that is stored off-page in the + clustered index. As this is not a + prefix index (prefix_len == 0), + include the entire off-page column in + the secondary index record. */ + continue; + } } else if (dfield_is_ext(dfield)) { + /* This table is either in Antelope format + (ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT) + or a purge record where the ordered part of + the field is not external. + In Antelope, the maximum column prefix + index length is 767 bytes, and the clustered + index record contains a 768-byte prefix of + each off-page column. */ ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); len -= BTR_EXTERN_FIELD_REF_SIZE; + dfield_set_len(dfield, len); } - len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, - ind_field->prefix_len, len, dfield_get_data(dfield)); - dfield_set_len(dfield, len); + /* If a column prefix index, take only the prefix. */ + if (ind_field->prefix_len) { + len = dtype_get_at_most_n_mbchars( + col->prtype, col->mbminmaxlen, + ind_field->prefix_len, len, + dfield_get_data(dfield)); + dfield_set_len(dfield, len); + } } ut_ad(dtuple_check_typed(entry)); diff --git a/row/row0sel.c b/row/row0sel.c index 4720bdb0f1e..7079e96bb12 100644 --- a/row/row0sel.c +++ b/row/row0sel.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved. +Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -99,14 +99,22 @@ row_sel_sec_rec_is_for_blob( ulint clust_len, /*!< in: length of clust_field */ const byte* sec_field, /*!< in: column in secondary index */ ulint sec_len, /*!< in: length of sec_field */ + ulint prefix_len, /*!< in: index column prefix length + in bytes */ dict_table_t* table) /*!< in: table */ { ulint len; byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN]; ulint zip_size = dict_table_flags_to_zip_size(table->flags); - ulint max_prefix_len = DICT_MAX_FIELD_LEN_BY_FORMAT(table); + /* This function should never be invoked on an Antelope format + table, because they should always contain enough prefix in the + clustered index record. */ + ut_ad(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP); ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE); + ut_ad(prefix_len >= sec_len); + ut_ad(prefix_len > 0); + ut_a(prefix_len <= sizeof buf); if (UNIV_UNLIKELY (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE, @@ -118,7 +126,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = btr_copy_externally_stored_field_prefix(buf, max_prefix_len, + len = btr_copy_externally_stored_field_prefix(buf, prefix_len, zip_size, clust_field, clust_len); @@ -132,7 +140,7 @@ row_sel_sec_rec_is_for_blob( } len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, - sec_len, len, (const char*) buf); + prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); } @@ -224,6 +232,7 @@ row_sel_sec_rec_is_for_clust_rec( col->mbminmaxlen, clust_field, clust_len, sec_field, sec_len, + ifield->prefix_len, clust_index->table)) { goto inequal; } @@ -493,7 +502,7 @@ sel_col_prefetch_buf_alloc( sel_buf = column->prefetch_buf + i; sel_buf->data = NULL; - + sel_buf->len = 0; sel_buf->val_buf_size = 0; } } @@ -518,6 +527,8 @@ sel_col_prefetch_buf_free( mem_free(sel_buf->data); } } + + mem_free(prefetch_buf); } /*********************************************************************//** @@ -2541,6 +2552,8 @@ row_sel_field_store_in_mysql_format( ut_ad(len != UNIV_SQL_NULL); UNIV_MEM_ASSERT_RW(data, len); + UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len); + UNIV_MEM_INVALID(dest, templ->mysql_col_len); switch (templ->type) { const byte* field_end; @@ -2579,14 +2592,16 @@ row_sel_field_store_in_mysql_format( dest = row_mysql_store_true_var_len( dest, len, templ->mysql_length_bytes); + /* Copy the actual data. Leave the rest of the + buffer uninitialized. */ + memcpy(dest, data, len); + break; } /* Copy the actual data */ ut_memcpy(dest, data, len); - /* Pad with trailing spaces. We pad with spaces also the - unused end of a >= 5.0.3 true VARCHAR column, just in case - MySQL expects its contents to be deterministic. */ + /* Pad with trailing spaces. */ pad = dest + len; @@ -3113,6 +3128,39 @@ sel_restore_position_for_mysql( } /********************************************************************//** +Copies a cached field for MySQL from the fetch cache. */ +static +void +row_sel_copy_cached_field_for_mysql( +/*================================*/ + byte* buf, /*!< in/out: row buffer */ + const byte* cache, /*!< in: cached row */ + const mysql_row_templ_t*templ) /*!< in: column template */ +{ + ulint len; + + buf += templ->mysql_col_offset; + cache += templ->mysql_col_offset; + + UNIV_MEM_ASSERT_W(buf, templ->mysql_col_len); + + if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR + && templ->type != DATA_INT) { + /* Check for != DATA_INT to make sure we do + not treat MySQL ENUM or SET as a true VARCHAR! + Find the actual length of the true VARCHAR field. */ + row_mysql_read_true_varchar( + &len, cache, templ->mysql_length_bytes); + len += templ->mysql_length_bytes; + UNIV_MEM_INVALID(buf, templ->mysql_col_len); + } else { + len = templ->mysql_col_len; + } + + ut_memcpy(buf, cache, len); +} + +/********************************************************************//** Pops a cached row for MySQL from the fetch cache. */ UNIV_INLINE void @@ -3124,26 +3172,22 @@ row_sel_pop_cached_row_for_mysql( { ulint i; const mysql_row_templ_t*templ; - byte* cached_rec; + const byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); + UNIV_MEM_ASSERT_W(buf, prebuilt->mysql_row_len); + + cached_rec = prebuilt->fetch_cache[prebuilt->fetch_cache_first]; + if (UNIV_UNLIKELY(prebuilt->keep_other_fields_on_keyread)) { /* Copy cache record field by field, don't touch fields that are not covered by current key */ - cached_rec = prebuilt->fetch_cache[ - prebuilt->fetch_cache_first]; for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; -#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ - UNIV_MEM_ASSERT_RW(cached_rec - + templ->mysql_col_offset, - templ->mysql_col_len); -#endif - ut_memcpy(buf + templ->mysql_col_offset, - cached_rec + templ->mysql_col_offset, - templ->mysql_col_len); + row_sel_copy_cached_field_for_mysql( + buf, cached_rec, templ); /* Copy NULL bit of the current field from cached_rec to buf */ if (templ->mysql_null_bit_mask) { @@ -3153,17 +3197,24 @@ row_sel_pop_cached_row_for_mysql( & (byte)templ->mysql_null_bit_mask; } } + } else if (prebuilt->mysql_prefix_len > 63) { + /* The record is long. Copy it field by field, in case + there are some long VARCHAR column of which only a + small length is being used. */ + UNIV_MEM_INVALID(buf, prebuilt->mysql_prefix_len); + + /* First copy the NULL bits. */ + ut_memcpy(buf, cached_rec, prebuilt->null_bitmap_len); + /* Then copy the requested fields. */ + + for (i = 0; i < prebuilt->n_template; i++) { + row_sel_copy_cached_field_for_mysql( + buf, cached_rec, prebuilt->mysql_template + i); + } + } else { + ut_memcpy(buf, cached_rec, prebuilt->mysql_prefix_len); } - else { -#if 0 /* Some of the cached_rec may legitimately be uninitialized. */ - UNIV_MEM_ASSERT_RW(prebuilt->fetch_cache - [prebuilt->fetch_cache_first], - prebuilt->mysql_prefix_len); -#endif - ut_memcpy(buf, - prebuilt->fetch_cache[prebuilt->fetch_cache_first], - prebuilt->mysql_prefix_len); - } + prebuilt->n_fetch_cached--; prebuilt->fetch_cache_first++; @@ -3404,6 +3455,13 @@ row_search_for_mysql( return(DB_MISSING_HISTORY); } + if (dict_index_is_corrupted(index)) { +#ifdef UNIV_SYNC_DEBUG + ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); +#endif /* UNIV_SYNC_DEBUG */ + return(DB_CORRUPTION); + } + if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) { fprintf(stderr, "InnoDB: Error: trying to free a corrupt\n" diff --git a/row/row0uins.c b/row/row0uins.c index d25afed3840..4fa97c9355d 100644 --- a/row/row0uins.c +++ b/row/row0uins.c @@ -328,6 +328,8 @@ row_undo_ins( node->index = dict_table_get_next_index( dict_table_get_first_index(node->table)); + dict_table_skip_corrupt_index(node->index); + while (node->index != NULL) { dtuple_t* entry; ulint err; @@ -355,7 +357,7 @@ row_undo_ins( } } - node->index = dict_table_get_next_index(node->index); + dict_table_next_uncorrupted_index(node->index); } log_free_check(); diff --git a/row/row0umod.c b/row/row0umod.c index 2188fdeff49..b86ce9eeabd 100644 --- a/row/row0umod.c +++ b/row/row0umod.c @@ -573,6 +573,14 @@ row_undo_mod_upd_del_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; entry = row_build_index_entry(node->row, node->ext, @@ -626,6 +634,13 @@ row_undo_mod_del_mark_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; entry = row_build_index_entry(node->row, node->ext, @@ -677,6 +692,13 @@ row_undo_mod_upd_exist_sec( heap = mem_heap_create(1024); while (node->index != NULL) { + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + index = node->index; if (row_upd_changes_ord_field_binary(node->index, node->update, @@ -859,6 +881,9 @@ row_undo_mod( node->index = dict_table_get_next_index( dict_table_get_first_index(node->table)); + /* Skip all corrupted secondary index */ + dict_table_skip_corrupt_index(node->index); + if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) { err = row_undo_mod_upd_exist_sec(node, thr); diff --git a/row/row0upd.c b/row/row0upd.c index 01fb44f42de..45c19b0ead0 100644 --- a/row/row0upd.c +++ b/row/row0upd.c @@ -1603,7 +1603,8 @@ row_upd_sec_index_entry( mode |= BTR_DELETE_MARK; } - search_result = row_search_index_entry(index, entry, mode, + search_result = row_search_index_entry(index, entry, + trx->fake_changes ? BTR_SEARCH_LEAF : mode, &pcur, &mtr); btr_cur = btr_pcur_get_btr_cur(&pcur); @@ -1850,9 +1851,11 @@ row_upd_clust_rec_by_insert( the previous invocation of this function. Mark the off-page columns in the entry inherited. */ + if (!(trx->fake_changes)) { change_ownership = row_upd_clust_rec_by_insert_inherit( NULL, NULL, entry, node->update); ut_a(change_ownership); + } /* fall through */ case UPD_NODE_INSERT_CLUSTERED: /* A lock wait occurred in row_ins_index_entry() in @@ -1882,7 +1885,7 @@ err_exit: delete-marked old record, mark them disowned by the old record and owned by the new entry. */ - if (rec_offs_any_extern(offsets)) { + if (rec_offs_any_extern(offsets) && !(trx->fake_changes)) { change_ownership = row_upd_clust_rec_by_insert_inherit( rec, offsets, entry, node->update); @@ -2012,7 +2015,8 @@ row_upd_clust_rec( the same transaction do not modify the record in the meantime. Therefore we can assert that the restoration of the cursor succeeds. */ - ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr)); + ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE, + pcur, mtr)); ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur), dict_table_is_comp(index->table))); @@ -2022,7 +2026,8 @@ row_upd_clust_rec( node->cmpl_info, thr, mtr); mtr_commit(mtr); - if (err == DB_SUCCESS && big_rec) { + /* skip store extern for fake_changes */ + if (err == DB_SUCCESS && big_rec && !(thr_get_trx(thr)->fake_changes)) { ulint offsets_[REC_OFFS_NORMAL_SIZE]; rec_t* rec; rec_offs_init(offsets_); @@ -2146,7 +2151,8 @@ row_upd_clust_step( ut_a(pcur->rel_pos == BTR_PCUR_ON); - success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); + success = btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_LEAF, + pcur, mtr); if (!success) { err = DB_RECORD_NOT_FOUND; @@ -2323,6 +2329,13 @@ row_upd( while (node->index != NULL) { + /* Skip corrupted index */ + dict_table_skip_corrupt_index(node->index); + + if (!node->index) { + break; + } + log_free_check(); err = row_upd_sec_step(node, thr); diff --git a/srv/srv0srv.c b/srv/srv0srv.c index e2d092540ff..1efda4ef18b 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -87,6 +87,12 @@ Created 10/8/1995 Heikki Tuuri #include "mysql/plugin.h" #include "mysql/service_thd_wait.h" +/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */ +ibool innobase_thd_is_idle(const void* thd); +ib_int64_t innobase_thd_get_start_time(const void* thd); +void innobase_thd_kill(ulong thd_id); +ulong innobase_thd_get_thread_id(const void* thd); + /* prototypes for new functions added to ha_innodb.cc */ ibool innobase_get_slow_log(); @@ -97,6 +103,9 @@ UNIV_INTERN ulint srv_activity_count = 0; /* The following is the maximum allowed duration of a lock wait. */ UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600; +/**/ +UNIV_INTERN lint srv_kill_idle_transaction = 0; + /* How much data manipulation language (DML) statements need to be delayed, in microseconds, in order to reduce the lagging of the purge thread. */ UNIV_INTERN ulint srv_dml_needed_delay = 0; @@ -234,6 +243,9 @@ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX; UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX; UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX; +/* Switch to enable random read ahead. */ +UNIV_INTERN my_bool srv_random_read_ahead = FALSE; + /* The universal page size of the database */ UNIV_INTERN ulint srv_page_size_shift = 0; UNIV_INTERN ulint srv_page_size = 0; @@ -342,6 +354,9 @@ UNIV_INTERN ulint srv_buf_pool_reads = 0; /** Time in seconds between automatic buffer pool dumps */ UNIV_INTERN uint srv_auto_lru_dump = 0; +/** Whether startup should be blocked until buffer pool is fully restored */ +UNIV_INTERN ibool srv_blocking_lru_restore; + /* structure to pass status variables to MySQL */ UNIV_INTERN export_struc export_vars; @@ -2316,6 +2331,8 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed; export_vars.innodb_buffer_pool_pages_LRU_flushed = buf_lru_flush_page_count; export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads; + export_vars.innodb_buffer_pool_read_ahead_rnd + = stat.n_ra_pages_read_rnd; export_vars.innodb_buffer_pool_read_ahead = stat.n_ra_pages_read; export_vars.innodb_buffer_pool_read_ahead_evicted @@ -2826,6 +2843,36 @@ loop: old_sema = sema; } + if (srv_kill_idle_transaction && trx_sys) { + trx_t* trx; + time_t now; +rescan_idle: + now = time(NULL); + mutex_enter(&kernel_mutex); + trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); + while (trx) { + if (trx->conc_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); + ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd); + + if (trx->last_stmt_start != start_time) { + trx->idle_start = now; + trx->last_stmt_start = start_time; + } else if (difftime(now, trx->idle_start) + > srv_kill_idle_transaction) { + /* kill the session */ + mutex_exit(&kernel_mutex); + innobase_thd_kill(thd_id); + goto rescan_idle; + } + } + trx = UT_LIST_GET_NEXT(mysql_trx_list, trx); + } + mutex_exit(&kernel_mutex); + } + /* Flush stderr so that a database user gets the output to possible MySQL error file */ @@ -2871,7 +2918,9 @@ srv_LRU_dump_restore_thread( os_thread_pf(os_thread_get_curr_id())); #endif - if (srv_auto_lru_dump) + /* If srv_blocking_lru_restore is TRUE, restore will be done + synchronously on startup. */ + if (srv_auto_lru_dump && !srv_blocking_lru_restore) buf_LRU_file_restore(); last_dump_time = time(NULL); @@ -3039,7 +3088,7 @@ srv_master_do_purge(void) ut_ad(!mutex_own(&kernel_mutex)); - ut_a(srv_n_purge_threads == 0); + ut_a(srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)); do { /* Check for shutdown and change in purge config. */ @@ -3536,7 +3585,7 @@ retry_flush_batch: /* Flush logs if needed */ srv_sync_log_buffer_in_background(); - if (srv_n_purge_threads == 0) { + if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) { srv_main_thread_op_info = "master purging"; srv_master_do_purge(); @@ -3614,7 +3663,7 @@ background_loop: } } - if (srv_n_purge_threads == 0) { + if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) { srv_main_thread_op_info = "master purging"; srv_master_do_purge(); diff --git a/srv/srv0start.c b/srv/srv0start.c index 71364cb5ded..793b70f50ce 100644 --- a/srv/srv0start.c +++ b/srv/srv0start.c @@ -87,6 +87,7 @@ Created 2/16/1996 Heikki Tuuri # include "btr0pcur.h" # include "os0sync.h" /* for INNODB_RW_LOCKS_USE_ATOMICS */ # include "zlib.h" /* for ZLIB_VERSION */ +# include "buf0lru.h" /* for buf_LRU_file_restore() */ /** Log sequence number immediately after startup */ UNIV_INTERN ib_uint64_t srv_start_lsn; @@ -1993,6 +1994,11 @@ innobase_start_or_create_for_mysql(void) os_thread_create(&srv_LRU_dump_restore_thread, NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS); + /* If srv_blocking_lru_restore is TRUE, load buffer pool contents + synchronously */ + if (srv_auto_lru_dump && srv_blocking_lru_restore) + buf_LRU_file_restore(); + srv_is_being_started = FALSE; err = dict_create_or_check_foreign_constraint_tables(); diff --git a/sync/sync0sync.c b/sync/sync0sync.c index 4b35d6db177..b38e2183b0f 100644 --- a/sync/sync0sync.c +++ b/sync/sync0sync.c @@ -1218,7 +1218,6 @@ sync_thread_add_level( case SYNC_WORK_QUEUE: case SYNC_LOG: case SYNC_LOG_FLUSH_ORDER: - case SYNC_THR_LOCAL: case SYNC_ANY_LATCH: case SYNC_OUTER_ANY_LATCH: case SYNC_FILE_FORMAT_TAG: @@ -1236,6 +1235,7 @@ sync_thread_add_level( case SYNC_DICT_HEADER: case SYNC_TRX_I_S_RWLOCK: case SYNC_TRX_I_S_LAST_READ: + case SYNC_IBUF_MUTEX: if (!sync_thread_levels_g(array, level, TRUE)) { fprintf(stderr, "InnoDB: sync_thread_levels_g(array, %lu)" @@ -1328,22 +1328,33 @@ sync_thread_add_level( || sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE)); break; case SYNC_TREE_NODE_NEW: - ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE) - || sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); + ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)); break; case SYNC_INDEX_TREE: - if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) - && sync_thread_levels_contain(array, SYNC_FSP)) { - ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, - TRUE)); + ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE)); + break; + case SYNC_IBUF_TREE_NODE: + ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE) + || sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1, + TRUE)); + break; + case SYNC_IBUF_TREE_NODE_NEW: + /* ibuf_add_free_page() allocates new pages for the + change buffer while only holding the tablespace + x-latch. These pre-allocated new pages may only be + taken in use while holding ibuf_mutex, in + btr_page_alloc_for_ibuf(). */ + ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX) + || sync_thread_levels_contain(array, SYNC_FSP)); + break; + case SYNC_IBUF_INDEX_TREE: + if (sync_thread_levels_contain(array, SYNC_FSP)) { + ut_a(sync_thread_levels_g(array, level - 1, TRUE)); } else { - ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, - TRUE)); + ut_a(sync_thread_levels_g( + array, SYNC_IBUF_TREE_NODE - 1, TRUE)); } break; - case SYNC_IBUF_MUTEX: - ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE)); - break; case SYNC_IBUF_PESS_INSERT_MUTEX: ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE)); ut_a(!sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)); diff --git a/trx/trx0rec.c b/trx/trx0rec.c index 84687c7195b..104b80f5d96 100644 --- a/trx/trx0rec.c +++ b/trx/trx0rec.c @@ -1131,13 +1131,14 @@ trx_undo_rec_get_partial_row( #endif /* !UNIV_HOTBACKUP */ /***********************************************************************//** -Erases the unused undo log page end. */ -static -void +Erases the unused undo log page end. +@return TRUE if the page contained something, FALSE if it was empty */ +static __attribute__((nonnull)) +ibool trx_undo_erase_page_end( /*====================*/ - page_t* undo_page, /*!< in: undo page whose end to erase */ - mtr_t* mtr) /*!< in: mtr */ + page_t* undo_page, /*!< in/out: undo page whose end to erase */ + mtr_t* mtr) /*!< in/out: mini-transaction */ { ulint first_free; @@ -1147,6 +1148,7 @@ trx_undo_erase_page_end( (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END) - first_free); mlog_write_initial_log_record(undo_page, MLOG_UNDO_ERASE_END, mtr); + return(first_free != TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); } /***********************************************************//** @@ -1214,6 +1216,9 @@ trx_undo_report_row_operation( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; +#ifdef UNIV_DEBUG + int loop_count = 0; +#endif /* UNIV_DEBUG */ rec_offs_init(offsets_); ut_a(dict_index_is_clust(index)); @@ -1276,7 +1281,7 @@ trx_undo_report_row_operation( mtr_start(&mtr); - for (;;) { + do { buf_block_t* undo_block; page_t* undo_page; ulint offset; @@ -1305,7 +1310,31 @@ trx_undo_report_row_operation( version the replicate page constructed using the log records stays identical to the original page */ - trx_undo_erase_page_end(undo_page, &mtr); + if (!trx_undo_erase_page_end(undo_page, &mtr)) { + /* The record did not fit on an empty + undo page. Discard the freshly allocated + page and return an error. */ + + /* When we remove a page from an undo + log, this is analogous to a + pessimistic insert in a B-tree, and we + must reserve the counterpart of the + tree latch, which is the rseg + mutex. We must commit the mini-transaction + first, because it may be holding lower-level + latches, such as SYNC_FSP and SYNC_FSP_PAGE. */ + + mtr_commit(&mtr); + mtr_start(&mtr); + + mutex_enter(&rseg->mutex); + trx_undo_free_last_page(trx, undo, &mtr); + mutex_exit(&rseg->mutex); + + err = DB_UNDO_RECORD_TOO_BIG; + goto err_exit; + } + mtr_commit(&mtr); } else { /* Success */ @@ -1325,16 +1354,15 @@ trx_undo_report_row_operation( *roll_ptr = trx_undo_build_roll_ptr( op_type == TRX_UNDO_INSERT_OP, rseg->id, page_no, offset); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - return(DB_SUCCESS); + err = DB_SUCCESS; + goto func_exit; } ut_ad(page_no == undo->last_page_no); /* We have to extend the undo log by one page */ + ut_ad(++loop_count < 2); mtr_start(&mtr); /* When we add a page to an undo log, this is analogous to @@ -1346,18 +1374,19 @@ trx_undo_report_row_operation( page_no = trx_undo_add_page(trx, undo, &mtr); mutex_exit(&(rseg->mutex)); + } while (UNIV_LIKELY(page_no != FIL_NULL)); - if (UNIV_UNLIKELY(page_no == FIL_NULL)) { - /* Did not succeed: out of space */ + /* Did not succeed: out of space */ + err = DB_OUT_OF_FILE_SPACE; - mutex_exit(&(trx->undo_mutex)); - mtr_commit(&mtr); - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - return(DB_OUT_OF_FILE_SPACE); - } +err_exit: + mutex_exit(&trx->undo_mutex); + mtr_commit(&mtr); +func_exit: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); } + return(err); } /*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/ diff --git a/trx/trx0trx.c b/trx/trx0trx.c index 2145261c487..73c4e5afb80 100644 --- a/trx/trx0trx.c +++ b/trx/trx0trx.c @@ -121,6 +121,8 @@ trx_create( trx->support_xa = TRUE; + trx->fake_changes = FALSE; + trx->check_foreigns = TRUE; trx->check_unique_secondary = TRUE; @@ -143,6 +145,9 @@ trx_create( trx->mysql_relay_log_file_name = ""; trx->mysql_relay_log_pos = 0; + trx->idle_start = 0; + trx->last_stmt_start = 0; + mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO); trx->rseg = NULL; diff --git a/trx/trx0undo.c b/trx/trx0undo.c index 4cb4b7b79c5..dae0637f72c 100644 --- a/trx/trx0undo.c +++ b/trx/trx0undo.c @@ -1004,29 +1004,28 @@ trx_undo_free_page( } /********************************************************************//** -Frees an undo log page when there is also the memory object for the undo -log. */ -static +Frees the last undo log page. +The caller must hold the rollback segment mutex. */ +UNIV_INTERN void -trx_undo_free_page_in_rollback( -/*===========================*/ - trx_t* trx __attribute__((unused)), /*!< in: transaction */ - trx_undo_t* undo, /*!< in: undo log memory copy */ - ulint page_no,/*!< in: page number to free: must not be the - header page */ - mtr_t* mtr) /*!< in: mtr which does not have a latch to any - undo log page; the caller must have reserved - the rollback segment mutex */ +trx_undo_free_last_page_func( +/*==========================*/ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction */ +#endif /* UNIV_DEBUG */ + trx_undo_t* undo, /*!< in/out: undo log memory copy */ + mtr_t* mtr) /*!< in/out: mini-transaction which does not + have a latch to any undo log page or which + has allocated the undo log page */ { - ulint last_page_no; - - ut_ad(undo->hdr_page_no != page_no); - ut_ad(mutex_own(&(trx->undo_mutex))); + ut_ad(mutex_own(&trx->undo_mutex)); + ut_ad(undo->hdr_page_no != undo->last_page_no); + ut_ad(undo->size > 0); - last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space, - undo->hdr_page_no, page_no, mtr); + undo->last_page_no = trx_undo_free_page( + undo->rseg, FALSE, undo->space, + undo->hdr_page_no, undo->last_page_no, mtr); - undo->last_page_no = last_page_no; undo->size--; } @@ -1062,9 +1061,11 @@ Truncates an undo log from the end. This function is used during a rollback to free space from an undo log. */ UNIV_INTERN void -trx_undo_truncate_end( -/*==================*/ - trx_t* trx, /*!< in: transaction whose undo log it is */ +trx_undo_truncate_end_func( +/*=======================*/ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction whose undo log it is */ +#endif /* UNIV_DEBUG */ trx_undo_t* undo, /*!< in: undo log */ undo_no_t limit) /*!< in: all undo records with undo number >= this value should be truncated */ @@ -1090,18 +1091,7 @@ trx_undo_truncate_end( rec = trx_undo_page_get_last_rec(undo_page, undo->hdr_page_no, undo->hdr_offset); - for (;;) { - if (rec == NULL) { - if (last_page_no == undo->hdr_page_no) { - - goto function_exit; - } - - trx_undo_free_page_in_rollback( - trx, undo, last_page_no, &mtr); - break; - } - + while (rec) { if (trx_undo_rec_get_undo_no(rec) >= limit) { /* Truncate at least this record off, maybe more */ @@ -1115,6 +1105,14 @@ trx_undo_truncate_end( undo->hdr_offset); } + if (last_page_no == undo->hdr_page_no) { + + goto function_exit; + } + + ut_ad(last_page_no == undo->last_page_no); + trx_undo_free_last_page(trx, undo, &mtr); + mtr_commit(&mtr); } diff --git a/ut/ut0mem.c b/ut/ut0mem.c index 53f15029e1b..303fdd6dd44 100644 --- a/ut/ut0mem.c +++ b/ut/ut0mem.c @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -483,53 +483,6 @@ ut_strlcpy_rev( return(src_size); } -/**********************************************************************//** -Make a quoted copy of a NUL-terminated string. Leading and trailing -quotes will not be included; only embedded quotes will be escaped. -See also ut_strlenq() and ut_memcpyq(). -@return pointer to end of dest */ -UNIV_INTERN -char* -ut_strcpyq( -/*=======*/ - char* dest, /*!< in: output buffer */ - char q, /*!< in: the quote character */ - const char* src) /*!< in: null-terminated string */ -{ - while (*src) { - if ((*dest++ = *src++) == q) { - *dest++ = q; - } - } - - return(dest); -} - -/**********************************************************************//** -Make a quoted copy of a fixed-length string. Leading and trailing -quotes will not be included; only embedded quotes will be escaped. -See also ut_strlenq() and ut_strcpyq(). -@return pointer to end of dest */ -UNIV_INTERN -char* -ut_memcpyq( -/*=======*/ - char* dest, /*!< in: output buffer */ - char q, /*!< in: the quote character */ - const char* src, /*!< in: string to be quoted */ - ulint len) /*!< in: length of src */ -{ - const char* srcend = src + len; - - while (src < srcend) { - if ((*dest++ = *src++) == q) { - *dest++ = q; - } - } - - return(dest); -} - #ifndef UNIV_HOTBACKUP /**********************************************************************//** Return the number of times s2 occurs in s1. Overlapping instances of s2 diff --git a/ut/ut0ut.c b/ut/ut0ut.c index a9c0d381e16..f6dfb3ba0b3 100644 --- a/ut/ut0ut.c +++ b/ut/ut0ut.c @@ -674,8 +674,6 @@ ut_strerr( return("Cannot add constraint"); case DB_CORRUPTION: return("Data structure corruption"); - case DB_COL_APPEARS_TWICE_IN_INDEX: - return("Column appears twice in index"); case DB_CANNOT_DROP_CONSTRAINT: return("Cannot drop constraint"); case DB_NO_SAVEPOINT: @@ -714,6 +712,10 @@ ut_strerr( return("No index on referencing keys in referencing table"); case DB_PARENT_NO_INDEX: return("No index on referenced keys in referenced table"); + case DB_INDEX_CORRUPT: + return("Index corrupted"); + case DB_UNDO_RECORD_TOO_BIG: + return("Undo record too big"); case DB_END_OF_INDEX: return("End of index"); /* do not add default: in order to produce a warning if new code |