diff options
author | Michael Widenius <monty@mysql.com> | 2010-11-30 23:11:03 +0200 |
---|---|---|
committer | Michael Widenius <monty@mysql.com> | 2010-11-30 23:11:03 +0200 |
commit | 1e5061fe3be981d6f685a2865fd1e2bcd3fcc23a (patch) | |
tree | a0c58838a4dd7bdf2ed4d739563da27727ada7b0 /storage | |
parent | b2e979d868d5d5964d58c97ed9580e07f6123217 (diff) | |
parent | 6f279f40145624c1ffab06c63521f96ce4ac3a02 (diff) | |
download | mariadb-git-1e5061fe3be981d6f685a2865fd1e2bcd3fcc23a.tar.gz |
merge with 5.1
Diffstat (limited to 'storage')
181 files changed, 1993 insertions, 2050 deletions
diff --git a/storage/archive/Makefile.am b/storage/archive/Makefile.am index 1dbe101c2d6..83df8bae0db 100644 --- a/storage/archive/Makefile.am +++ b/storage/archive/Makefile.am @@ -65,5 +65,3 @@ archive_reader_LDFLAGS = @NOINST_LDFLAGS@ EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/blackhole/Makefile.am b/storage/blackhole/Makefile.am index 6665898cae7..0ff5ebaa17a 100644 --- a/storage/blackhole/Makefile.am +++ b/storage/blackhole/Makefile.am @@ -45,5 +45,3 @@ libblackhole_la_SOURCES= ha_blackhole.cc EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/csv/Makefile.am b/storage/csv/Makefile.am index c711e4020fc..2965b0c87eb 100644 --- a/storage/csv/Makefile.am +++ b/storage/csv/Makefile.am @@ -40,5 +40,3 @@ libcsv_la_CXXFLAGS = $(AM_CXXFLAGS) libcsv_la_SOURCES = transparent_file.cc ha_tina.cc EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/example/Makefile.am b/storage/example/Makefile.am index 807f2e39fd6..f4ee8e3c276 100644 --- a/storage/example/Makefile.am +++ b/storage/example/Makefile.am @@ -45,5 +45,4 @@ libexample_la_SOURCES= ha_example.cc EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% + diff --git a/storage/federated/Makefile.am b/storage/federated/Makefile.am index 6bea656d291..48d86dded69 100644 --- a/storage/federated/Makefile.am +++ b/storage/federated/Makefile.am @@ -49,5 +49,3 @@ libfederated_embedded_la_SOURCES= ha_federated.cc EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/federatedx/Makefile.am b/storage/federatedx/Makefile.am index 637ad642ce6..731b5dee01e 100644 --- a/storage/federatedx/Makefile.am +++ b/storage/federatedx/Makefile.am @@ -69,6 +69,3 @@ ha_federatedx_la_LIBADD = # $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES) # End - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/heap/Makefile.am b/storage/heap/Makefile.am index c896442728a..d1b5c3b0cc9 100644 --- a/storage/heap/Makefile.am +++ b/storage/heap/Makefile.am @@ -64,6 +64,3 @@ libheap.a: libheap.la EXTRA_DIST = CMakeLists.txt plug.in - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ibmdb2i/Makefile.am b/storage/ibmdb2i/Makefile.am index b9602e392e0..a9977de895d 100644 --- a/storage/ibmdb2i/Makefile.am +++ b/storage/ibmdb2i/Makefile.am @@ -50,5 +50,3 @@ libibmdb2i_a_SOURCES= $(ha_ibmdb2i_la_SOURCES) EXTRA_DIST = CMakeLists.txt plug.in -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am index c2bbb98e73d..fb75bc1eb92 100644 --- a/storage/innobase/Makefile.am +++ b/storage/innobase/Makefile.am @@ -169,6 +169,3 @@ ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES) EXTRA_DIST= CMakeLists.txt plug.in \ pars/make_bison.sh pars/make_flex.sh \ pars/pars0grm.y pars/pars0lex.l - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 5e8831b5d5e..b1b59227883 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -2060,7 +2060,6 @@ btr_compress( ulint n_recs; ulint max_ins_size; ulint max_ins_size_reorg; - ulint level; ulint comp; page = btr_cur_get_page(cursor); @@ -2072,7 +2071,6 @@ btr_compress( MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(mtr, buf_block_align(page), MTR_MEMO_PAGE_X_FIX)); - level = btr_page_get_level(page, mtr); space = dict_index_get_space(index); left_page_no = btr_page_get_prev(page, mtr); diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index d2a2e4d2157..a7160d74a32 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -3365,7 +3365,9 @@ btr_store_big_rec_extern_fields( page_t* page; ulint space_id; page_t* prev_page; +#ifdef UNIV_SYNC_DEBUG page_t* rec_page; +#endif /* UNIV_SYNC_DEBUG */ ulint prev_page_no; ulint hint_page_no; ulint i; @@ -3460,9 +3462,12 @@ btr_store_big_rec_extern_fields( extern_len -= store_len; - rec_page = buf_page_get(space_id, - buf_frame_get_page_no(data), - RW_X_LATCH, &mtr); +#ifdef UNIV_SYNC_DEBUG + rec_page = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(space_id, + buf_frame_get_page_no(data), + RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(rec_page, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ @@ -3536,10 +3541,11 @@ btr_free_externally_stored_field( X-latch to the index tree */ { page_t* page; +#ifdef UNIV_SYNC_DEBUG page_t* rec_page; +#endif /* UNIV_SYNC_DEBUG */ ulint space_id; ulint page_no; - ulint offset; ulint extern_len; ulint next_page_no; ulint part_len; @@ -3556,9 +3562,12 @@ btr_free_externally_stored_field( for (;;) { mtr_start(&mtr); - rec_page = buf_page_get(buf_frame_get_space_id(data), - buf_frame_get_page_no(data), - RW_X_LATCH, &mtr); +#ifdef UNIV_SYNC_DEBUG + rec_page = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(buf_frame_get_space_id(data), + buf_frame_get_page_no(data), + RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(rec_page, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ @@ -3568,8 +3577,6 @@ btr_free_externally_stored_field( page_no = mach_read_from_4(data + local_len + BTR_EXTERN_PAGE_NO); - offset = mach_read_from_4(data + local_len - + BTR_EXTERN_OFFSET); extern_len = mach_read_from_4(data + local_len + BTR_EXTERN_LEN + 4); diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 65b3c90c809..f73e82fb597 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -429,7 +429,6 @@ btr_pcur_move_backward_from_page( mtr_t* mtr) /* in: mtr */ { ulint prev_page_no; - ulint space; page_t* page; page_t* prev_page; ulint latch_mode; @@ -465,7 +464,6 @@ btr_pcur_move_backward_from_page( page = btr_pcur_get_page(cursor); prev_page_no = btr_page_get_prev(page, mtr); - space = buf_frame_get_space_id(page); if (btr_pcur_is_before_first_on_page(cursor, mtr) && (prev_page_no != FIL_NULL)) { diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index 84ad0e27110..97c9f89db72 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -1401,7 +1401,6 @@ btr_search_update_hash_on_delete( rec_t* rec; ulint fold; dulint index_id; - ibool found; ulint offsets_[REC_OFFS_NORMAL_SIZE]; mem_heap_t* heap = NULL; *offsets_ = (sizeof offsets_) / sizeof *offsets_; @@ -1433,7 +1432,7 @@ btr_search_update_hash_on_delete( } rw_lock_x_lock(&btr_search_latch); - found = ha_search_and_delete_if_found(table, fold, rec); + ha_search_and_delete_if_found(table, fold, rec); rw_lock_x_unlock(&btr_search_latch); } diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 45867388a61..500088c3901 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -1270,6 +1270,30 @@ loop: buf_awe_map_page_to_frame(block, TRUE); } +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + if (mode == BUF_GET_IF_IN_POOL && ibuf_debug) { + /* Try to evict the block from the buffer pool, to use the + insert buffer as much as possible. */ + + if (buf_LRU_free_block(block)) { + mutex_exit(&buf_pool->mutex); + mutex_exit(&block->mutex); + fprintf(stderr, + "innodb_change_buffering_debug evict %u %u\n", + (unsigned) space, (unsigned) offset); + return(NULL); + } else if (buf_flush_page_try(block)) { + fprintf(stderr, + "innodb_change_buffering_debug flush %u %u\n", + (unsigned) space, (unsigned) offset); + guess = block->frame; + goto loop; + } + + /* Failed to evict the page; change it directly */ + } +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + #ifdef UNIV_SYNC_DEBUG buf_block_buf_fix_inc_debug(block, file, line); #else diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 7533205d695..7dd6bfd9198 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -723,6 +723,82 @@ buf_flush_try_page( return(0); } +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_try_page(). */ + +ibool +buf_flush_page_try( +/*===============*/ + /* out: TRUE if flushed and + mutexes released */ + buf_block_t* block) /*!< in/out: buffer control block */ +{ + ut_ad(mutex_own(&buf_pool->mutex)); + ut_ad(block->state == BUF_BLOCK_FILE_PAGE); + ut_ad(mutex_own(&block->mutex)); + + if (!buf_flush_ready_for_flush(block, BUF_FLUSH_LRU)) { + return(FALSE); + } + + if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0 + || buf_pool->init_flush[BUF_FLUSH_LRU]) { + /* There is already a flush batch of the same type running */ + return(FALSE); + } + + buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE; + + block->io_fix = BUF_IO_WRITE; + block->flush_type = BUF_FLUSH_LRU; + + if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) { + + os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + /* VERY IMPORTANT: + Because any thread may call the LRU flush, even when owning + locks on pages, to avoid deadlocks, we must make sure that the + s-lock is acquired on the page without waiting: this is + accomplished because buf_flush_ready_for_flush() must hold, + and that requires the page not to be bufferfixed. */ + + rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE); + + /* Note that the s-latch is acquired before releasing the + buf_pool mutex: this ensures that the latch is acquired + immediately. */ + + mutex_exit(&block->mutex); + mutex_exit(&buf_pool->mutex); + + /* Even though block is not protected by any mutex at this + point, it is safe to access block, because it is io_fixed and + oldest_modification != 0. Thus, it cannot be relocated in the + buffer pool or removed from flush_list or LRU_list. */ + + buf_flush_write_block_low(block); + + mutex_enter(&buf_pool->mutex); + buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE; + + if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) { + /* The running flush batch has ended */ + os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + mutex_exit(&buf_pool->mutex); + buf_flush_buffered_writes(); + + return(TRUE); +} +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /*************************************************************** Flushes to disk all flushable pages within the flush area. */ static @@ -841,7 +917,6 @@ buf_flush_batch( { buf_block_t* block; ulint page_count = 0; - ulint old_page_count; ulint space; ulint offset; ibool found; @@ -913,15 +988,9 @@ buf_flush_batch( mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); - old_page_count = page_count; - /* Try to flush also all the neighbors */ page_count += buf_flush_try_neighbors( space, offset, flush_type); - /* fprintf(stderr, - "Flush type %lu, page no %lu, neighb %lu\n", - flush_type, offset, - page_count - old_page_count); */ mutex_enter(&(buf_pool->mutex)); diff --git a/storage/innobase/buf/buf0lru.c b/storage/innobase/buf/buf0lru.c index d3c787d1578..1dc3efd1464 100644 --- a/storage/innobase/buf/buf0lru.c +++ b/storage/innobase/buf/buf0lru.c @@ -321,6 +321,60 @@ buf_LRU_get_recent_limit(void) } /********************************************************************** +Try to put a block from the LRU list to the free list. */ + +ibool +buf_LRU_free_block( +/*===============*/ + /* out: TRUE if freed */ + buf_block_t* block) /* in/out: block to be freed */ +{ + if (!buf_flush_ready_for_replace(block)) { + return(FALSE); + } + +#ifdef UNIV_DEBUG + if (buf_debug_prints) { + fprintf(stderr, + "Putting space %lu page %lu" + " to free list\n", + (ulong) block->space, + (ulong) block->offset); + } +#endif /* UNIV_DEBUG */ + + buf_LRU_block_remove_hashed_page(block); + + mutex_exit(&(buf_pool->mutex)); + mutex_exit(&block->mutex); + + /* Remove possible adaptive hash index built on the + page; in the case of AWE the block may not have a + frame at all */ + + if (block->frame) { + /* The page was declared uninitialized + by buf_LRU_block_remove_hashed_page(). + We need to flag the contents of the + page valid (which it still is) in + order to avoid bogus Valgrind + warnings. */ + UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE); + btr_search_drop_page_hash_index(block->frame); + UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE); + } + + ut_a(block->buf_fix_count == 0); + + mutex_enter(&(buf_pool->mutex)); + mutex_enter(&block->mutex); + + buf_LRU_block_free_hashed_page(block); + + return(TRUE); +} + +/********************************************************************** Look for a replaceable block from the end of the LRU list and put it to the free list if found. */ @@ -348,54 +402,13 @@ buf_LRU_search_and_free_block( ut_a(block->in_LRU_list); mutex_enter(&block->mutex); + freed = buf_LRU_free_block(block); + mutex_exit(&block->mutex); - if (buf_flush_ready_for_replace(block)) { - -#ifdef UNIV_DEBUG - if (buf_debug_prints) { - fprintf(stderr, - "Putting space %lu page %lu" - " to free list\n", - (ulong) block->space, - (ulong) block->offset); - } -#endif /* UNIV_DEBUG */ - - buf_LRU_block_remove_hashed_page(block); - - mutex_exit(&(buf_pool->mutex)); - mutex_exit(&block->mutex); - - /* Remove possible adaptive hash index built on the - page; in the case of AWE the block may not have a - frame at all */ - - if (block->frame) { - /* The page was declared uninitialized - by buf_LRU_block_remove_hashed_page(). - We need to flag the contents of the - page valid (which it still is) in - order to avoid bogus Valgrind - warnings. */ - UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE); - btr_search_drop_page_hash_index(block->frame); - UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE); - } - - ut_a(block->buf_fix_count == 0); - - mutex_enter(&(buf_pool->mutex)); - mutex_enter(&block->mutex); - - buf_LRU_block_free_hashed_page(block); - freed = TRUE; - mutex_exit(&block->mutex); - + if (freed) { break; } - mutex_exit(&block->mutex); - block = UT_LIST_GET_PREV(LRU, block); distance++; diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index 625956600c0..c505bfbd6c4 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -878,13 +878,13 @@ err_exit: if (err != DB_SUCCESS) { dict_table_remove_from_cache(table); table = NULL; + } else { + table->fk_max_recusive_level = 0; } } else if (!srv_force_recovery) { dict_table_remove_from_cache(table); table = NULL; } - - table->fk_max_recusive_level = 0; #if 0 if (err != DB_SUCCESS && table != NULL) { diff --git a/storage/innobase/eval/eval0eval.c b/storage/innobase/eval/eval0eval.c index cbc47ec508f..52e9923fc05 100644 --- a/storage/innobase/eval/eval0eval.c +++ b/storage/innobase/eval/eval0eval.c @@ -367,18 +367,13 @@ eval_notfound( /*==========*/ func_node_t* func_node) /* in: function node */ { - que_node_t* arg1; - que_node_t* arg2; sym_node_t* cursor; sel_node_t* sel_node; ibool ibool_val; - arg1 = func_node->args; - arg2 = que_node_get_next(arg1); - ut_ad(func_node->func == PARS_NOTFOUND_TOKEN); - cursor = arg1; + cursor = func_node->args; ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 887f29064ed..4c52326a58a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -79,6 +79,7 @@ extern "C" { #include "../storage/innobase/include/dict0crea.h" #include "../storage/innobase/include/btr0cur.h" #include "../storage/innobase/include/btr0btr.h" +#include "../storage/innobase/include/ibuf0ibuf.h" #include "../storage/innobase/include/fsp0fsp.h" #include "../storage/innobase/include/sync0sync.h" #include "../storage/innobase/include/fil0fil.h" @@ -3723,17 +3724,18 @@ include_field: n_requested_fields++; templ->col_no = i; + templ->clust_rec_field_no = dict_col_get_clust_pos_noninline( + &index->table->cols[i], clust_index); + ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED); if (index == clust_index) { - templ->rec_field_no = dict_col_get_clust_pos_noninline( - &index->table->cols[i], index); + templ->rec_field_no = templ->clust_rec_field_no; } else { templ->rec_field_no = dict_index_get_nth_col_pos( index, i); - } - - if (templ->rec_field_no == ULINT_UNDEFINED) { - prebuilt->need_to_access_clustered = TRUE; + if (templ->rec_field_no == ULINT_UNDEFINED) { + prebuilt->need_to_access_clustered = TRUE; + } } if (field->null_ptr) { @@ -3785,9 +3787,7 @@ skip_field: for (i = 0; i < n_requested_fields; i++) { templ = prebuilt->mysql_template + i; - templ->rec_field_no = dict_col_get_clust_pos_noninline( - &index->table->cols[templ->col_no], - clust_index); + templ->rec_field_no = templ->clust_rec_field_no; } } } @@ -5983,7 +5983,6 @@ innobase_drop_database( trx_t* parent_trx; trx_t* trx; char* ptr; - int error; char* namebuf; THD* thd = current_thd; @@ -6021,7 +6020,7 @@ innobase_drop_database( trx->check_foreigns = FALSE; } - error = row_drop_database_for_mysql(namebuf, trx); + row_drop_database_for_mysql(namebuf, trx); my_free(namebuf, MYF(0)); /* Flush the log to reduce probability that the .frm files and @@ -6037,13 +6036,7 @@ innobase_drop_database( innobase_commit_low(trx); trx_free_for_mysql(trx); -#ifdef NO_LONGER_INTERESTED_IN_DROP_DB_ERROR - error = convert_error_code_to_mysql(error, NULL); - - return(error); -#else return; -#endif } /************************************************************************* @@ -6374,9 +6367,12 @@ Returns statistics information of the table to the MySQL interpreter, in various fields of the handle object. */ int -ha_innobase::info( -/*==============*/ - uint flag) /* in: what information MySQL requests */ +ha_innobase::info_low( +/*==================*/ + uint flag, /* in: what information MySQL + requests */ + bool called_from_analyze) /* in: TRUE if called from + ::analyze() */ { dict_table_t* ib_table; dict_index_t* index; @@ -6407,7 +6403,7 @@ ha_innobase::info( ib_table = prebuilt->table; if (flag & HA_STATUS_TIME) { - if (innobase_stats_on_metadata) { + if (called_from_analyze || innobase_stats_on_metadata) { /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ @@ -6623,6 +6619,18 @@ func_exit: DBUG_RETURN(0); } +/************************************************************************* +Returns statistics information of the table to the MySQL interpreter, +in various fields of the handle object. */ + +int +ha_innobase::info( +/*==============*/ + uint flag) /* in: what information MySQL requests */ +{ + return(info_low(flag, false /* not called from analyze */)); +} + /************************************************************************** Updates index cardinalities of the table, based on 8 random dives into each index tree. This does NOT calculate exact statistics on the table. */ @@ -6639,7 +6647,8 @@ ha_innobase::analyze( pthread_mutex_lock(&analyze_mutex); /* Simply call ::info() with all the flags */ - info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, + true /* called from analyze */); pthread_mutex_unlock(&analyze_mutex); @@ -6812,8 +6821,6 @@ ha_innobase::get_foreign_key_create_info(void) flen = ftell(srv_dict_tmpfile); if (flen < 0) { flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; } /* allocate buffer for the string, and @@ -7560,12 +7567,9 @@ innodb_show_status( mutex_exit_noninline(&srv_monitor_file_mutex); - bool result = FALSE; + stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), + STRING_WITH_LEN(""), str, flen); - if (stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), - STRING_WITH_LEN(""), str, flen)) { - result= TRUE; - } my_free(str, MYF(0)); DBUG_RETURN(FALSE); @@ -8986,6 +8990,13 @@ static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode, AUTOINC_OLD_STYLE_LOCKING, /* Minimum value */ AUTOINC_NO_LOCKING, 0); /* Maximum value */ +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, + PLUGIN_VAR_RQCMDARG, + "Debug flags for InnoDB change buffering (0=none)", + NULL, NULL, 0, 0, 1, 0); +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), @@ -9027,6 +9038,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(thread_concurrency), MYSQL_SYSVAR(thread_sleep_delay), MYSQL_SYSVAR(autoinc_lock_mode), +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + MYSQL_SYSVAR(change_buffering_debug), +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ NULL }; diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index eb9199b8955..8b91f7d4c51 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -80,6 +80,7 @@ class ha_innobase: public handler ulong innobase_update_autoinc(ulonglong auto_inc); void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); + int info_low(uint flag, bool called_from_analyze); /* Init values for the class: */ public: diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index d54a3378993..71ecc7ec49f 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -22,6 +22,7 @@ Created 7/19/1997 Heikki Tuuri #include "btr0cur.h" #include "btr0pcur.h" #include "btr0btr.h" +#include "row0upd.h" #include "sync0sync.h" #include "dict0boot.h" #include "fut0lst.h" @@ -137,6 +138,11 @@ access order rules. */ /* Buffer pool size per the maximum insert buffer size */ #define IBUF_POOL_SIZE_PER_MAX_SIZE 2 +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/* Flag to control insert buffer debugging. */ +uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /* The insert buffer control structure */ ibuf_t* ibuf = NULL; @@ -2824,6 +2830,72 @@ During merge, inserts to an index page a secondary index entry extracted from the insert buffer. */ static void +ibuf_insert_to_index_page_low( +/*==========================*/ + dtuple_t* entry, /* in: buffered entry to insert */ + page_t* page, /* in: index page where the buffered entry + should be placed */ + dict_index_t* index, /* in: record descriptor */ + mtr_t* mtr, /* in: mtr */ + page_cur_t* page_cur)/* in: cursor positioned on the record + after which to insert the buffered entry */ +{ + ulint space; + ulint page_no; + page_t* bitmap_page; + ulint old_bits; + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, mtr) != NULL)) { + return; + } + + /* If the record did not fit, reorganize */ + + btr_page_reorganize(page, index, mtr); + + page_cur_search(page, index, entry, PAGE_CUR_LE, page_cur); + + /* This time the record must fit */ + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, mtr) != NULL)) { + return; + } + + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: Error: Insert buffer insert fails;" + " page free %lu, dtuple size %lu\n", + (ulong) page_get_max_insert_size(page, 1), + (ulong) rec_get_converted_size(index, entry)); + fputs("InnoDB: Cannot insert index record ", stderr); + dtuple_print(stderr, entry); + fputs("\nInnoDB: The table where this index record belongs\n" + "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" + "InnoDB: that table.\n", stderr); + + space = buf_frame_get_space_id(page); + page_no = buf_frame_get_page_no(page); + + bitmap_page = ibuf_bitmap_get_map_page(space, page_no, mtr); + old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, + IBUF_BITMAP_FREE, mtr); + + fprintf(stderr, + "InnoDB: space %lu, page %lu, bitmap bits %lu\n", + (ulong) space, (ulong) page_no, (ulong) old_bits); + + fputs("InnoDB: Submit a detailed bug report" + " to http://bugs.mysql.com\n", stderr); +} + +/************************************************************************ +During merge, inserts to an index page a secondary index entry extracted +from the insert buffer. */ +static +void ibuf_insert_to_index_page( /*======================*/ dtuple_t* entry, /* in: buffered entry to insert */ @@ -2835,11 +2907,10 @@ ibuf_insert_to_index_page( page_cur_t page_cur; ulint low_match; rec_t* rec; - page_t* bitmap_page; - ulint old_bits; ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); + ut_ad(!buf_block_align(page)->is_hashed); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) != (ibool)!!page_is_comp(page))) { @@ -2877,61 +2948,79 @@ dump: low_match = page_cur_search(page, index, entry, PAGE_CUR_LE, &page_cur); - if (low_match == dtuple_get_n_fields(entry)) { + if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) { + mem_heap_t* heap; + upd_t* update; + ulint* offsets; + rec = page_cur_get_rec(&page_cur); - btr_cur_del_unmark_for_ibuf(rec, mtr); - } else { - rec = page_cur_tuple_insert(&page_cur, entry, index, mtr); + /* This is based on + row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ + ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - if (rec == NULL) { - /* If the record did not fit, reorganize */ + heap = mem_heap_create(1024); - btr_page_reorganize(page, index, mtr); + offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, + &heap); + update = row_upd_build_sec_rec_difference_binary( + index, entry, rec, NULL, heap); - page_cur_search(page, index, entry, - PAGE_CUR_LE, &page_cur); + if (update->n_fields == 0) { + /* The records only differ in the delete-mark. + Clear the delete-mark, like we did before + Bug #56680 was fixed. */ + btr_cur_del_unmark_for_ibuf(rec, mtr); +updated_in_place: + mem_heap_free(heap); + return; + } - /* This time the record must fit */ - if (UNIV_UNLIKELY(!page_cur_tuple_insert( - &page_cur, entry, index, - mtr))) { + /* Copy the info bits. Clear the delete-mark. */ + update->info_bits = rec_get_info_bits(rec, page_is_comp(page)); + update->info_bits &= ~REC_INFO_DELETED_FLAG; + + /* We cannot invoke btr_cur_optimistic_update() here, + because we do not have a btr_cur_t or que_thr_t, + as the insert buffer merge occurs at a very low level. */ + if (!row_upd_changes_field_size_or_external(index, offsets, + update)) { + /* This is the easy case. Do something similar + to btr_cur_update_in_place(). */ + row_upd_rec_in_place(rec, offsets, update); + goto updated_in_place; + } - ut_print_timestamp(stderr); + /* A collation may identify values that differ in + storage length. + Some examples (1 or 2 bytes): + utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I + utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S + utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS - fprintf(stderr, - " InnoDB: Error: Insert buffer insert" - " fails; page free %lu," - " dtuple size %lu\n", - (ulong) page_get_max_insert_size( - page, 1), - (ulong) rec_get_converted_size( - index, entry)); - fputs("InnoDB: Cannot insert index record ", - stderr); - dtuple_print(stderr, entry); - fputs("\nInnoDB: The table where" - " this index record belongs\n" - "InnoDB: is now probably corrupt." - " Please run CHECK TABLE on\n" - "InnoDB: that table.\n", stderr); - - bitmap_page = ibuf_bitmap_get_map_page( - buf_frame_get_space_id(page), - buf_frame_get_page_no(page), - mtr); - old_bits = ibuf_bitmap_page_get_bits( - bitmap_page, - buf_frame_get_page_no(page), - IBUF_BITMAP_FREE, mtr); + latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S - fprintf(stderr, "InnoDB: Bitmap bits %lu\n", - (ulong) old_bits); + Examples of a character (3-byte UTF-8 sequence) + identified with 2 or 4 characters (1-byte UTF-8 sequences): - fputs("InnoDB: Submit a detailed bug report" - " to http://bugs.mysql.com\n", stderr); - } - } + utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO + utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN + */ + + /* Delete the different-length record, and insert the + buffered one. */ + + lock_rec_store_on_page_infimum(page, rec); + page_cur_delete_rec(&page_cur, index, offsets, mtr); + page_cur_move_to_prev(&page_cur); + mem_heap_free(heap); + + ibuf_insert_to_index_page_low(entry, page, index, mtr, + &page_cur); + lock_rec_restore_from_page_infimum(rec, page); + } else { + ibuf_insert_to_index_page_low(entry, page, index, mtr, + &page_cur); } } diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index 322848509f4..e52c22b8f57 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -38,6 +38,20 @@ buf_flush_init_for_writing( dulint newest_lsn, /* in: newest modification lsn to the page */ ulint space, /* in: space id */ ulint page_no); /* in: page number */ +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_try_page(). */ + +ibool +buf_flush_page_try( +/*===============*/ + /* out: TRUE if flushed and + mutexes released */ + buf_block_t* block); /*!< in/out: buffer control block */ +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ /*********************************************************************** This utility flushes dirty blocks from the end of the LRU list or flush_list. NOTE 1: in the case of an LRU flush the calling thread may own latches to diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 6d26fd4d3b2..777e55a350d 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -66,6 +66,14 @@ buf_LRU_get_recent_limit(void); /*==========================*/ /* out: the limit; zero if could not determine it */ /********************************************************************** +Try to put a block from the LRU list to the free list. */ + +ibool +buf_LRU_free_block( +/*===============*/ + /* out: TRUE if freed */ + buf_block_t* block); /* in/out: block to be freed */ +/********************************************************************** Look for a replaceable block from the end of the LRU list and put it to the free list if found. */ diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 77fefe2020b..d6d7a918b62 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -18,6 +18,11 @@ Created 7/19/1997 Heikki Tuuri #include "ibuf0types.h" #include "fsp0fsp.h" +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/* Flag to control insert buffer debugging. */ +extern uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + extern ibuf_t* ibuf; /********************************************************************** diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index abc204bb583..58762fc3111 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -19,6 +19,9 @@ if and only if the record is the first user record on a non-leaf B-tree page that is the leftmost page on its level (PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */ #define REC_INFO_MIN_REC_FLAG 0x10UL +/* The deleted flag in info bits */ +#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the + record has been delete marked */ /* Number of extra bytes in an old-style record, in addition to the data and the offsets */ diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index d91fb4c4391..df66bb13aeb 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -98,9 +98,6 @@ and the shift needed to obtain each bit-field of the record. */ #define REC_INFO_BITS_MASK 0xF0UL #define REC_INFO_BITS_SHIFT 0 -/* The deleted flag in info bits */ -#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the - record has been delete marked */ /* The following masks are used to filter the SQL null bit from one-byte and two-byte offsets */ diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 488177791a4..52b13838cc7 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -485,6 +485,10 @@ struct mysql_row_templ_struct { Innobase record in the current index; not defined if template_type is ROW_MYSQL_WHOLE_ROW */ + ulint clust_rec_field_no; /* field number of the column in an + Innobase record in the clustered index; + not defined if template_type is + ROW_MYSQL_WHOLE_ROW */ ulint mysql_col_offset; /* offset of the column in the MySQL row format */ ulint mysql_col_len; /* length of the column in the MySQL diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index efbc6d6facf..034b1dafb17 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -129,9 +129,11 @@ row_upd_changes_field_size_or_external( const ulint* offsets,/* in: rec_get_offsets(rec, index) */ upd_t* update);/* in: update vector */ /*************************************************************** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. This function is used only for -a clustered index */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ void row_upd_rec_in_place( diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index a317f35f4be..06dead7fc03 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -39,7 +39,7 @@ extern ibool panic_shutdown; void ut_dbg_panic(void); # define UT_DBG_PANIC ut_dbg_panic() /* Stop threads in ut_a(). */ -# define UT_DBG_STOP while (0) /* We do not do this on NetWare */ +# define UT_DBG_STOP do {} while (0) /* We do not do this on NetWare */ #else /* __NETWARE__ */ # if defined(__WIN__) || defined(__INTEL_COMPILER) # undef UT_DBG_USE_ABORT @@ -71,7 +71,7 @@ ut_dbg_stop_thread( /* Abort the execution. */ # define UT_DBG_PANIC abort() /* Stop threads (null operation) */ -# define UT_DBG_STOP while (0) +# define UT_DBG_STOP do {} while (0) # else /* UT_DBG_USE_ABORT */ /* Abort the execution. */ # define UT_DBG_PANIC \ diff --git a/storage/innobase/include/ut0rnd.ic b/storage/innobase/include/ut0rnd.ic index 625c378489a..dc4c0d62f56 100644 --- a/storage/innobase/include/ut0rnd.ic +++ b/storage/innobase/include/ut0rnd.ic @@ -67,9 +67,6 @@ ut_rnd_gen_ulint(void) /* out: the 'random' number */ { ulint rnd; - ulint n_bits; - - n_bits = 8 * sizeof(ulint); ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 04240960b3a..57df99fb401 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -4296,7 +4296,6 @@ lock_print_info_all_transactions( lock_t* lock; ulint space; ulint page_no; - page_t* page; ibool load_page_first = TRUE; ulint nth_trx = 0; ulint nth_lock = 0; @@ -4410,8 +4409,7 @@ loop: mtr_start(&mtr); - page = buf_page_get_with_no_latch( - space, page_no, &mtr); + buf_page_get_with_no_latch(space, page_no, &mtr); mtr_commit(&mtr); diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index e6524eeefbf..6e1ca58cb15 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -400,10 +400,8 @@ recv_synchronize_groups( dulint start_lsn; dulint end_lsn; dulint recovered_lsn; - dulint limit_lsn; recovered_lsn = recv_sys->recovered_lsn; - limit_lsn = recv_sys->limit_lsn; /* Read the last recovered log block to the recovery system buffer: the block is always incomplete */ @@ -2506,7 +2504,9 @@ recv_recovery_from_checkpoint_start( dulint old_scanned_lsn; dulint group_scanned_lsn; dulint contiguous_lsn; +#ifdef UNIV_LOG_ARCHIVE dulint archived_lsn; +#endif /* UNIV_LOG_ARCHIVE */ ulint capacity; byte* buf; byte log_hdr_buf[LOG_FILE_HDR_SIZE]; @@ -2552,7 +2552,9 @@ recv_recovery_from_checkpoint_start( checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO); +#ifdef UNIV_LOG_ARCHIVE archived_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_ARCHIVED_LSN); +#endif /* UNIV_LOG_ARCHIVE */ /* Read the first log file header to print a note if this is a recovery from a restored InnoDB Hot Backup */ diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 3396d1adf2f..566c50381e7 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -1138,9 +1138,12 @@ Tries to disable OS caching on an opened file descriptor. */ void os_file_set_nocache( /*================*/ - int fd, /* in: file descriptor to alter */ - const char* file_name, /* in: used in the diagnostic message */ - const char* operation_name) /* in: used in the diagnostic message, + int fd /* in: file descriptor to alter */ + __attribute__((unused)), + const char* file_name /* in: used in the diagnostic message */ + __attribute__((unused)), + const char* operation_name __attribute__((unused))) + /* in: used in the diagnostic message, we call os_file_set_nocache() immediately after opening or creating a file, so this is either "open" or @@ -1314,8 +1317,6 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; - const char* type_str = NULL; - const char* purpose_str = NULL; try_again: ut_a(name); @@ -1335,26 +1336,9 @@ try_again: ut_error; } - if (type == OS_LOG_FILE) { - type_str = "LOG"; - } else if (type == OS_DATA_FILE) { - type_str = "DATA"; - } else { - ut_error; - } - - if (purpose == OS_FILE_AIO) { - purpose_str = "AIO"; - } else if (purpose == OS_FILE_NORMAL) { - purpose_str = "NORMAL"; - } else { - ut_error; - } + ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); + ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL); -#if 0 - fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n", - name, mode_str, type_str, purpose_str); -#endif #ifdef O_SYNC /* We let O_SYNC only affect log files; note that we map O_DSYNC to O_SYNC because the datasync options seemed to corrupt files in 2001 @@ -2223,7 +2207,10 @@ os_file_read( ibool retry; ulint i; + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2340,7 +2327,10 @@ os_file_read_no_error_handling( ibool retry; ulint i; + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2463,7 +2453,10 @@ os_file_write( ulint n_retries = 0; ulint err; - ut_a((offset & 0xFFFFFFFF) == offset); + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ + ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_writes++; @@ -3261,14 +3254,16 @@ os_aio_array_reserve_slot( ulint len) /* in: length of the block to read or write */ { os_aio_slot_t* slot; + ulint i; #ifdef WIN_ASYNC_IO OVERLAPPED* control; + ut_a((len & 0xFFFFFFFFUL) == len); #elif defined(POSIX_ASYNC_IO) struct aiocb* control; #endif - ulint i; + loop: os_mutex_enter(array->mutex); @@ -3533,6 +3528,9 @@ os_aio( ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(os_aio_validate()); +#ifdef WIN_ASYNC_IO + ut_ad((n & 0xFFFFFFFFUL) == n); +#endif wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); @@ -3781,16 +3779,18 @@ os_aio_windows_handle( /* retry failed read/write operation synchronously. No need to hold array->mutex. */ + ut_a((slot->len & 0xFFFFFFFFUL) == slot->len); + switch (slot->type) { case OS_FILE_WRITE: ret = WriteFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; case OS_FILE_READ: ret = ReadFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; diff --git a/storage/innobase/que/que0que.c b/storage/innobase/que/que0que.c index bf83f28f04e..1a76823ca4d 100644 --- a/storage/innobase/que/que0que.c +++ b/storage/innobase/que/que0que.c @@ -802,13 +802,11 @@ que_thr_dec_refer_count( { que_fork_t* fork; trx_t* trx; - sess_t* sess; ulint fork_type; ibool stopped; fork = thr->common.parent; trx = thr_get_trx(thr); - sess = trx->sess; mutex_enter(&kernel_mutex); @@ -1292,18 +1290,13 @@ que_run_threads_low( que_thr_t* thr) /* in: query thread */ { que_thr_t* next_thr; - ulint cumul_resource; ulint loop_count; ut_ad(thr->state == QUE_THR_RUNNING); ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS); ut_ad(!mutex_own(&kernel_mutex)); - /* cumul_resource counts how much resources the OS thread (NOT the - query thread) has spent in this function */ - loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; - cumul_resource = 0; loop: /* Check that there is enough space in the log to accommodate possible log entries by this query step; if the operation can touch diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index aae4703737b..4fdd92c7cba 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -400,7 +400,7 @@ row_mysql_convert_row_to_innobase( row is used, as row may contain pointers to this record! */ { - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; dfield_t* dfield; ulint i; @@ -1457,7 +1457,12 @@ run_again: srv_n_rows_updated++; } - row_update_statistics_if_needed(prebuilt->table); + /* We update table statistics only if it is a DELETE or UPDATE + 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)) { + row_update_statistics_if_needed(prebuilt->table); + } trx->op_info = ""; @@ -1608,6 +1613,9 @@ row_update_cascade_for_mysql( trx = thr_get_trx(thr); + /* Increment fk_cascade_depth to record the recursive call depth on + a single update/delete that affects multiple tables chained + together with foreign key relations. */ thr->fk_cascade_depth++; if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) { @@ -1619,6 +1627,12 @@ run_again: row_upd_step(thr); + /* The recursive call for cascading update/delete happens + in above row_upd_step(), reset the counter once we come + out of the recursive call, so it does not accumulate for + different row deletes */ + thr->fk_cascade_depth = 0; + err = trx->error_state; /* Note that the cascade node is a subnode of another InnoDB @@ -1967,6 +1981,7 @@ row_create_table_for_mysql( table already exists */ trx->error_state = DB_SUCCESS; + dict_mem_table_free(table); } que_graph_free((que_t*) que_node_get_parent(thr)); diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index 1fef47da13f..deec3b0a454 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -667,7 +667,7 @@ row_purge_step( err = row_purge(node, thr); - ut_ad(err == DB_SUCCESS); + ut_a(err == DB_SUCCESS); return(thr); } diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 06a19ba7979..e03d3d79768 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2601,38 +2601,38 @@ row_sel_store_mysql_rec( row_prebuilt_t* prebuilt, /* in: prebuilt struct */ rec_t* rec, /* in: Innobase record in the index which was described in prebuilt's - template */ + template, or in the clustered index; + must be protected by a page latch */ + ibool rec_clust, /* in: TRUE if rec is in the clustered + index instead of prebuilt->index */ const ulint* offsets) /* in: array returned by - rec_get_offsets() */ + rec_get_offsets(rec) */ { - mysql_row_templ_t* templ; mem_heap_t* extern_field_heap = NULL; mem_heap_t* heap; - byte* data; - ulint len; ulint i; ut_ad(prebuilt->mysql_template); ut_ad(prebuilt->default_rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) { mem_heap_free(prebuilt->blob_heap); prebuilt->blob_heap = NULL; } - /* init null bytes with default values as they might be - left uninitialized in some cases and this uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); - for (i = 0; i < prebuilt->n_template; i++) { - templ = prebuilt->mysql_template + i; + const mysql_row_templ_t*templ = prebuilt->mysql_template + i; + byte* data; + ulint len; + ulint field_no; + + field_no = rec_clust + ? templ->clust_rec_field_no : templ->rec_field_no; - if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, - templ->rec_field_no))) { + if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) { /* Copy an externally stored field to the temporary heap */ @@ -2658,15 +2658,13 @@ row_sel_store_mysql_rec( causes an assert */ data = btr_rec_copy_externally_stored_field( - rec, offsets, templ->rec_field_no, - &len, heap); + rec, offsets, field_no, &len, heap); ut_a(len != UNIV_SQL_NULL); } else { /* Field is stored in the row. */ - data = rec_get_nth_field(rec, offsets, - templ->rec_field_no, &len); + data = rec_get_nth_field(rec, offsets, field_no, &len); if (UNIV_UNLIKELY(templ->type == DATA_BLOB) && len != UNIV_SQL_NULL) { @@ -3025,7 +3023,7 @@ row_sel_pop_cached_row_for_mysql( row_prebuilt_t* prebuilt) /* in: prebuilt struct */ { ulint i; - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); @@ -3081,14 +3079,19 @@ void row_sel_push_cache_row_for_mysql( /*=============================*/ row_prebuilt_t* prebuilt, /* in: prebuilt struct */ - rec_t* rec, /* in: record to push */ - const ulint* offsets) /* in: rec_get_offsets() */ + rec_t* rec, /* in: Innobase record in the index + which was described in prebuilt's + template, or in the clustered index */ + ibool rec_clust, /* in: TRUE if rec is in the clustered + index instead of prebuilt->index */ + const ulint* offsets) /* in: rec_get_offsets(rec) */ { byte* buf; ulint i; ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); ut_a(!prebuilt->templ_contains_blob); if (prebuilt->fetch_cache[0] == NULL) { @@ -3117,7 +3120,7 @@ row_sel_push_cache_row_for_mysql( if (UNIV_UNLIKELY(!row_sel_store_mysql_rec( prebuilt->fetch_cache[ prebuilt->n_fetch_cached], - prebuilt, rec, offsets))) { + prebuilt, rec, rec_clust, offsets))) { ut_error; } @@ -3259,6 +3262,7 @@ row_search_for_mysql( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; + ibool table_lock_waited = FALSE; *offsets_ = (sizeof offsets_) / sizeof *offsets_; @@ -3505,7 +3509,8 @@ row_search_for_mysql( rec, offsets)); #endif if (!row_sel_store_mysql_rec(buf, prebuilt, - rec, offsets)) { + rec, FALSE, + offsets)) { err = DB_TOO_BIG_RECORD; /* We let the main loop to do the @@ -3599,6 +3604,44 @@ shortcut_fails_too_big_rec: clust_index = dict_table_get_first_index(index->table); + /* Do some start-of-statement preparations */ + + if (!prebuilt->sql_stat_start) { + /* No need to set an intention lock or assign a read view */ + + if (trx->read_view == NULL + && prebuilt->select_lock_type == LOCK_NONE) { + + fputs("InnoDB: Error: MySQL is trying to" + " perform a consistent read\n" + "InnoDB: but the read view is not assigned!\n", + stderr); + trx_print(stderr, trx, 600); + fputc('\n', stderr); + ut_error; + } + } else if (prebuilt->select_lock_type == LOCK_NONE) { + /* This is a consistent read */ + /* Assign a read view for the query */ + + trx_assign_read_view(trx); + prebuilt->sql_stat_start = FALSE; + } else { +wait_table_again: + err = lock_table(0, index->table, + prebuilt->select_lock_type == LOCK_S + ? LOCK_IS : LOCK_IX, thr); + + if (err != DB_SUCCESS) { + + table_lock_waited = TRUE; + goto lock_table_wait; + } + prebuilt->sql_stat_start = FALSE; + } + + /* Open or restore index cursor position */ + if (UNIV_LIKELY(direction != 0)) { ibool need_to_process = sel_restore_position_for_mysql( &same_user_rec, BTR_SEARCH_LEAF, @@ -3674,42 +3717,6 @@ shortcut_fails_too_big_rec: } } - if (!prebuilt->sql_stat_start) { - /* No need to set an intention lock or assign a read view */ - - if (trx->read_view == NULL - && prebuilt->select_lock_type == LOCK_NONE) { - - fputs("InnoDB: Error: MySQL is trying to" - " perform a consistent read\n" - "InnoDB: but the read view is not assigned!\n", - stderr); - trx_print(stderr, trx, 600); - fputc('\n', stderr); - ut_a(0); - } - } else if (prebuilt->select_lock_type == LOCK_NONE) { - /* This is a consistent read */ - /* Assign a read view for the query */ - - trx_assign_read_view(trx); - prebuilt->sql_stat_start = FALSE; - } else { - ulint lock_mode; - if (prebuilt->select_lock_type == LOCK_S) { - lock_mode = LOCK_IS; - } else { - lock_mode = LOCK_IX; - } - err = lock_table(0, index->table, lock_mode, thr); - - if (err != DB_SUCCESS) { - - goto lock_wait_or_error; - } - prebuilt->sql_stat_start = FALSE; - } - rec_loop: /*-------------------------------------------------------------*/ /* PHASE 4: Look for matching records in a loop */ @@ -4236,19 +4243,8 @@ requires_clust_rec: goto next_rec; } - if (prebuilt->need_to_access_clustered) { - - result_rec = clust_rec; - - ut_ad(rec_offs_validate(result_rec, clust_index, - offsets)); - } else { - /* We used 'offsets' for the clust rec, recalculate - them for 'rec' */ - offsets = rec_get_offsets(rec, index, offsets, - ULINT_UNDEFINED, &heap); - result_rec = rec; - } + result_rec = clust_rec; + ut_ad(rec_offs_validate(result_rec, clust_index, offsets)); } else { result_rec = rec; } @@ -4259,6 +4255,7 @@ requires_clust_rec: ut_ad(rec_offs_validate(result_rec, result_rec != rec ? clust_index : index, offsets)); + ut_ad(!rec_get_deleted_flag(result_rec, comp)); if ((match_mode == ROW_SEL_EXACT || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD) @@ -4279,7 +4276,7 @@ requires_clust_rec: cursor. */ row_sel_push_cache_row_for_mysql(prebuilt, result_rec, - offsets); + result_rec != rec, offsets); if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) { goto got_row; @@ -4287,15 +4284,31 @@ requires_clust_rec: goto next_rec; } else { - if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) { + if (UNIV_UNLIKELY + (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) { + /* CHECK TABLE: fetch the row */ + + if (result_rec != rec + && !prebuilt->need_to_access_clustered) { + /* We used 'offsets' for the clust + rec, recalculate them for 'rec' */ + offsets = rec_get_offsets(rec, index, offsets, + ULINT_UNDEFINED, + &heap); + result_rec = rec; + } + memcpy(buf + 4, result_rec - rec_offs_extra_size(offsets), rec_offs_size(offsets)); mach_write_to_4(buf, rec_offs_extra_size(offsets) + 4); } else { - if (!row_sel_store_mysql_rec(buf, prebuilt, - result_rec, offsets)) { + /* Returning a row to MySQL */ + + if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec, + result_rec != rec, + offsets)) { err = DB_TOO_BIG_RECORD; goto lock_wait_or_error; @@ -4408,6 +4421,7 @@ lock_wait_or_error: btr_pcur_store_position(pcur, &mtr); +lock_table_wait: mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; @@ -4425,6 +4439,14 @@ lock_wait_or_error: thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); + /* Table lock waited, go try to obtain table lock + again */ + if (table_lock_waited) { + table_lock_waited = FALSE; + + goto wait_table_again; + } + sel_restore_position_for_mysql(&same_user_rec, BTR_SEARCH_LEAF, pcur, moves_up, &mtr); diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c index 68139da116e..a3333fcc536 100644 --- a/storage/innobase/row/row0umod.c +++ b/storage/innobase/row/row0umod.c @@ -89,12 +89,17 @@ row_undo_mod_clust_low( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; +#ifdef UNIV_DEBUG ibool success; +#endif /* UNIV_DEBUG */ pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); - success = btr_pcur_restore_position(mode, pcur, mtr); +#ifdef UNIV_DEBUG + success = +#endif /* UNIV_DEBUG */ + btr_pcur_restore_position(mode, pcur, mtr); ut_ad(success); diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index c91cc449b96..0790cfe02e2 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -430,9 +430,11 @@ row_upd_changes_field_size_or_external( } /*************************************************************** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. This function is used only for -a clustered index */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ void row_upd_rec_in_place( @@ -2037,7 +2039,9 @@ row_upd_in_place_in_select( upd_node_t* node; btr_pcur_t* pcur; btr_cur_t* btr_cur; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; *offsets_ = (sizeof offsets_) / sizeof *offsets_; @@ -2074,8 +2078,11 @@ row_upd_in_place_in_select( ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); ut_ad(node->select_will_do_update); - err = btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur, - node->update, node->cmpl_info, - thr, mtr); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + btr_cur_update_in_place(BTR_NO_LOCKING_FLAG, btr_cur, + node->update, node->cmpl_info, + thr, mtr); ut_ad(err == DB_SUCCESS); } diff --git a/storage/innobase/row/row0vers.c b/storage/innobase/row/row0vers.c index 03d9a2f1203..f4adfa855df 100644 --- a/storage/innobase/row/row0vers.c +++ b/storage/innobase/row/row0vers.c @@ -59,7 +59,9 @@ row_vers_impl_x_locked_off_kernel( trx_t* trx; ulint vers_del; ulint rec_del; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ mtr_t mtr; ulint comp; @@ -152,9 +154,12 @@ row_vers_impl_x_locked_off_kernel( heap2 = heap; heap = mem_heap_create(1024); - err = trx_undo_prev_version_build(clust_rec, &mtr, version, - clust_index, clust_offsets, - heap, &prev_version); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + trx_undo_prev_version_build(clust_rec, &mtr, version, + clust_index, clust_offsets, + heap, &prev_version); mem_heap_free(heap2); /* free version and clust_offsets */ if (prev_version) { diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index f0f300d918e..9e09efc82b2 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -249,9 +249,10 @@ trx_purge_add_update_undo_to_history( trx_undo_t* undo; trx_rseg_t* rseg; trx_rsegf_t* rseg_header; +#ifdef UNIV_DEBUG trx_usegf_t* seg_header; +#endif /* UNIV_DEBUG */ trx_ulogf_t* undo_header; - trx_upagef_t* page_header; ulint hist_size; undo = trx->update_undo; @@ -265,8 +266,9 @@ trx_purge_add_update_undo_to_history( rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr); undo_header = undo_page + undo->hdr_offset; +#ifdef UNIV_DEBUG seg_header = undo_page + TRX_UNDO_SEG_HDR; - page_header = undo_page + TRX_UNDO_PAGE_HDR; +#endif /* UNIV_DEBUG */ if (undo->state != TRX_UNDO_CACHED) { /* The undo log segment will not be reused */ @@ -594,7 +596,6 @@ trx_purge_rseg_get_next_history_log( { page_t* undo_page; trx_ulogf_t* log_hdr; - trx_usegf_t* seg_hdr; fil_addr_t prev_log_addr; dulint trx_no; ibool del_marks; @@ -615,7 +616,6 @@ trx_purge_rseg_get_next_history_log( undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->last_page_no, &mtr); log_hdr = undo_page + rseg->last_offset; - seg_hdr = undo_page + TRX_UNDO_SEG_HDR; /* Increase the purge page count by one for every handled log */ @@ -1004,12 +1004,8 @@ trx_purge_rec_release( /*==================*/ trx_undo_inf_t* cell) /* in: storage cell */ { - trx_undo_arr_t* arr; - mutex_enter(&(purge_sys->mutex)); - arr = purge_sys->arr; - trx_purge_arr_remove_info(cell); mutex_exit(&(purge_sys->mutex)); diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index 8934fe87c7e..285e30796a5 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -713,13 +713,8 @@ trx_undo_arr_remove_info( dulint undo_no)/* in: undo number */ { trx_undo_inf_t* cell; - ulint n_used; - ulint n; ulint i; - n_used = arr->n_used; - n = 0; - for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index f732aca93f5..137771b71ed 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -165,7 +165,9 @@ trx_sys_create_doublewrite_buf(void) { page_t* page; page_t* page2; +#ifdef UNIV_SYNC_DEBUG page_t* new_page; +#endif /* UNIV_SYNC_DEBUG */ byte* doublewrite; byte* fseg_header; ulint page_no; @@ -271,8 +273,11 @@ start_again: the page position in the tablespace, then the page has not been written to in doublewrite. */ - new_page = buf_page_get(TRX_SYS_SPACE, page_no, - RW_X_LATCH, &mtr); +#ifdef UNIV_SYNC_DEBUG + new_page = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(TRX_SYS_SPACE, page_no, + RW_X_LATCH, &mtr); #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(new_page, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 545226a5994..21f75e0818f 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -1827,7 +1827,6 @@ trx_prepare_off_kernel( /*===================*/ trx_t* trx) /* in: transaction */ { - page_t* update_hdr_page; trx_rseg_t* rseg; ibool must_flush_log = FALSE; dulint lsn; @@ -1863,7 +1862,7 @@ trx_prepare_off_kernel( } if (trx->update_undo) { - update_hdr_page = trx_undo_set_state_at_prepare( + trx_undo_set_state_at_prepare( trx, trx->update_undo, &mtr); } diff --git a/storage/innobase/trx/trx0undo.c b/storage/innobase/trx/trx0undo.c index deb6c85e6e3..329565943c8 100644 --- a/storage/innobase/trx/trx0undo.c +++ b/storage/innobase/trx/trx0undo.c @@ -1012,14 +1012,11 @@ trx_undo_truncate_end( ulint last_page_no; trx_undo_rec_t* rec; trx_undo_rec_t* trunc_here; - trx_rseg_t* rseg; mtr_t mtr; ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(mutex_own(&(trx->rseg->mutex))); - rseg = trx->rseg; - for (;;) { mtr_start(&mtr); @@ -1755,21 +1752,11 @@ trx_undo_set_state_at_finish( if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) - < TRX_UNDO_PAGE_REUSE_LIMIT) { + < TRX_UNDO_PAGE_REUSE_LIMIT + && UT_LIST_GET_LEN(rseg->update_undo_list) < 500 + && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - /* This is a heuristic to avoid the problem of all UNDO - slots ending up in one of the UNDO lists. Previously if - the server crashed with all the slots in one of the lists, - transactions that required the slots of a different type - would fail for lack of slots. */ - - if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500 - && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - - state = TRX_UNDO_CACHED; - } else { - state = TRX_UNDO_TO_FREE; - } + state = TRX_UNDO_CACHED; } else if (undo->type == TRX_UNDO_INSERT) { @@ -1798,7 +1785,6 @@ trx_undo_set_state_at_prepare( mtr_t* mtr) /* in: mtr */ { trx_usegf_t* seg_hdr; - trx_upagef_t* page_hdr; trx_ulogf_t* undo_header; page_t* undo_page; ulint offset; @@ -1815,7 +1801,6 @@ trx_undo_set_state_at_prepare( undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr); seg_hdr = undo_page + TRX_UNDO_SEG_HDR; - page_hdr = undo_page + TRX_UNDO_PAGE_HDR; /*------------------------------*/ undo->state = TRX_UNDO_PREPARED; diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 43f87a1baf5..0cd8ac8a7e6 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,7 +1,73 @@ +2010-10-24 The InnoDB Team + + * row/row0mysql.c + Fix Bug #57700 Latching order violation in + row_truncate_table_for_mysql() + +2010-10-20 The InnoDB Team + + * dict/dict0load.c + Fix Bug #57616 Sig 11 in dict_load_table() when failed to load + index or foreign key + +2010-10-19 The InnoDB Team + + * btr/btr0cur.c, buf/buf0buf.c, buf/buf0flu.c, handler/ha_innodb.cc, + ibuf/ibuf0ibuf.c, include/btr0cur.h, include/buf0flu.h, + include/ibuf0ibuf.h, include/row0mysql.h, + row/row0mysql.c, row/row0sel.c, + innodb_bug56680.test, innodb_bug56680.result: + Fix Bug #56680 InnoDB may return wrong results from a + case-insensitive covering index + +2010-10-18 The InnoDB Team + + * handler/ha_innodb.cc, handler/ha_innodb.h, innodb_bug57252.result, + innodb_bug57252.test: + Fix Bug#57252 disabling innobase_stats_on_metadata disables ANALYZE + +2010-10-14 The InnoDB Team + + * handler/ha_innodb.cc, innodb_bug56143.result, innodb_bug56143.test: + Fix Bug#56143 too many foreign keys causes output of show create + table to become invalid + +2010-10-14 The InnoDB Team + + * srv/srv0start.c: + Fix Bug#57397 io_handler_thread() will never cleanup + +2010-10-11 The InnoDB Team + + * row/row0sel.c + Fix Bug #57345 btr_pcur_store_position abort for load with + concurrent lock/unlock tables + +2010-10-11 The InnoDB Team + + * row/row0mysql.c, innodb_bug56947.result, innodb_bug56947.test: + Fix Bug #56947 InnoDB leaks memory when failing to create a table + +2010-10-06 The InnoDB Team + + * row/row0mysql.c, innodb_bug57255.result, innodb_bug57255.test + Fix Bug #57255 Cascade Delete results in "Got error -1 from + storage engine" + +2010-09-27 The InnoDB Team + + * row/row0sel.c, innodb_bug56716.result, innodb_bug56716.test: + Fix Bug#56716 InnoDB locks a record gap without locking the table + +2010-09-06 The InnoDB Team + + * dict/dict0load.c, innodb_bug53756.test innodb_bug53756.result: + Fix Bug#53756 ALTER TABLE ADD PRIMARY KEY affects crash recovery + 2010-08-24 The InnoDB Team * handler/ha_innodb.c, dict/dict0dict.c: - Fix Bug #55832 selects crash too easily when innodb_force_recovery>3 + Fix Bug#55832 selects crash too easily when innodb_force_recovery>3 2010-08-03 The InnoDB Team @@ -19,15 +85,14 @@ 2010-08-03 The InnoDB Team * include/ut0mem.h, ut/ut0mem.c: - Fix Bug #55627 segv in ut_free pars_lexer_close innobase_shutdown + Fix Bug#55627 segv in ut_free pars_lexer_close innobase_shutdown innodb-use-sys-malloc=0 2010-08-01 The InnoDB Team - * handler/ha_innodb.cc - Fix Bug #55382 Assignment with SELECT expressions takes unexpected + * handler/ha_innodb.cc: + Fix Bug#55382 Assignment with SELECT expressions takes unexpected S locks in READ COMMITTED ->>>>>>> MERGE-SOURCE 2010-07-27 The InnoDB Team @@ -48,8 +113,8 @@ 2010-06-29 The InnoDB Team - * btr/btr0cur.c, include/btr0cur.h, - include/row0mysql.h, row/row0merge.c, row/row0sel.c: + * btr/btr0cur.c, include/btr0cur.h, include/row0mysql.h, + row/row0merge.c, row/row0sel.c: Fix Bug#54358 READ UNCOMMITTED access failure of off-page DYNAMIC or COMPRESSED columns diff --git a/storage/innodb_plugin/Makefile.am b/storage/innodb_plugin/Makefile.am index 53b65c3d6ca..846a6acef36 100644 --- a/storage/innodb_plugin/Makefile.am +++ b/storage/innodb_plugin/Makefile.am @@ -338,6 +338,3 @@ ha_innodb_plugin_la_SOURCES= $(libinnobase_la_SOURCES) EXTRA_DIST= CMakeLists.txt plug.in \ pars/make_bison.sh pars/make_flex.sh \ pars/pars0grm.y pars/pars0lex.l - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 02677e0a71c..29cd470e650 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -1895,7 +1895,6 @@ btr_page_split_and_insert( buf_block_t* left_block; buf_block_t* right_block; buf_block_t* insert_block; - page_t* insert_page; page_cur_t* page_cursor; rec_t* first_rec; byte* buf = 0; /* remove warning */ @@ -2153,8 +2152,6 @@ insert_empty: insert_block = right_block; } - insert_page = buf_block_get_frame(insert_block); - /* 7. Reposition the cursor for insert and try insertion */ page_cursor = btr_cur_get_page_cur(cursor); @@ -2166,8 +2163,12 @@ insert_empty: #ifdef UNIV_ZIP_DEBUG { + page_t* insert_page + = buf_block_get_frame(insert_block); + page_zip_des_t* insert_page_zip = buf_block_get_page_zip(insert_block); + ut_a(!insert_page_zip || page_zip_validate(insert_page_zip, insert_page)); } @@ -2560,7 +2561,6 @@ btr_compress( ulint n_recs; ulint max_ins_size; ulint max_ins_size_reorg; - ulint level; block = btr_cur_get_block(cursor); page = btr_cur_get_page(cursor); @@ -2570,7 +2570,6 @@ btr_compress( ut_ad(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)); - level = btr_page_get_level(page, mtr); space = dict_index_get_space(index); zip_size = dict_table_zip_size(index->table); diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 8db12a0bbb8..79fe328a631 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -1626,7 +1626,7 @@ func_exit: See if there is enough place in the page modification log to log an update-in-place. @return TRUE if enough place */ -static +UNIV_INTERN ibool btr_cur_update_alloc_zip( /*=====================*/ @@ -1836,7 +1836,6 @@ btr_cur_optimistic_update( page_t* page; page_zip_des_t* page_zip; rec_t* rec; - rec_t* orig_rec; ulint max_size; ulint new_rec_size; ulint old_rec_size; @@ -1850,7 +1849,7 @@ btr_cur_optimistic_update( block = btr_cur_get_block(cursor); page = buf_block_get_frame(block); - orig_rec = rec = btr_cur_get_rec(cursor); + 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)); @@ -4285,12 +4284,17 @@ btr_free_externally_stored_field( } for (;;) { +#ifdef UNIV_SYNC_DEBUG buf_block_t* rec_block; +#endif /* UNIV_SYNC_DEBUG */ buf_block_t* ext_block; mtr_start(&mtr); - rec_block = buf_page_get(page_get_space_id( +#ifdef UNIV_SYNC_DEBUG + rec_block = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(page_get_space_id( page_align(field_ref)), rec_zip_size, page_get_page_no( diff --git a/storage/innodb_plugin/btr/btr0pcur.c b/storage/innodb_plugin/btr/btr0pcur.c index 658901208ef..056896c7927 100644 --- a/storage/innodb_plugin/btr/btr0pcur.c +++ b/storage/innodb_plugin/btr/btr0pcur.c @@ -452,7 +452,6 @@ btr_pcur_move_backward_from_page( mtr_t* mtr) /*!< in: mtr */ { ulint prev_page_no; - ulint space; page_t* page; buf_block_t* prev_block; ulint latch_mode; @@ -488,7 +487,6 @@ btr_pcur_move_backward_from_page( page = btr_pcur_get_page(cursor); prev_page_no = btr_page_get_prev(page, mtr); - space = buf_block_get_space(btr_pcur_get_block(cursor)); if (prev_page_no == FIL_NULL) { } else if (btr_pcur_is_before_first_on_page(cursor)) { diff --git a/storage/innodb_plugin/btr/btr0sea.c b/storage/innodb_plugin/btr/btr0sea.c index f3ffe07a951..035fdbb61d2 100644 --- a/storage/innodb_plugin/btr/btr0sea.c +++ b/storage/innodb_plugin/btr/btr0sea.c @@ -1495,7 +1495,6 @@ btr_search_update_hash_on_delete( rec_t* rec; ulint fold; dulint index_id; - ibool found; ulint offsets_[REC_OFFS_NORMAL_SIZE]; mem_heap_t* heap = NULL; rec_offs_init(offsets_); @@ -1528,7 +1527,7 @@ btr_search_update_hash_on_delete( } rw_lock_x_lock(&btr_search_latch); - found = ha_search_and_delete_if_found(table, fold, rec); + ha_search_and_delete_if_found(table, fold, rec); rw_lock_x_unlock(&btr_search_latch); } diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c index 660686bac1e..65d4311b840 100644 --- a/storage/innodb_plugin/buf/buf0buf.c +++ b/storage/innodb_plugin/buf/buf0buf.c @@ -2286,6 +2286,30 @@ wait_until_unfixed: bytes. */ UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page); #endif +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + if (mode == BUF_GET_IF_IN_POOL && ibuf_debug) { + /* Try to evict the block from the buffer pool, to use the + insert buffer as much as possible. */ + + if (buf_LRU_free_block(&block->page, TRUE, NULL) + == BUF_LRU_FREED) { + buf_pool_mutex_exit(); + mutex_exit(&block->mutex); + fprintf(stderr, + "innodb_change_buffering_debug evict %u %u\n", + (unsigned) space, (unsigned) offset); + return(NULL); + } else if (buf_flush_page_try(block)) { + fprintf(stderr, + "innodb_change_buffering_debug flush %u %u\n", + (unsigned) space, (unsigned) offset); + guess = block; + goto loop; + } + + /* Failed to evict the page; change it directly */ + } +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ buf_block_buf_fix_inc(block, file, line); diff --git a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c index d8c0497fa1e..2123f8a060d 100644 --- a/storage/innodb_plugin/buf/buf0flu.c +++ b/storage/innodb_plugin/buf/buf0flu.c @@ -128,10 +128,15 @@ buf_flush_delete_from_flush_rbt( buf_page_t* bpage) /*!< in: bpage to be removed. */ { +#ifdef UNIV_DEBUG ibool ret = FALSE; +#endif /* UNIV_DEBUG */ ut_ad(buf_pool_mutex_own()); - ret = rbt_delete(buf_pool->flush_rbt, &bpage); +#ifdef UNIV_DEBUG + ret = +#endif /* UNIV_DEBUG */ + rbt_delete(buf_pool->flush_rbt, &bpage); ut_ad(ret); } @@ -1034,6 +1039,82 @@ buf_flush_write_block_low( } } +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************//** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_page(). +@return TRUE if the page was flushed and the mutexes released */ +UNIV_INTERN +ibool +buf_flush_page_try( +/*===============*/ + buf_block_t* block) /*!< in/out: buffer control block */ +{ + ut_ad(buf_pool_mutex_own()); + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(mutex_own(&block->mutex)); + + if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_LRU)) { + return(FALSE); + } + + if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0 + || buf_pool->init_flush[BUF_FLUSH_LRU]) { + /* There is already a flush batch of the same type running */ + return(FALSE); + } + + buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE; + + buf_page_set_io_fix(&block->page, BUF_IO_WRITE); + + buf_page_set_flush_type(&block->page, BUF_FLUSH_LRU); + + if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) { + + os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + /* VERY IMPORTANT: + Because any thread may call the LRU flush, even when owning + locks on pages, to avoid deadlocks, we must make sure that the + s-lock is acquired on the page without waiting: this is + accomplished because buf_flush_ready_for_flush() must hold, + and that requires the page not to be bufferfixed. */ + + rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE); + + /* Note that the s-latch is acquired before releasing the + buf_pool mutex: this ensures that the latch is acquired + immediately. */ + + mutex_exit(&block->mutex); + buf_pool_mutex_exit(); + + /* Even though block is not protected by any mutex at this + point, it is safe to access block, because it is io_fixed and + oldest_modification != 0. Thus, it cannot be relocated in the + buffer pool or removed from flush_list or LRU_list. */ + + buf_flush_write_block_low(&block->page); + + buf_pool_mutex_enter(); + buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE; + + if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) { + /* The running flush batch has ended */ + os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + buf_pool_mutex_exit(); + buf_flush_buffered_writes(); + + return(TRUE); +} +# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /********************************************************************//** Writes a flushable page asynchronously from the buffer pool to a file. NOTE: in simulated aio we must call @@ -1266,7 +1347,6 @@ buf_flush_batch( { buf_page_t* bpage; ulint page_count = 0; - ulint old_page_count; ulint space; ulint offset; @@ -1338,15 +1418,9 @@ flush_next: buf_pool_mutex_exit(); - old_page_count = page_count; - /* Try to flush also all the neighbors */ page_count += buf_flush_try_neighbors( space, offset, flush_type); - /* fprintf(stderr, - "Flush type %lu, page no %lu, neighb %lu\n", - flush_type, offset, - page_count - old_page_count); */ buf_pool_mutex_enter(); goto flush_next; diff --git a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c index 09353c45c8c..e63f8bc3e6a 100644 --- a/storage/innodb_plugin/dict/dict0crea.c +++ b/storage/innodb_plugin/dict/dict0crea.c @@ -627,7 +627,6 @@ dict_create_index_tree_step( { dict_index_t* index; dict_table_t* sys_indexes; - dict_table_t* table; dtuple_t* search_tuple; ulint zip_size; btr_pcur_t pcur; @@ -636,7 +635,6 @@ dict_create_index_tree_step( ut_ad(mutex_own(&(dict_sys->mutex))); index = node->index; - table = node->table; sys_indexes = dict_sys->sys_indexes; diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 560534345f9..a3575c283cd 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -4441,7 +4441,6 @@ dict_index_print_low( { ib_int64_t n_vals; ulint i; - const char* type_string; ut_ad(mutex_own(&(dict_sys->mutex))); @@ -4456,14 +4455,6 @@ dict_index_print_low( dict_index_stat_mutex_exit(index); - if (dict_index_is_clust(index)) { - type_string = "clustered index"; - } else if (dict_index_is_unique(index)) { - type_string = "unique index"; - } else { - type_string = "secondary index"; - } - fprintf(stderr, " INDEX: name %s, id %lu %lu, fields %lu/%lu," " uniq %lu, type %lu\n" diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c index 3acc267308f..3dcee46b92c 100644 --- a/storage/innodb_plugin/dict/dict0load.c +++ b/storage/innodb_plugin/dict/dict0load.c @@ -1023,13 +1023,13 @@ err_exit: if (err != DB_SUCCESS) { dict_table_remove_from_cache(table); table = NULL; + } else { + table->fk_max_recusive_level = 0; } } else if (!srv_force_recovery) { dict_table_remove_from_cache(table); table = NULL; } - - table->fk_max_recusive_level = 0; #if 0 if (err != DB_SUCCESS && table != NULL) { @@ -1083,6 +1083,8 @@ dict_load_table_on_id( ut_ad(mutex_own(&(dict_sys->mutex))); + table = NULL; + /* NOTE that the operation of this function is protected by the dictionary mutex, and therefore no deadlocks can occur with other dictionary operations. */ @@ -1109,15 +1111,17 @@ dict_load_table_on_id( BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); - if (!btr_pcur_is_on_user_rec(&pcur) - || rec_get_deleted_flag(rec, 0)) { + if (!btr_pcur_is_on_user_rec(&pcur)) { /* Not found */ + goto func_exit; + } - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - - return(NULL); + /* Find the first record that is not delete marked */ + while (rec_get_deleted_flag(rec, 0)) { + if (!btr_pcur_move_to_next_user_rec(&pcur, &mtr)) { + goto func_exit; + } + rec = btr_pcur_get_rec(&pcur); } /*---------------------------------------------------*/ @@ -1130,19 +1134,14 @@ dict_load_table_on_id( /* Check if the table id in record is the one searched for */ if (ut_dulint_cmp(table_id, mach_read_from_8(field)) != 0) { - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - - return(NULL); + goto func_exit; } /* Now we get the table name from the record */ field = rec_get_nth_field_old(rec, 1, &len); /* Load the table definition to memory */ table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len)); - +func_exit: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); diff --git a/storage/innodb_plugin/eval/eval0eval.c b/storage/innodb_plugin/eval/eval0eval.c index 589b0fa1576..dcd416adeee 100644 --- a/storage/innodb_plugin/eval/eval0eval.c +++ b/storage/innodb_plugin/eval/eval0eval.c @@ -384,18 +384,13 @@ eval_notfound( /*==========*/ func_node_t* func_node) /*!< in: function node */ { - que_node_t* arg1; - que_node_t* arg2; sym_node_t* cursor; sel_node_t* sel_node; ibool ibool_val; - arg1 = func_node->args; - arg2 = que_node_get_next(arg1); - ut_ad(func_node->func == PARS_NOTFOUND_TOKEN); - cursor = arg1; + cursor = func_node->args; ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL); diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index a865d2ba3de..9715cb54d2c 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -4432,17 +4432,18 @@ include_field: n_requested_fields++; templ->col_no = i; + templ->clust_rec_field_no = dict_col_get_clust_pos( + &index->table->cols[i], clust_index); + ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED); if (index == clust_index) { - templ->rec_field_no = dict_col_get_clust_pos( - &index->table->cols[i], index); + templ->rec_field_no = templ->clust_rec_field_no; } else { templ->rec_field_no = dict_index_get_nth_col_pos( index, i); - } - - if (templ->rec_field_no == ULINT_UNDEFINED) { - prebuilt->need_to_access_clustered = TRUE; + if (templ->rec_field_no == ULINT_UNDEFINED) { + prebuilt->need_to_access_clustered = TRUE; + } } if (field->null_ptr) { @@ -4494,9 +4495,7 @@ skip_field: for (i = 0; i < n_requested_fields; i++) { templ = prebuilt->mysql_template + i; - templ->rec_field_no = dict_col_get_clust_pos( - &index->table->cols[templ->col_no], - clust_index); + templ->rec_field_no = templ->clust_rec_field_no; } } } @@ -6376,8 +6375,8 @@ create_options_are_valid( ? "COMPRESSED" : "DYNAMIC"; - /* These two ROW_FORMATs require - srv_file_per_table and srv_file_format */ + /* These two ROW_FORMATs require srv_file_per_table + and srv_file_format > Antelope */ if (!srv_file_per_table) { push_warning_printf( thd, @@ -6387,7 +6386,6 @@ create_options_are_valid( " requires innodb_file_per_table.", row_format_name); ret = FALSE; - } if (srv_file_format < DICT_TF_FORMAT_ZIP) { @@ -6586,6 +6584,8 @@ ha_innobase::create( ulint ssize, ksize; ulint key_block_size = create_info->key_block_size; + /* Set 'flags' to the correct key_block_size. + It will be zero if key_block_size is an invalid number.*/ for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX; ssize++, ksize <<= 1) { if (key_block_size == ksize) { @@ -6626,10 +6626,10 @@ ha_innobase::create( row_type = form->s->row_type; if (flags) { - /* KEY_BLOCK_SIZE was specified. */ - if (!(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) { - /* ROW_FORMAT was not specified; - default to ROW_FORMAT=COMPRESSED */ + /* if KEY_BLOCK_SIZE was specified on this statement and + ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/ + if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) + && !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) { row_type = ROW_TYPE_COMPRESSED; } else if (row_type != ROW_TYPE_COMPRESSED) { /* ROW_FORMAT other than COMPRESSED @@ -6648,7 +6648,7 @@ ha_innobase::create( flags = 0; } } else { - /* No KEY_BLOCK_SIZE */ + /* flags == 0 means no KEY_BLOCK_SIZE.*/ if (row_type == ROW_TYPE_COMPRESSED) { /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the @@ -7028,7 +7028,6 @@ innobase_drop_database( ulint len = 0; trx_t* trx; char* ptr; - int error; char* namebuf; THD* thd = current_thd; @@ -7071,7 +7070,7 @@ innobase_drop_database( #else trx = innobase_trx_allocate(thd); #endif - error = row_drop_database_for_mysql(namebuf, trx); + row_drop_database_for_mysql(namebuf, trx); my_free(namebuf, MYF(0)); /* Flush the log to reduce probability that the .frm files and @@ -7524,9 +7523,12 @@ Returns statistics information of the table to the MySQL interpreter, in various fields of the handle object. */ UNIV_INTERN int -ha_innobase::info( -/*==============*/ - uint flag) /*!< in: what information MySQL requests */ +ha_innobase::info_low( +/*==================*/ + uint flag, /*!< in: what information MySQL + requests */ + bool called_from_analyze) /* in: TRUE if called from + ::analyze() */ { dict_table_t* ib_table; dict_index_t* index; @@ -7557,7 +7559,7 @@ ha_innobase::info( ib_table = prebuilt->table; if (flag & HA_STATUS_TIME) { - if (innobase_stats_on_metadata) { + if (called_from_analyze || innobase_stats_on_metadata) { /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ @@ -7805,6 +7807,18 @@ func_exit: DBUG_RETURN(0); } +/*********************************************************************//** +Returns statistics information of the table to the MySQL interpreter, +in various fields of the handle object. */ +UNIV_INTERN +int +ha_innobase::info( +/*==============*/ + uint flag) /*!< in: what information MySQL requests */ +{ + return(info_low(flag, false /* not called from analyze */)); +} + /**********************************************************************//** Updates index cardinalities of the table, based on 8 random dives into each index tree. This does NOT calculate exact statistics on the table. @@ -7817,7 +7831,8 @@ ha_innobase::analyze( HA_CHECK_OPT* check_opt) /*!< in: currently ignored */ { /* Simply call ::info() with all the flags */ - info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, + true /* called from analyze */); return(0); } @@ -8118,8 +8133,6 @@ ha_innobase::get_foreign_key_create_info(void) flen = ftell(srv_dict_tmpfile); if (flen < 0) { flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; } /* allocate buffer for the string, and @@ -8869,12 +8882,9 @@ innodb_show_status( mutex_exit(&srv_monitor_file_mutex); - bool result = FALSE; + stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), + STRING_WITH_LEN(""), str, flen); - if (stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), - STRING_WITH_LEN(""), str, flen)) { - result= TRUE; - } my_free(str, MYF(0)); DBUG_RETURN(FALSE); @@ -9414,7 +9424,11 @@ ha_innobase::innobase_peek_autoinc(void) auto_inc = dict_table_autoinc_read(innodb_table); - ut_a(auto_inc > 0); + if (auto_inc == 0) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: AUTOINC next value generation " + "is disabled for '%s'\n", innodb_table->name); + } dict_table_autoinc_unlock(innodb_table); @@ -10931,6 +10945,13 @@ static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering, innodb_change_buffering_validate, innodb_change_buffering_update, "inserts"); +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, + PLUGIN_VAR_RQCMDARG, + "Debug flags for InnoDB change buffering (0=none)", + NULL, NULL, 0, 0, 1, 0); +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + 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 " @@ -10991,6 +11012,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(version), MYSQL_SYSVAR(use_sys_malloc), MYSQL_SYSVAR(change_buffering), +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + MYSQL_SYSVAR(change_buffering_debug), +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), NULL diff --git a/storage/innodb_plugin/handler/ha_innodb.h b/storage/innodb_plugin/handler/ha_innodb.h index 9789e4ba639..7a8f29853de 100644 --- a/storage/innodb_plugin/handler/ha_innodb.h +++ b/storage/innodb_plugin/handler/ha_innodb.h @@ -109,6 +109,7 @@ class ha_innobase: public handler ulint innobase_update_autoinc(ulonglong auto_inc); void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); + int info_low(uint flag, bool called_from_analyze); /* Init values for the class: */ public: diff --git a/storage/innodb_plugin/handler/i_s.cc b/storage/innodb_plugin/handler/i_s.cc index 524fe696de2..9ad2d656365 100644 --- a/storage/innodb_plugin/handler/i_s.cc +++ b/storage/innodb_plugin/handler/i_s.cc @@ -1012,6 +1012,7 @@ trx_i_s_common_fill_table( deadlock occurs between the mysqld server and mysql client, see http://bugs.mysql.com/29900 ; when that bug is resolved we can enable the DBUG_RETURN(ret) above */ + ret++; // silence a gcc46 warning DBUG_RETURN(0); #endif } diff --git a/storage/innodb_plugin/ibuf/ibuf0ibuf.c b/storage/innodb_plugin/ibuf/ibuf0ibuf.c index 5e9b4b27611..701e8f0ef04 100644 --- a/storage/innodb_plugin/ibuf/ibuf0ibuf.c +++ b/storage/innodb_plugin/ibuf/ibuf0ibuf.c @@ -49,6 +49,7 @@ Created 7/19/1997 Heikki Tuuri #include "btr0cur.h" #include "btr0pcur.h" #include "btr0btr.h" +#include "row0upd.h" #include "sync0sync.h" #include "dict0boot.h" #include "fut0lst.h" @@ -170,6 +171,11 @@ access order rules. */ /** Operations that can currently be buffered. */ UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_INSERT; +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/** Flag to control insert buffer debugging. */ +UNIV_INTERN uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /** The insert buffer control structure */ UNIV_INTERN ibuf_t* ibuf = NULL; @@ -2881,9 +2887,80 @@ During merge, inserts to an index page a secondary index entry extracted from the insert buffer. */ static void +ibuf_insert_to_index_page_low( +/*==========================*/ + const dtuple_t* entry, /*!< in: buffered entry to insert */ + buf_block_t* block, /*!< in/out: index page where the buffered + entry should be placed */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr, /*!< in/out: mtr */ + page_cur_t* page_cur)/*!< in/out: cursor positioned on the record + after which to insert the buffered entry */ +{ + const page_t* page; + ulint space; + ulint page_no; + ulint zip_size; + const page_t* bitmap_page; + ulint old_bits; + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) { + return; + } + + /* If the record did not fit, reorganize */ + + btr_page_reorganize(block, index, mtr); + page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur); + + /* This time the record must fit */ + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) { + return; + } + + page = buf_block_get_frame(block); + + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: Error: Insert buffer insert fails;" + " page free %lu, dtuple size %lu\n", + (ulong) page_get_max_insert_size(page, 1), + (ulong) rec_get_converted_size(index, entry, 0)); + fputs("InnoDB: Cannot insert index record ", stderr); + dtuple_print(stderr, entry); + fputs("\nInnoDB: The table where this index record belongs\n" + "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" + "InnoDB: that table.\n", stderr); + + space = page_get_space_id(page); + zip_size = buf_block_get_zip_size(block); + page_no = page_get_page_no(page); + + bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr); + old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size, + IBUF_BITMAP_FREE, mtr); + + fprintf(stderr, + "InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n", + (ulong) space, (ulong) page_no, + (ulong) zip_size, (ulong) old_bits); + + fputs("InnoDB: Submit a detailed bug report" + " to http://bugs.mysql.com\n", stderr); +} + +/************************************************************************ +During merge, inserts to an index page a secondary index entry extracted +from the insert buffer. */ +static +void ibuf_insert_to_index_page( /*======================*/ - dtuple_t* entry, /*!< in: buffered entry to insert */ + const dtuple_t* entry, /*!< in: buffered entry to insert */ buf_block_t* block, /*!< in/out: index page where the buffered entry should be placed */ dict_index_t* index, /*!< in: record descriptor */ @@ -2893,11 +2970,10 @@ ibuf_insert_to_index_page( ulint low_match; page_t* page = buf_block_get_frame(block); rec_t* rec; - page_t* bitmap_page; - ulint old_bits; ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); + ut_ad(!buf_block_align(page)->is_hashed); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) != (ibool)!!page_is_comp(page))) { @@ -2935,71 +3011,86 @@ dump: low_match = page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur); - if (low_match == dtuple_get_n_fields(entry)) { + if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) { + mem_heap_t* heap; + upd_t* update; + ulint* offsets; page_zip_des_t* page_zip; rec = page_cur_get_rec(&page_cur); - page_zip = buf_block_get_page_zip(block); - btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr); - } else { - rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr); + /* This is based on + row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ + ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - if (UNIV_LIKELY(rec != NULL)) { + heap = mem_heap_create(1024); + + offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, + &heap); + update = row_upd_build_sec_rec_difference_binary( + index, entry, rec, NULL, heap); + + page_zip = buf_block_get_page_zip(block); + + if (update->n_fields == 0) { + /* The records only differ in the delete-mark. + Clear the delete-mark, like we did before + Bug #56680 was fixed. */ + btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr); +updated_in_place: + mem_heap_free(heap); return; } - /* If the record did not fit, reorganize */ - - btr_page_reorganize(block, index, mtr); - page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur); + /* Copy the info bits. Clear the delete-mark. */ + update->info_bits = rec_get_info_bits(rec, page_is_comp(page)); + update->info_bits &= ~REC_INFO_DELETED_FLAG; + + /* We cannot invoke btr_cur_optimistic_update() here, + because we do not have a btr_cur_t or que_thr_t, + as the insert buffer merge occurs at a very low level. */ + if (!row_upd_changes_field_size_or_external(index, offsets, + update) + && (!page_zip || btr_cur_update_alloc_zip( + page_zip, block, index, + rec_offs_size(offsets), FALSE, mtr))) { + /* This is the easy case. Do something similar + to btr_cur_update_in_place(). */ + row_upd_rec_in_place(rec, index, offsets, + update, page_zip); + goto updated_in_place; + } - /* This time the record must fit */ - if (UNIV_UNLIKELY - (!page_cur_tuple_insert(&page_cur, entry, index, - 0, mtr))) { - ulint space; - ulint page_no; - ulint zip_size; + /* A collation may identify values that differ in + storage length. + Some examples (1 or 2 bytes): + utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I + utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S + utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS - ut_print_timestamp(stderr); + latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S - fprintf(stderr, - " InnoDB: Error: Insert buffer insert" - " fails; page free %lu," - " dtuple size %lu\n", - (ulong) page_get_max_insert_size( - page, 1), - (ulong) rec_get_converted_size( - index, entry, 0)); - fputs("InnoDB: Cannot insert index record ", - stderr); - dtuple_print(stderr, entry); - fputs("\nInnoDB: The table where" - " this index record belongs\n" - "InnoDB: is now probably corrupt." - " Please run CHECK TABLE on\n" - "InnoDB: that table.\n", stderr); + Examples of a character (3-byte UTF-8 sequence) + identified with 2 or 4 characters (1-byte UTF-8 sequences): - space = page_get_space_id(page); - zip_size = buf_block_get_zip_size(block); - page_no = page_get_page_no(page); + utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO + utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN + */ - bitmap_page = ibuf_bitmap_get_map_page( - space, page_no, zip_size, mtr); - old_bits = ibuf_bitmap_page_get_bits( - bitmap_page, page_no, zip_size, - IBUF_BITMAP_FREE, mtr); + /* Delete the different-length record, and insert the + buffered one. */ - fprintf(stderr, - "InnoDB: space %lu, page %lu," - " zip_size %lu, bitmap bits %lu\n", - (ulong) space, (ulong) page_no, - (ulong) zip_size, (ulong) old_bits); + lock_rec_store_on_page_infimum(block, rec); + page_cur_delete_rec(&page_cur, index, offsets, mtr); + page_cur_move_to_prev(&page_cur); + mem_heap_free(heap); - fputs("InnoDB: Submit a detailed bug report" - " to http://bugs.mysql.com\n", stderr); - } + ibuf_insert_to_index_page_low(entry, block, index, mtr, + &page_cur); + lock_rec_restore_from_page_infimum(block, rec, block); + } else { + ibuf_insert_to_index_page_low(entry, block, index, mtr, + &page_cur); } } diff --git a/storage/innodb_plugin/include/btr0cur.h b/storage/innodb_plugin/include/btr0cur.h index e151fdcb563..7f6bff11f84 100644 --- a/storage/innodb_plugin/include/btr0cur.h +++ b/storage/innodb_plugin/include/btr0cur.h @@ -242,6 +242,22 @@ btr_cur_pessimistic_insert( que_thr_t* thr, /*!< in: query thread or NULL */ mtr_t* mtr); /*!< in: mtr */ /*************************************************************//** +See if there is enough place in the page modification log to log +an update-in-place. +@return TRUE if enough place */ +UNIV_INTERN +ibool +btr_cur_update_alloc_zip( +/*=====================*/ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + buf_block_t* block, /*!< in/out: buffer page */ + dict_index_t* index, /*!< in: the index corresponding to the block */ + ulint length, /*!< in: size needed */ + ibool create, /*!< in: TRUE=delete-and-insert, + FALSE=update-in-place */ + mtr_t* mtr) /*!< in: mini-transaction */ + __attribute__((nonnull, warn_unused_result)); +/*************************************************************//** Updates a record when the update causes no size changes in its fields. @return DB_SUCCESS or error number */ UNIV_INTERN diff --git a/storage/innodb_plugin/include/buf0flu.h b/storage/innodb_plugin/include/buf0flu.h index c996f6eaab4..cb8c49fde15 100644 --- a/storage/innodb_plugin/include/buf0flu.h +++ b/storage/innodb_plugin/include/buf0flu.h @@ -75,6 +75,20 @@ buf_flush_init_for_writing( ib_uint64_t newest_lsn); /*!< in: newest modification lsn to the page */ #ifndef UNIV_HOTBACKUP +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************//** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_page(). +@return TRUE if the page was flushed and the mutexes released */ +UNIV_INTERN +ibool +buf_flush_page_try( +/*===============*/ + buf_block_t* block) /*!< in/out: buffer control block */ + __attribute__((nonnull, warn_unused_result)); +# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ /*******************************************************************//** This utility flushes dirty blocks from the end of the LRU list or flush_list. NOTE 1: in the case of an LRU flush the calling thread may own latches to diff --git a/storage/innodb_plugin/include/ibuf0ibuf.h b/storage/innodb_plugin/include/ibuf0ibuf.h index 8aa21fb9d95..f8cc4471d43 100644 --- a/storage/innodb_plugin/include/ibuf0ibuf.h +++ b/storage/innodb_plugin/include/ibuf0ibuf.h @@ -48,6 +48,11 @@ typedef enum { /** Operations that can currently be buffered. */ extern ibuf_use_t ibuf_use; +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/** Flag to control insert buffer debugging. */ +extern uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /** The insert buffer control structure */ extern ibuf_t* ibuf; diff --git a/storage/innodb_plugin/include/os0sync.h b/storage/innodb_plugin/include/os0sync.h index 0c22162b900..f32e7ab710a 100644 --- a/storage/innodb_plugin/include/os0sync.h +++ b/storage/innodb_plugin/include/os0sync.h @@ -330,7 +330,7 @@ amount of increment. */ Returns the old value of *ptr, atomically sets *ptr to new_val */ # define os_atomic_test_and_set_byte(ptr, new_val) \ - __sync_lock_test_and_set(ptr, new_val) + __sync_lock_test_and_set(ptr, (byte) new_val) #elif defined(HAVE_IB_SOLARIS_ATOMICS) diff --git a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h index b69e657361b..42182cc0044 100644 --- a/storage/innodb_plugin/include/row0mysql.h +++ b/storage/innodb_plugin/include/row0mysql.h @@ -527,6 +527,10 @@ struct mysql_row_templ_struct { Innobase record in the current index; not defined if template_type is ROW_MYSQL_WHOLE_ROW */ + ulint clust_rec_field_no; /*!< field number of the column in an + Innobase record in the clustered index; + not defined if template_type is + ROW_MYSQL_WHOLE_ROW */ ulint mysql_col_offset; /*!< offset of the column in the MySQL row format */ ulint mysql_col_len; /*!< length of the column in the MySQL diff --git a/storage/innodb_plugin/include/row0upd.h b/storage/innodb_plugin/include/row0upd.h index 635d746d5a1..4e2de9bd2ec 100644 --- a/storage/innodb_plugin/include/row0upd.h +++ b/storage/innodb_plugin/include/row0upd.h @@ -167,8 +167,11 @@ row_upd_changes_field_size_or_external( const upd_t* update);/*!< in: update vector */ #endif /* !UNIV_HOTBACKUP */ /***********************************************************//** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ UNIV_INTERN void row_upd_rec_in_place( diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 627b65cf849..0bb4b744d05 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 12 +#define INNODB_VERSION_BUGFIX 13 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/innodb_plugin/include/ut0rnd.ic b/storage/innodb_plugin/include/ut0rnd.ic index c3dbd86923c..a33813037ea 100644 --- a/storage/innodb_plugin/include/ut0rnd.ic +++ b/storage/innodb_plugin/include/ut0rnd.ic @@ -85,9 +85,6 @@ ut_rnd_gen_ulint(void) /*==================*/ { ulint rnd; - ulint n_bits; - - n_bits = 8 * sizeof(ulint); ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; diff --git a/storage/innodb_plugin/log/log0recv.c b/storage/innodb_plugin/log/log0recv.c index a727d6be768..c1d12dad413 100644 --- a/storage/innodb_plugin/log/log0recv.c +++ b/storage/innodb_plugin/log/log0recv.c @@ -559,10 +559,8 @@ recv_synchronize_groups( ib_uint64_t start_lsn; ib_uint64_t end_lsn; ib_uint64_t recovered_lsn; - ib_uint64_t limit_lsn; recovered_lsn = recv_sys->recovered_lsn; - limit_lsn = recv_sys->limit_lsn; /* Read the last recovered log block to the recovery system buffer: the block is always incomplete */ @@ -2891,7 +2889,9 @@ recv_recovery_from_checkpoint_start_func( ib_uint64_t old_scanned_lsn; ib_uint64_t group_scanned_lsn; ib_uint64_t contiguous_lsn; +#ifdef UNIV_LOG_ARCHIVE ib_uint64_t archived_lsn; +#endif /* UNIV_LOG_ARCHIVE */ byte* buf; byte log_hdr_buf[LOG_FILE_HDR_SIZE]; ulint err; @@ -2946,7 +2946,9 @@ recv_recovery_from_checkpoint_start_func( checkpoint_lsn = mach_read_ull(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_ull(buf + LOG_CHECKPOINT_NO); +#ifdef UNIV_LOG_ARCHIVE archived_lsn = mach_read_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN); +#endif /* UNIV_LOG_ARCHIVE */ /* Read the first log file header to print a note if this is a recovery from a restored InnoDB Hot Backup */ diff --git a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c index 9f937b9def2..ff80f7ed1b4 100644 --- a/storage/innodb_plugin/os/os0file.c +++ b/storage/innodb_plugin/os/os0file.c @@ -1182,10 +1182,12 @@ UNIV_INTERN void os_file_set_nocache( /*================*/ - int fd, /*!< in: file descriptor to alter */ - const char* file_name, /*!< in: file name, used in the - diagnostic message */ - const char* operation_name) /*!< in: "open" or "create"; used in the + int fd /*!< in: file descriptor to alter */ + __attribute__((unused)), + const char* file_name /*!< in: used in the diagnostic message */ + __attribute__((unused)), + const char* operation_name __attribute__((unused))) + /*!< in: "open" or "create"; used in the diagnostic message */ { /* some versions of Solaris may not have DIRECTIO_ON */ @@ -1367,8 +1369,6 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; - const char* type_str = NULL; - const char* purpose_str = NULL; try_again: ut_a(name); @@ -1388,26 +1388,9 @@ try_again: ut_error; } - if (type == OS_LOG_FILE) { - type_str = "LOG"; - } else if (type == OS_DATA_FILE) { - type_str = "DATA"; - } else { - ut_error; - } - - if (purpose == OS_FILE_AIO) { - purpose_str = "AIO"; - } else if (purpose == OS_FILE_NORMAL) { - purpose_str = "NORMAL"; - } else { - ut_error; - } + ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); + ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL); -#if 0 - fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n", - name, mode_str, type_str, purpose_str); -#endif #ifdef O_SYNC /* We let O_SYNC only affect log files; note that we map O_DSYNC to O_SYNC because the datasync options seemed to corrupt files in 2001 @@ -2297,7 +2280,10 @@ os_file_read( ulint i; #endif /* !UNIV_HOTBACKUP */ + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2421,7 +2407,10 @@ os_file_read_no_error_handling( ulint i; #endif /* !UNIV_HOTBACKUP */ + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2551,7 +2540,10 @@ os_file_write( ulint i; #endif /* !UNIV_HOTBACKUP */ - ut_a((offset & 0xFFFFFFFF) == offset); + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ + ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_writes++; @@ -3321,12 +3313,14 @@ os_aio_array_reserve_slot( ulint len) /*!< in: length of the block to read or write */ { os_aio_slot_t* slot; -#ifdef WIN_ASYNC_IO - OVERLAPPED* control; -#endif ulint i; ulint slots_per_seg; ulint local_seg; +#ifdef WIN_ASYNC_IO + OVERLAPPED* control; + + ut_a((len & 0xFFFFFFFFUL) == len); +#endif /* No need of a mutex. Only reading constant fields */ slots_per_seg = array->n_slots / array->n_segments; @@ -3606,6 +3600,9 @@ os_aio( ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(os_aio_validate()); +#ifdef WIN_ASYNC_IO + ut_ad((n & 0xFFFFFFFFUL) == n); +#endif wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); @@ -3846,16 +3843,18 @@ os_aio_windows_handle( /* retry failed read/write operation synchronously. No need to hold array->mutex. */ + ut_a((slot->len & 0xFFFFFFFFUL) == slot->len); + switch (slot->type) { case OS_FILE_WRITE: ret = WriteFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; case OS_FILE_READ: ret = ReadFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; diff --git a/storage/innodb_plugin/plug.in b/storage/innodb_plugin/plug.in index 38e14d9d2fd..c99703415f9 100644 --- a/storage/innodb_plugin/plug.in +++ b/storage/innodb_plugin/plug.in @@ -137,10 +137,11 @@ MYSQL_PLUGIN_ACTIONS(innodb_plugin, [ AC_MSG_CHECKING(whether Solaris libc atomic functions are available) # either define HAVE_IB_SOLARIS_ATOMICS or not - AC_CHECK_FUNCS(atomic_add_long \ + AC_CHECK_FUNCS(atomic_cas_ulong \ atomic_cas_32 \ atomic_cas_64 \ - atomic_cas_ulong, + atomic_add_long_nv \ + atomic_swap_uchar, AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1], [Define to 1 if Solaris libc atomic functions \ diff --git a/storage/innodb_plugin/que/que0que.c b/storage/innodb_plugin/que/que0que.c index 2fe046fa9b8..b616b3d9c14 100644 --- a/storage/innodb_plugin/que/que0que.c +++ b/storage/innodb_plugin/que/que0que.c @@ -1284,18 +1284,13 @@ que_run_threads_low( que_thr_t* thr) /*!< in: query thread */ { que_thr_t* next_thr; - ulint cumul_resource; ulint loop_count; ut_ad(thr->state == QUE_THR_RUNNING); ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS); ut_ad(!mutex_own(&kernel_mutex)); - /* cumul_resource counts how much resources the OS thread (NOT the - query thread) has spent in this function */ - loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; - cumul_resource = 0; loop: /* Check that there is enough space in the log to accommodate possible log entries by this query step; if the operation can touch diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 9d7cb976caf..9e8d0a884f4 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -444,7 +444,7 @@ row_mysql_convert_row_to_innobase( row is used, as row may contain pointers to this record! */ { - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; dfield_t* dfield; ulint i; @@ -1433,7 +1433,12 @@ run_again: srv_n_rows_updated++; } - row_update_statistics_if_needed(prebuilt->table); + /* We update table statistics only if it is a DELETE or UPDATE + 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)) { + row_update_statistics_if_needed(prebuilt->table); + } trx->op_info = ""; @@ -1588,6 +1593,9 @@ row_update_cascade_for_mysql( trx = thr_get_trx(thr); + /* Increment fk_cascade_depth to record the recursive call depth on + a single update/delete that affects multiple tables chained + together with foreign key relations. */ thr->fk_cascade_depth++; if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) { @@ -1599,6 +1607,12 @@ run_again: row_upd_step(thr); + /* The recursive call for cascading update/delete happens + in above row_upd_step(), reset the counter once we come + out of the recursive call, so it does not accumulate for + different row deletes */ + thr->fk_cascade_depth = 0; + err = trx->error_state; /* Note that the cascade node is a subnode of another InnoDB @@ -1865,15 +1879,13 @@ err_exit: err = trx->error_state; - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + switch (err) { + case DB_SUCCESS: + break; + case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); - /* TO DO: free table? The code below will dereference - table->name, though. */ - } - switch (err) { - case DB_OUT_OF_FILE_SPACE: ut_print_timestamp(stderr); fputs(" InnoDB: Warning: cannot create table ", stderr); @@ -1888,9 +1900,13 @@ err_exit: break; case DB_DUPLICATE_KEY: + default: /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, NULL); + dict_mem_table_free(table); break; } @@ -2766,15 +2782,6 @@ row_truncate_table_for_mysql( trx->table_id = table->id; - /* Lock all index trees for this table, as we will - truncate the table/index and possibly change their metadata. - All DML/DDL are blocked by table level lock, with - a few exceptions such as queries into information schema - about the table, MySQL could try to access index stats - for this kind of query, we need to use index locks to - sync up */ - dict_table_x_lock_indexes(table); - if (table->space && !table->dir_path_of_temp_table) { /* Discard and create the single-table tablespace. */ ulint space = table->space; @@ -2787,6 +2794,11 @@ row_truncate_table_for_mysql( dict_hdr_get_new_id(NULL, NULL, &space); + /* Lock all index trees for this table. We must + do so after dict_hdr_get_new_id() to preserve + the latch order */ + dict_table_x_lock_indexes(table); + if (space == ULINT_UNDEFINED || fil_create_new_single_table_tablespace( space, table->name, FALSE, flags, @@ -2820,6 +2832,15 @@ row_truncate_table_for_mysql( FIL_IBD_FILE_INITIAL_SIZE, &mtr); mtr_commit(&mtr); } + } else { + /* Lock all index trees for this table, as we will + truncate the table/index and possibly change their metadata. + All DML/DDL are blocked by table level lock, with + a few exceptions such as queries into information schema + about the table, MySQL could try to access index stats + for this kind of query, we need to use index locks to + sync up */ + dict_table_x_lock_indexes(table); } /* scan SYS_INDEXES for all indexes of the table */ diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c index 835af990672..31b255cf2d4 100644 --- a/storage/innodb_plugin/row/row0purge.c +++ b/storage/innodb_plugin/row/row0purge.c @@ -684,7 +684,9 @@ row_purge_step( que_thr_t* thr) /*!< in: query thread */ { purge_node_t* node; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ ut_ad(thr); @@ -692,7 +694,10 @@ row_purge_step( ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); - err = row_purge(node, thr); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + row_purge(node, thr); ut_ad(err == DB_SUCCESS); diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index aff36b65124..ac78a95839c 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -2675,39 +2675,39 @@ row_sel_store_mysql_rec( row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ const rec_t* rec, /*!< in: Innobase record in the index which was described in prebuilt's - template; must be protected by - a page latch */ + template, or in the clustered index; + must be protected by a page latch */ + ibool rec_clust, /*!< in: TRUE if rec is in the + clustered index instead of + prebuilt->index */ const ulint* offsets) /*!< in: array returned by - rec_get_offsets() */ + rec_get_offsets(rec) */ { - mysql_row_templ_t* templ; - mem_heap_t* extern_field_heap = NULL; - mem_heap_t* heap; - const byte* data; - ulint len; - ulint i; + mem_heap_t* extern_field_heap = NULL; + mem_heap_t* heap; + ulint i; ut_ad(prebuilt->mysql_template); ut_ad(prebuilt->default_rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) { mem_heap_free(prebuilt->blob_heap); prebuilt->blob_heap = NULL; } - /* init null bytes with default values as they might be - left uninitialized in some cases and these uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); - for (i = 0; i < prebuilt->n_template; i++) { - templ = prebuilt->mysql_template + i; + const mysql_row_templ_t*templ = prebuilt->mysql_template + i; + const byte* data; + ulint len; + ulint field_no; + + field_no = rec_clust + ? templ->clust_rec_field_no : templ->rec_field_no; - if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, - templ->rec_field_no))) { + if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) { /* Copy an externally stored field to the temporary heap */ @@ -2735,7 +2735,7 @@ row_sel_store_mysql_rec( data = btr_rec_copy_externally_stored_field( rec, offsets, dict_table_zip_size(prebuilt->table), - templ->rec_field_no, &len, heap); + field_no, &len, heap); if (UNIV_UNLIKELY(!data)) { /* The externally stored field @@ -2756,8 +2756,7 @@ row_sel_store_mysql_rec( } else { /* Field is stored in the row. */ - data = rec_get_nth_field(rec, offsets, - templ->rec_field_no, &len); + data = rec_get_nth_field(rec, offsets, field_no, &len); if (UNIV_UNLIKELY(templ->type == DATA_BLOB) && len != UNIV_SQL_NULL) { @@ -3119,7 +3118,7 @@ row_sel_pop_cached_row_for_mysql( row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */ { ulint i; - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); @@ -3176,15 +3175,21 @@ ibool row_sel_push_cache_row_for_mysql( /*=============================*/ row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ - const rec_t* rec, /*!< in: record to push; must - be protected by a page latch */ - const ulint* offsets) /*!< in: rec_get_offsets() */ + const rec_t* rec, /*!< in: record to push, in the index + which was described in prebuilt's + template, or in the clustered index; + must be protected by a page latch */ + ibool rec_clust, /*!< in: TRUE if rec is in the + clustered index instead of + prebuilt->index */ + const ulint* offsets) /*!< in: rec_get_offsets(rec) */ { byte* buf; ulint i; ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); ut_a(!prebuilt->templ_contains_blob); if (prebuilt->fetch_cache[0] == NULL) { @@ -3213,7 +3218,7 @@ row_sel_push_cache_row_for_mysql( if (UNIV_UNLIKELY(!row_sel_store_mysql_rec( prebuilt->fetch_cache[ prebuilt->n_fetch_cached], - prebuilt, rec, offsets))) { + prebuilt, rec, rec_clust, offsets))) { return(FALSE); } @@ -3356,6 +3361,7 @@ row_search_for_mysql( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; + ibool table_lock_waited = FALSE; rec_offs_init(offsets_); @@ -3613,7 +3619,8 @@ row_search_for_mysql( ut_ad(!rec_get_deleted_flag(rec, comp)); if (!row_sel_store_mysql_rec(buf, prebuilt, - rec, offsets)) { + rec, FALSE, + offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -3719,6 +3726,44 @@ release_search_latch_if_needed: clust_index = dict_table_get_first_index(index->table); + /* Do some start-of-statement preparations */ + + if (!prebuilt->sql_stat_start) { + /* No need to set an intention lock or assign a read view */ + + if (trx->read_view == NULL + && prebuilt->select_lock_type == LOCK_NONE) { + + fputs("InnoDB: Error: MySQL is trying to" + " perform a consistent read\n" + "InnoDB: but the read view is not assigned!\n", + stderr); + trx_print(stderr, trx, 600); + fputc('\n', stderr); + ut_error; + } + } else if (prebuilt->select_lock_type == LOCK_NONE) { + /* This is a consistent read */ + /* Assign a read view for the query */ + + trx_assign_read_view(trx); + prebuilt->sql_stat_start = FALSE; + } else { +wait_table_again: + err = lock_table(0, index->table, + prebuilt->select_lock_type == LOCK_S + ? LOCK_IS : LOCK_IX, thr); + + if (err != DB_SUCCESS) { + + table_lock_waited = TRUE; + goto lock_table_wait; + } + prebuilt->sql_stat_start = FALSE; + } + + /* Open or restore index cursor position */ + if (UNIV_LIKELY(direction != 0)) { ibool need_to_process = sel_restore_position_for_mysql( &same_user_rec, BTR_SEARCH_LEAF, @@ -3794,42 +3839,6 @@ release_search_latch_if_needed: } } - if (!prebuilt->sql_stat_start) { - /* No need to set an intention lock or assign a read view */ - - if (trx->read_view == NULL - && prebuilt->select_lock_type == LOCK_NONE) { - - fputs("InnoDB: Error: MySQL is trying to" - " perform a consistent read\n" - "InnoDB: but the read view is not assigned!\n", - stderr); - trx_print(stderr, trx, 600); - fputc('\n', stderr); - ut_a(0); - } - } else if (prebuilt->select_lock_type == LOCK_NONE) { - /* This is a consistent read */ - /* Assign a read view for the query */ - - trx_assign_read_view(trx); - prebuilt->sql_stat_start = FALSE; - } else { - ulint lock_mode; - if (prebuilt->select_lock_type == LOCK_S) { - lock_mode = LOCK_IS; - } else { - lock_mode = LOCK_IX; - } - err = lock_table(0, index->table, lock_mode, thr); - - if (err != DB_SUCCESS) { - - goto lock_wait_or_error; - } - prebuilt->sql_stat_start = FALSE; - } - rec_loop: /*-------------------------------------------------------------*/ /* PHASE 4: Look for matching records in a loop */ @@ -4245,7 +4254,6 @@ no_gap_lock: is necessary, because we can only get the undo information via the clustered index record. */ - ut_ad(index != clust_index); ut_ad(!dict_index_is_clust(index)); if (!lock_sec_rec_cons_read_sees( @@ -4361,26 +4369,10 @@ requires_clust_rec: goto next_rec; } - if (prebuilt->need_to_access_clustered) { - - result_rec = clust_rec; - - ut_ad(rec_offs_validate(result_rec, clust_index, - offsets)); - } else { - /* We used 'offsets' for the clust rec, recalculate - them for 'rec' */ - offsets = rec_get_offsets(rec, index, offsets, - ULINT_UNDEFINED, &heap); - result_rec = rec; - } - - /* result_rec can legitimately be delete-marked - now that it has been established that it points to a - clustered index record that exists in the read view. */ + result_rec = clust_rec; + ut_ad(rec_offs_validate(result_rec, clust_index, offsets)); } else { result_rec = rec; - ut_ad(!rec_get_deleted_flag(rec, comp)); } /* We found a qualifying record 'result_rec'. At this point, @@ -4389,6 +4381,7 @@ requires_clust_rec: ut_ad(rec_offs_validate(result_rec, result_rec != rec ? clust_index : index, offsets)); + ut_ad(!rec_get_deleted_flag(result_rec, comp)); /* At this point, the clustered index record is protected by a page latch that was acquired when pcur was positioned. @@ -4413,6 +4406,7 @@ requires_clust_rec: cursor. */ if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec, + result_rec != rec, offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -4430,15 +4424,31 @@ requires_clust_rec: goto next_rec; } else { - if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) { + if (UNIV_UNLIKELY + (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) { + /* CHECK TABLE: fetch the row */ + + if (result_rec != rec + && !prebuilt->need_to_access_clustered) { + /* We used 'offsets' for the clust + rec, recalculate them for 'rec' */ + offsets = rec_get_offsets(rec, index, offsets, + ULINT_UNDEFINED, + &heap); + result_rec = rec; + } + memcpy(buf + 4, result_rec - rec_offs_extra_size(offsets), rec_offs_size(offsets)); mach_write_to_4(buf, rec_offs_extra_size(offsets) + 4); } else { - if (!row_sel_store_mysql_rec(buf, prebuilt, - result_rec, offsets)) { + /* Returning a row to MySQL */ + + if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec, + result_rec != rec, + offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such records do @@ -4559,6 +4569,7 @@ lock_wait_or_error: btr_pcur_store_position(pcur, &mtr); +lock_table_wait: mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; @@ -4576,6 +4587,14 @@ lock_wait_or_error: thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); + /* Table lock waited, go try to obtain table lock + again */ + if (table_lock_waited) { + table_lock_waited = FALSE; + + goto wait_table_again; + } + sel_restore_position_for_mysql(&same_user_rec, BTR_SEARCH_LEAF, pcur, moves_up, &mtr); diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index 8464b0f95cc..5998dadd16d 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -114,12 +114,17 @@ row_undo_mod_clust_low( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; +#ifdef UNIV_DEBUG ibool success; +#endif /* UNIV_DEBUG */ pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); - success = btr_pcur_restore_position(mode, pcur, mtr); +#ifdef UNIV_DEBUG + success = +#endif /* UNIV_DEBUG */ + btr_pcur_restore_position(mode, pcur, mtr); ut_ad(success); diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c index 04c3139fcc7..444003ba3f0 100644 --- a/storage/innodb_plugin/row/row0upd.c +++ b/storage/innodb_plugin/row/row0upd.c @@ -466,8 +466,11 @@ row_upd_changes_field_size_or_external( #endif /* !UNIV_HOTBACKUP */ /***********************************************************//** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ UNIV_INTERN void row_upd_rec_in_place( diff --git a/storage/innodb_plugin/row/row0vers.c b/storage/innodb_plugin/row/row0vers.c index a4fbb5289aa..b6d35363f08 100644 --- a/storage/innodb_plugin/row/row0vers.c +++ b/storage/innodb_plugin/row/row0vers.c @@ -71,7 +71,9 @@ row_vers_impl_x_locked_off_kernel( warning */ trx_t* trx; ulint rec_del; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ mtr_t mtr; ulint comp; @@ -169,9 +171,12 @@ row_vers_impl_x_locked_off_kernel( heap2 = heap; heap = mem_heap_create(1024); - err = trx_undo_prev_version_build(clust_rec, &mtr, version, - clust_index, clust_offsets, - heap, &prev_version); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + trx_undo_prev_version_build(clust_rec, &mtr, version, + clust_index, clust_offsets, + heap, &prev_version); mem_heap_free(heap2); /* free version and clust_offsets */ if (prev_version == NULL) { diff --git a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c index ba9fc831b39..f823b72fbc1 100644 --- a/storage/innodb_plugin/srv/srv0start.c +++ b/storage/innodb_plugin/srv/srv0start.c @@ -463,7 +463,6 @@ io_handler_thread( the aio array */ { ulint segment; - ulint i; segment = *((ulint*)arg); @@ -471,7 +470,7 @@ io_handler_thread( fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment, os_thread_pf(os_thread_get_curr_id())); #endif - for (i = 0;; i++) { + while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { fil_aio_wait(segment); mutex_enter(&ios_mutex); @@ -479,8 +478,6 @@ io_handler_thread( mutex_exit(&ios_mutex); } - thr_local_free(os_thread_get_curr_id()); - /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an @@ -1894,7 +1891,7 @@ innobase_shutdown_for_mysql(void) #ifdef __NETWARE__ if (!panic_shutdown) #endif - logs_empty_and_mark_files_at_shutdown(); + logs_empty_and_mark_files_at_shutdown(); if (srv_conc_n_threads != 0) { fprintf(stderr, diff --git a/storage/innodb_plugin/trx/trx0purge.c b/storage/innodb_plugin/trx/trx0purge.c index abbfa3d7f81..1a70750083a 100644 --- a/storage/innodb_plugin/trx/trx0purge.c +++ b/storage/innodb_plugin/trx/trx0purge.c @@ -304,9 +304,10 @@ trx_purge_add_update_undo_to_history( trx_undo_t* undo; trx_rseg_t* rseg; trx_rsegf_t* rseg_header; +#ifdef UNIV_DEBUG trx_usegf_t* seg_header; +#endif /* UNIV_DEBUG */ trx_ulogf_t* undo_header; - trx_upagef_t* page_header; ulint hist_size; undo = trx->update_undo; @@ -321,8 +322,9 @@ trx_purge_add_update_undo_to_history( rseg->page_no, mtr); undo_header = undo_page + undo->hdr_offset; +#ifdef UNIV_DEBUG seg_header = undo_page + TRX_UNDO_SEG_HDR; - page_header = undo_page + TRX_UNDO_PAGE_HDR; +#endif /* UNIV_DEBUG */ if (undo->state != TRX_UNDO_CACHED) { /* The undo log segment will not be reused */ @@ -655,7 +657,6 @@ trx_purge_rseg_get_next_history_log( { page_t* undo_page; trx_ulogf_t* log_hdr; - trx_usegf_t* seg_hdr; fil_addr_t prev_log_addr; trx_id_t trx_no; ibool del_marks; @@ -676,7 +677,6 @@ trx_purge_rseg_get_next_history_log( undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->zip_size, rseg->last_page_no, &mtr); log_hdr = undo_page + rseg->last_offset; - seg_hdr = undo_page + TRX_UNDO_SEG_HDR; /* Increase the purge page count by one for every handled log */ @@ -1068,12 +1068,8 @@ trx_purge_rec_release( /*==================*/ trx_undo_inf_t* cell) /*!< in: storage cell */ { - trx_undo_arr_t* arr; - mutex_enter(&(purge_sys->mutex)); - arr = purge_sys->arr; - trx_purge_arr_remove_info(cell); mutex_exit(&(purge_sys->mutex)); diff --git a/storage/innodb_plugin/trx/trx0roll.c b/storage/innodb_plugin/trx/trx0roll.c index c925478cdf4..1a43e419214 100644 --- a/storage/innodb_plugin/trx/trx0roll.c +++ b/storage/innodb_plugin/trx/trx0roll.c @@ -740,13 +740,8 @@ trx_undo_arr_remove_info( undo_no_t undo_no)/*!< in: undo number */ { trx_undo_inf_t* cell; - ulint n_used; - ulint n; ulint i; - n_used = arr->n_used; - n = 0; - for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); diff --git a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c index 410c55f132d..6eb356947cc 100644 --- a/storage/innodb_plugin/trx/trx0sys.c +++ b/storage/innodb_plugin/trx/trx0sys.c @@ -241,7 +241,9 @@ trx_sys_create_doublewrite_buf(void) { buf_block_t* block; buf_block_t* block2; +#ifdef UNIV_SYNC_DEBUG buf_block_t* new_block; +#endif /* UNIV_SYNC_DEBUG */ byte* doublewrite; byte* fseg_header; ulint page_no; @@ -344,8 +346,11 @@ start_again: the page position in the tablespace, then the page has not been written to in doublewrite. */ - new_block = buf_page_get(TRX_SYS_SPACE, 0, page_no, - RW_X_LATCH, &mtr); +#ifdef UNIV_SYNC_DEBUG + new_block = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(TRX_SYS_SPACE, 0, page_no, + RW_X_LATCH, &mtr); buf_block_dbg_add_level(new_block, SYNC_NO_ORDER_CHECK); diff --git a/storage/innodb_plugin/trx/trx0trx.c b/storage/innodb_plugin/trx/trx0trx.c index 9722bb59a5e..ee744fd58b1 100644 --- a/storage/innodb_plugin/trx/trx0trx.c +++ b/storage/innodb_plugin/trx/trx0trx.c @@ -1805,7 +1805,6 @@ trx_prepare_off_kernel( /*===================*/ trx_t* trx) /*!< in: transaction */ { - page_t* update_hdr_page; trx_rseg_t* rseg; ib_uint64_t lsn = 0; mtr_t mtr; @@ -1838,7 +1837,7 @@ trx_prepare_off_kernel( } if (trx->update_undo) { - update_hdr_page = trx_undo_set_state_at_prepare( + trx_undo_set_state_at_prepare( trx, trx->update_undo, &mtr); } diff --git a/storage/innodb_plugin/trx/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c index eb5112c4d31..76e88948e41 100644 --- a/storage/innodb_plugin/trx/trx0undo.c +++ b/storage/innodb_plugin/trx/trx0undo.c @@ -1066,14 +1066,11 @@ trx_undo_truncate_end( ulint last_page_no; trx_undo_rec_t* rec; trx_undo_rec_t* trunc_here; - trx_rseg_t* rseg; mtr_t mtr; ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(mutex_own(&(trx->rseg->mutex))); - rseg = trx->rseg; - for (;;) { mtr_start(&mtr); @@ -1826,21 +1823,11 @@ trx_undo_set_state_at_finish( if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) - < TRX_UNDO_PAGE_REUSE_LIMIT) { + < TRX_UNDO_PAGE_REUSE_LIMIT + && UT_LIST_GET_LEN(rseg->update_undo_list) < 500 + && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - /* This is a heuristic to avoid the problem of all UNDO - slots ending up in one of the UNDO lists. Previously if - the server crashed with all the slots in one of the lists, - transactions that required the slots of a different type - would fail for lack of slots. */ - - if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500 - && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - - state = TRX_UNDO_CACHED; - } else { - state = TRX_UNDO_TO_FREE; - } + state = TRX_UNDO_CACHED; } else if (undo->type == TRX_UNDO_INSERT) { @@ -1868,7 +1855,6 @@ trx_undo_set_state_at_prepare( mtr_t* mtr) /*!< in: mtr */ { trx_usegf_t* seg_hdr; - trx_upagef_t* page_hdr; trx_ulogf_t* undo_header; page_t* undo_page; ulint offset; @@ -1886,7 +1872,6 @@ trx_undo_set_state_at_prepare( undo->hdr_page_no, mtr); seg_hdr = undo_page + TRX_UNDO_SEG_HDR; - page_hdr = undo_page + TRX_UNDO_PAGE_HDR; /*------------------------------*/ undo->state = TRX_UNDO_PREPARED; diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am index 0569efa91b8..c2bb61e77dd 100644 --- a/storage/maria/Makefile.am +++ b/storage/maria/Makefile.am @@ -212,6 +212,3 @@ test: test-verbose: HARNESS_VERBOSE=1 perl $(top_srcdir)/unittest/unit.pl run $(unittests) - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/maria/unittest/Makefile.am b/storage/maria/unittest/Makefile.am index b5bc8587066..557e14b0515 100644 --- a/storage/maria/unittest/Makefile.am +++ b/storage/maria/unittest/Makefile.am @@ -110,6 +110,3 @@ ma_pagecache_rwconsist2_1k_t_CPPFLAGS = -DTEST_PAGE_SIZE=1024 # so we don't build lockman-t and lockman1-t and lockman2-t CLEANFILES = aria_log_control page_cache_test_file_1 \ aria_log.???????? - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/myisam/Makefile.am b/storage/myisam/Makefile.am index 8f3d51c4886..b232a6a1d07 100644 --- a/storage/myisam/Makefile.am +++ b/storage/myisam/Makefile.am @@ -165,6 +165,3 @@ SUFFIXES = .sh $< > $@-t @CHMOD@ +x $@-t @MV@ $@-t $@ - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c index aabbe1277c4..60d51637591 100644 --- a/storage/myisam/mi_range.c +++ b/storage/myisam/mi_range.c @@ -193,12 +193,11 @@ static double _mi_search_pos(register MI_INFO *info, register my_off_t pos) { int flag; - uint nod_flag,keynr,max_keynr; + uint nod_flag,keynr,UNINIT_VAR(max_keynr); my_bool after_key; uchar *keypos,*buff; double offset; DBUG_ENTER("_mi_search_pos"); - LINT_INIT(max_keynr); if (pos == HA_OFFSET_ERROR) DBUG_RETURN(0.5); diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index 52e28f8a5e9..1f8399f25ca 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -296,9 +296,9 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, flag is the value returned by ha_key_cmp and as treated as final */ int flag=0, my_flag=-1; - uint nod_flag, length, len, matched, cmplen, kseg_len; - uint prefix_len,suffix_len; - int key_len_skip, seg_len_pack, key_len_left; + uint nod_flag, UNINIT_VAR(length), len, matched, cmplen, kseg_len; + uint UNINIT_VAR(prefix_len), suffix_len; + int key_len_skip, UNINIT_VAR(seg_len_pack), key_len_left; uchar *end, *kseg, *vseg; const uchar *sort_order= keyinfo->seg->charset->sort_order; uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2; @@ -308,10 +308,6 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uint length_pack; DBUG_ENTER("_mi_prefix_search"); - LINT_INIT(length); - LINT_INIT(prefix_len); - LINT_INIT(seg_len_pack); - t_buff[0]=0; /* Avoid bugs */ end= page+mi_getint(page); nod_flag=mi_test_if_nod(page); diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c index 575cc32eb56..6a825bab1fa 100644 --- a/storage/myisam/rt_index.c +++ b/storage/myisam/rt_index.c @@ -481,17 +481,13 @@ static uchar *rtree_pick_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *key, uint key_length, uchar *page_buf, uint nod_flag) { double increase; - double best_incr; + double UNINIT_VAR(best_incr); double area; - double best_area; + double UNINIT_VAR(best_area); uchar *best_key= NULL; uchar *k = rt_PAGE_FIRST_KEY(page_buf, nod_flag); uchar *last = rt_PAGE_END(page_buf); - LINT_INIT(best_area); - LINT_INIT(best_key); - LINT_INIT(best_incr); - for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag)) { /* The following is safe as -1.0 is an exact number */ diff --git a/storage/myisam/rt_split.c b/storage/myisam/rt_split.c index 03d22de68fa..0b7cc43e062 100644 --- a/storage/myisam/rt_split.c +++ b/storage/myisam/rt_split.c @@ -178,18 +178,13 @@ static int split_rtree_node(SplitStruct *node, int n_entries, double **d_buffer, int n_dim) { SplitStruct *cur; - SplitStruct *a; - SplitStruct *b; + SplitStruct *UNINIT_VAR(a), *UNINIT_VAR(b); double *g1 = reserve_coords(d_buffer, n_dim); double *g2 = reserve_coords(d_buffer, n_dim); - SplitStruct *next; - int next_node; + SplitStruct *UNINIT_VAR(next); + int UNINIT_VAR(next_node); int i; SplitStruct *end = node + n_entries; - LINT_INIT(a); - LINT_INIT(b); - LINT_INIT(next); - LINT_INIT(next_node); if (all_size < min_size * 2) { diff --git a/storage/myisammrg/Makefile.am b/storage/myisammrg/Makefile.am index 66fd2402646..28a0e532bae 100644 --- a/storage/myisammrg/Makefile.am +++ b/storage/myisammrg/Makefile.am @@ -49,6 +49,3 @@ libmyisammrg.a: libmyisammrg.la $(CP) .libs/libmyisammrg.a $@ EXTRA_DIST = CMakeLists.txt plug.in - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/Makefile.am b/storage/ndb/Makefile.am index 5e519ec1c98..0da8ec136c9 100644 --- a/storage/ndb/Makefile.am +++ b/storage/ndb/Makefile.am @@ -44,6 +44,3 @@ all-windoze-dsp: windoze find . -name '*.dsp' | grep -v SCCS | xargs unix2dos $(top_srcdir)/storage/ndb/config/make-win-dsw.sh | unix2dos > ndb.dsw tar cvfz ndb-win-dsp.tar.gz ndb.dsw `find . -name '*.dsp' | grep -v SCCS` - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/docs/Makefile.am b/storage/ndb/docs/Makefile.am index 66d116c02b7..b0166d40779 100644 --- a/storage/ndb/docs/Makefile.am +++ b/storage/ndb/docs/Makefile.am @@ -127,6 +127,3 @@ testdoc: DUMMY cd $(top_srcdir)/storage/ndb ; $(DOXYGEN) $(DOXYDIR)/Doxyfile.test windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/include/Makefile.am b/storage/ndb/include/Makefile.am index 9e6ad016d75..34a243d82a1 100644 --- a/storage/ndb/include/Makefile.am +++ b/storage/ndb/include/Makefile.am @@ -63,6 +63,3 @@ dist-hook: -rm -rf `find $(distdir) -type d -name SCCS` windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/Makefile.am b/storage/ndb/src/Makefile.am index 627347daf02..e879249bed6 100644 --- a/storage/ndb/src/Makefile.am +++ b/storage/ndb/src/Makefile.am @@ -48,6 +48,3 @@ libndbclient.dsp: Makefile \ @$(top_srcdir)/storage/ndb/config/win-sources $@ dummy.cpp @$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(libndbclient_la_LIBADD) @touch dummy.cpp - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/common/Makefile.am b/storage/ndb/src/common/Makefile.am index 9d601c7a18a..34e9871da55 100644 --- a/storage/ndb/src/common/Makefile.am +++ b/storage/ndb/src/common/Makefile.am @@ -28,6 +28,3 @@ libcommon_la_LIBADD = \ util/libgeneral.la windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/common/debugger/Makefile.am b/storage/ndb/src/common/debugger/Makefile.am index 56910ee8ea4..30b8563af6d 100644 --- a/storage/ndb/src/common/debugger/Makefile.am +++ b/storage/ndb/src/common/debugger/Makefile.am @@ -22,9 +22,6 @@ libtrace_la_SOURCES = SignalLoggerManager.cpp DebuggerNames.cpp BlockNames.cpp E include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libtrace.dsp libtrace.dsp: Makefile \ diff --git a/storage/ndb/src/common/debugger/signaldata/Makefile.am b/storage/ndb/src/common/debugger/signaldata/Makefile.am index 280cd6a5a39..028049cf67b 100644 --- a/storage/ndb/src/common/debugger/signaldata/Makefile.am +++ b/storage/ndb/src/common/debugger/signaldata/Makefile.am @@ -43,9 +43,6 @@ libsignaldataprint_la_SOURCES = \ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libsignaldataprint.dsp libsignaldataprint.dsp: Makefile \ diff --git a/storage/ndb/src/common/logger/Makefile.am b/storage/ndb/src/common/logger/Makefile.am index 77615212e0d..870946c1e9d 100644 --- a/storage/ndb/src/common/logger/Makefile.am +++ b/storage/ndb/src/common/logger/Makefile.am @@ -22,8 +22,6 @@ liblogger_la_SOURCES = $(SOURCE_WIN) SysLogHandler.cpp include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% windoze-dsp: liblogger.dsp liblogger.dsp: Makefile \ diff --git a/storage/ndb/src/common/mgmcommon/Makefile.am b/storage/ndb/src/common/mgmcommon/Makefile.am index ad56e8c1459..2b41c2bfdd9 100644 --- a/storage/ndb/src/common/mgmcommon/Makefile.am +++ b/storage/ndb/src/common/mgmcommon/Makefile.am @@ -25,9 +25,6 @@ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am include $(top_srcdir)/storage/ndb/config/type_mgmapiclient.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libmgmsrvcommon.dsp libmgmsrvcommon.dsp: Makefile \ diff --git a/storage/ndb/src/common/portlib/Makefile.am b/storage/ndb/src/common/portlib/Makefile.am index f427b2170b4..84d9cc754a8 100644 --- a/storage/ndb/src/common/portlib/Makefile.am +++ b/storage/ndb/src/common/portlib/Makefile.am @@ -54,6 +54,3 @@ libportlib.dsp: Makefile \ @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES) @$(top_srcdir)/storage/ndb/config/win-sources $@ $(WIN_src) @$(top_srcdir)/storage/ndb/config/win-libraries $@ LIB $(LDADD) - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/common/transporter/Makefile.am b/storage/ndb/src/common/transporter/Makefile.am index 83ac3b6121d..ccf51b352b1 100644 --- a/storage/ndb/src/common/transporter/Makefile.am +++ b/storage/ndb/src/common/transporter/Makefile.am @@ -32,9 +32,6 @@ INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/include/mgmapi -I$(top_srcdir)/storag include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_util.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libtransporter.dsp libtransporter.dsp: Makefile \ diff --git a/storage/ndb/src/common/util/Makefile.am b/storage/ndb/src/common/util/Makefile.am index 5379a425c49..4a69924192e 100644 --- a/storage/ndb/src/common/util/Makefile.am +++ b/storage/ndb/src/common/util/Makefile.am @@ -46,9 +46,6 @@ testBitmask.o: $(testBitmask_SOURCES) include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_util.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libgeneral.dsp libgeneral.dsp: Makefile \ diff --git a/storage/ndb/src/cw/Makefile.am b/storage/ndb/src/cw/Makefile.am index d9a40002062..3695e197cfb 100644 --- a/storage/ndb/src/cw/Makefile.am +++ b/storage/ndb/src/cw/Makefile.am @@ -16,6 +16,3 @@ SUBDIRS = cpcd windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/cw/cpcd/Makefile.am b/storage/ndb/src/cw/cpcd/Makefile.am index efc828e21a9..722ceaf22e8 100644 --- a/storage/ndb/src/cw/cpcd/Makefile.am +++ b/storage/ndb/src/cw/cpcd/Makefile.am @@ -28,7 +28,4 @@ include $(top_srcdir)/storage/ndb/config/type_util.mk.am ndb_cpcd_LDFLAGS = -static @ndb_bin_am_ldflags@ -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: diff --git a/storage/ndb/src/kernel/Makefile.am b/storage/ndb/src/kernel/Makefile.am index 343d5eeab6d..9596c53da37 100644 --- a/storage/ndb/src/kernel/Makefile.am +++ b/storage/ndb/src/kernel/Makefile.am @@ -70,6 +70,3 @@ storage/ndbd.dsp: Makefile \ @$(top_srcdir)/storage/ndb/config/win-includes $@ $(INCLUDES) @$(top_srcdir)/storage/ndb/config/win-sources $@ $(ndbd_SOURCES) @$(top_srcdir)/storage/ndb/config/win-libraries $@ LINK $(LDADD) - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/blocks/Makefile.am b/storage/ndb/src/kernel/blocks/Makefile.am index ebb2e48ad14..f17f274defb 100644 --- a/storage/ndb/src/kernel/blocks/Makefile.am +++ b/storage/ndb/src/kernel/blocks/Makefile.am @@ -64,10 +64,4 @@ ndb_print_file_LDFLAGS = @ndb_bin_am_ldflags@ \ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/blocks/backup/Makefile.am b/storage/ndb/src/kernel/blocks/backup/Makefile.am index 4594e0fe717..bfeede8a984 100644 --- a/storage/ndb/src/kernel/blocks/backup/Makefile.am +++ b/storage/ndb/src/kernel/blocks/backup/Makefile.am @@ -24,6 +24,3 @@ ndb_print_backup_file_LDFLAGS = @ndb_bin_am_ldflags@ \ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - diff --git a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am index 0ee3df7036d..678aa54684e 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Makefile.am +++ b/storage/ndb/src/kernel/blocks/dbdict/Makefile.am @@ -30,6 +30,3 @@ ndb_print_schema_file_LDFLAGS = @ndb_bin_am_ldflags@ \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am b/storage/ndb/src/kernel/blocks/dbdih/Makefile.am index 1c84714289d..651c966cad1 100644 --- a/storage/ndb/src/kernel/blocks/dbdih/Makefile.am +++ b/storage/ndb/src/kernel/blocks/dbdih/Makefile.am @@ -24,6 +24,3 @@ ndb_print_sys_file_LDFLAGS = @ndb_bin_am_ldflags@ \ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/blocks/dblqh/Makefile.am b/storage/ndb/src/kernel/blocks/dblqh/Makefile.am index b545096dc83..74ac3fd3a17 100644 --- a/storage/ndb/src/kernel/blocks/dblqh/Makefile.am +++ b/storage/ndb/src/kernel/blocks/dblqh/Makefile.am @@ -26,6 +26,3 @@ ndbd_redo_log_reader_LDFLAGS = @ndb_bin_am_ldflags@ \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am b/storage/ndb/src/kernel/blocks/dbtup/Makefile.am index 7feda3d8ac5..9fe51d30fab 100644 --- a/storage/ndb/src/kernel/blocks/dbtup/Makefile.am +++ b/storage/ndb/src/kernel/blocks/dbtup/Makefile.am @@ -23,6 +23,3 @@ test_varpage_LDFLAGS = @ndb_bin_am_ldflags@ \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/strings/libmystrings.a - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/src/kernel/error/Makefile.am b/storage/ndb/src/kernel/error/Makefile.am index 6db5c0e4ede..9d3c460eae8 100644 --- a/storage/ndb/src/kernel/error/Makefile.am +++ b/storage/ndb/src/kernel/error/Makefile.am @@ -22,9 +22,6 @@ liberror_a_SOURCES = TimeModule.cpp \ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: liberror.dsp liberror.dsp: Makefile \ diff --git a/storage/ndb/src/kernel/vm/Makefile.am b/storage/ndb/src/kernel/vm/Makefile.am index 4964b4ea85a..fdc7854e822 100644 --- a/storage/ndb/src/kernel/vm/Makefile.am +++ b/storage/ndb/src/kernel/vm/Makefile.am @@ -43,9 +43,6 @@ INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/mgmapi include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_kernel.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libkernel.dsp libkernel.dsp: Makefile \ diff --git a/storage/ndb/src/mgmapi/Makefile.am b/storage/ndb/src/mgmapi/Makefile.am index 96ee65d7d9e..ed4404245b7 100644 --- a/storage/ndb/src/mgmapi/Makefile.am +++ b/storage/ndb/src/mgmapi/Makefile.am @@ -29,9 +29,6 @@ include $(top_srcdir)/storage/ndb/config/type_util.mk.am #ndbtest_PROGRAMS = ndb_test_mgmapi -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libmgmapi.dsp libmgmapi.dsp: Makefile \ diff --git a/storage/ndb/src/mgmclient/Makefile.am b/storage/ndb/src/mgmclient/Makefile.am index 41f659cf68d..4cb5990e75f 100644 --- a/storage/ndb/src/mgmclient/Makefile.am +++ b/storage/ndb/src/mgmclient/Makefile.am @@ -44,9 +44,6 @@ LDADD_LOC = $(noinst_LTLIBRARIES) \ ndb_mgm_LDFLAGS = @ndb_bin_am_ldflags@ -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: ndb_mgm.dsp libndbmgmclient.dsp ndb_mgm.dsp: Makefile \ diff --git a/storage/ndb/src/mgmsrv/Makefile.am b/storage/ndb/src/mgmsrv/Makefile.am index 3f37280d7a5..3ae70155554 100644 --- a/storage/ndb/src/mgmsrv/Makefile.am +++ b/storage/ndb/src/mgmsrv/Makefile.am @@ -57,9 +57,6 @@ include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am ndb_mgmd_LDFLAGS = @ndb_bin_am_ldflags@ -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: ndb_mgmd.dsp ndb_mgmd.dsp: Makefile \ diff --git a/storage/ndb/src/ndbapi/Makefile.am b/storage/ndb/src/ndbapi/Makefile.am index 8ff427772b0..6a18649039d 100644 --- a/storage/ndb/src/ndbapi/Makefile.am +++ b/storage/ndb/src/ndbapi/Makefile.am @@ -71,9 +71,6 @@ ndberror_check_LDFLAGS = \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libndbapi.dsp libndbapi.dsp: Makefile \ diff --git a/storage/ndb/test/Makefile.am b/storage/ndb/test/Makefile.am index c746f526769..57e9db7b543 100644 --- a/storage/ndb/test/Makefile.am +++ b/storage/ndb/test/Makefile.am @@ -21,6 +21,3 @@ dist-hook: -rm -rf `find $(distdir) -type d -name SCCS` windoze-dsp: - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/ndb/test/ndbapi/Makefile.am b/storage/ndb/test/ndbapi/Makefile.am index 81bb346417f..81ac588ba3e 100644 --- a/storage/ndb/test/ndbapi/Makefile.am +++ b/storage/ndb/test/ndbapi/Makefile.am @@ -125,10 +125,6 @@ testBackup_LDADD = $(LDADD) bank/libbank.a testSRBank_LDADD = bank/libbank.a $(LDADD) NdbRepStress_LDADD = $(LDADD) $(top_builddir)/libmysql_r/libmysqlclient_r.la -# Don't update the files from bitkeeper -%::SCCS/s.% - - windoze-dsp: flexBench.dsp testBasic.dsp testBlobs.dsp \ testScan.dsp diff --git a/storage/ndb/test/ndbapi/bank/Makefile.am b/storage/ndb/test/ndbapi/bank/Makefile.am index 8e6c0f23eea..aee3ec57449 100644 --- a/storage/ndb/test/ndbapi/bank/Makefile.am +++ b/storage/ndb/test/ndbapi/bank/Makefile.am @@ -32,7 +32,4 @@ LDADD_LOC = $(noinst_LIBRARIES) include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: diff --git a/storage/ndb/test/run-test/Makefile.am b/storage/ndb/test/run-test/Makefile.am index 54ca0c009b2..e1bc71fb4a9 100644 --- a/storage/ndb/test/run-test/Makefile.am +++ b/storage/ndb/test/run-test/Makefile.am @@ -51,7 +51,4 @@ wrappers_SCRIPTS=atrt-testBackup atrt-mysql-test-run EXTRA_DIST = $(test_DATA) $(test_SCRIPTS) $(wrappers_SCRIPTS) README.ATRT atrt.hpp -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: diff --git a/storage/ndb/test/src/Makefile.am b/storage/ndb/test/src/Makefile.am index 1e4f30c3f39..148304adc47 100644 --- a/storage/ndb/test/src/Makefile.am +++ b/storage/ndb/test/src/Makefile.am @@ -31,9 +31,6 @@ INCLUDES_LOC = -I$(top_srcdir)/storage/ndb/src/common/mgmcommon -I$(top_srcdir)/ include $(top_srcdir)/storage/ndb/config/common.mk.am include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: libNDBT.dsp libNDBT.dsp: Makefile \ diff --git a/storage/ndb/test/tools/Makefile.am b/storage/ndb/test/tools/Makefile.am index da715caa1cb..6a93b1a36ba 100644 --- a/storage/ndb/test/tools/Makefile.am +++ b/storage/ndb/test/tools/Makefile.am @@ -43,7 +43,4 @@ include $(top_srcdir)/storage/ndb/config/type_ndbapitest.mk.am ndb_cpcc_LDADD = $(LDADD) ndb_cpcc_LDFLAGS = -static -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: diff --git a/storage/ndb/tools/Makefile.am b/storage/ndb/tools/Makefile.am index de0f36963bf..ef74198e2bd 100644 --- a/storage/ndb/tools/Makefile.am +++ b/storage/ndb/tools/Makefile.am @@ -75,9 +75,6 @@ ndb_select_count_LDFLAGS = @ndb_bin_am_ldflags@ ndb_restore_LDFLAGS = @ndb_bin_am_ldflags@ ndb_config_LDFLAGS = @ndb_bin_am_ldflags@ -# Don't update the files from bitkeeper -%::SCCS/s.% - windoze-dsp: \ ndb_waiter.dsp \ ndb_drop_table.dsp \ diff --git a/storage/pbxt/src/ha_pbxt.cc b/storage/pbxt/src/ha_pbxt.cc index ef0ae582c07..8640c079a37 100644 --- a/storage/pbxt/src/ha_pbxt.cc +++ b/storage/pbxt/src/ha_pbxt.cc @@ -1615,7 +1615,7 @@ static int pbxt_prepare(handlerton *hton, THD *thd, bool all) static XTThreadPtr ha_temp_open_global_database(handlerton *hton, THD **ret_thd, int *temp_thread, const char *thread_name, int *err) { THD *thd; - XTThreadPtr self = NULL; + XTThreadPtr volatile self = NULL; *temp_thread = 0; if ((thd = current_thd)) diff --git a/storage/pbxt/src/table_xt.cc b/storage/pbxt/src/table_xt.cc index 2d93f161ac9..a9fec660697 100644 --- a/storage/pbxt/src/table_xt.cc +++ b/storage/pbxt/src/table_xt.cc @@ -1822,8 +1822,8 @@ xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool } if (free_count != tab->tab_rec_fnum) { if (correct_count) { - tab->tab_rec_fnum = free_count; - tab->tab_head_rec_fnum = free_count; + tab->tab_rec_fnum = (uint) free_count; + tab->tab_head_rec_fnum = (uint) free_count; tab->tab_flush_pending = TRUE; xt_logf(XT_NT_INFO, "Table %s: free record count (%llu) has been set to the number of records on the list: %llu\n", table_name, (u_llong) tab->tab_rec_fnum, (u_llong) free_count); } @@ -1875,8 +1875,8 @@ xtPublic void xt_tab_check_free_lists(XTThreadPtr self, XTOpenTablePtr ot, bool * The correct way to do this at run time would be to add the change to the * transaction log, so that it is applied by the writer. */ - tab->tab_row_fnum = free_count; - tab->tab_head_row_fnum = free_count; + tab->tab_row_fnum = (uint) free_count; + tab->tab_head_row_fnum = (uint) free_count; tab->tab_flush_pending = TRUE; xt_logf(XT_NT_INFO, "Table %s: free row count (%llu) has been set to the number of rows on the list: %llu\n", table_name, (u_llong) tab->tab_row_fnum, (u_llong) free_count); } @@ -4450,10 +4450,10 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact xtXactID rec_xn_id = 0; xtBool wait = FALSE; xtXactID wait_xn_id = 0; - xtRowID row_id; + xtRowID row_id= 0; xtRecordID var_rec_id; xtXactID xn_id; - register XTTableHPtr tab; + register XTTableHPtr tab = 0; #ifdef TRACE_VARIATIONS_IN_DUP_CHECK char t_buf[500]; int len; @@ -4628,7 +4628,8 @@ xtPublic int xt_tab_maybe_committed(XTOpenTablePtr ot, xtRecordID rec_id, xtXact return FALSE; failed: - XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread); + if (tab) + XT_TAB_ROW_UNLOCK(&tab->tab_row_rwlock[row_id % XT_ROW_RWLOCKS], ot->ot_thread); return XT_ERR; } diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index e88464eb16c..6f4f12a318c 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -2671,7 +2671,7 @@ int ha_sphinx::get_rec ( byte * buf, const byte *, uint ) if ( pCur < sBuf+sizeof(sBuf)-16 ) // 10 chars per 32bit value plus some safety bytes { sprintf ( pCur, "%u", uEntry ); - while ( *pCur ) *pCur++; + while ( *pCur ) pCur++; if ( uValue>1 ) *pCur++ = ','; // non-trailing commas } diff --git a/storage/xtradb/ChangeLog b/storage/xtradb/ChangeLog index 43f87a1baf5..0cd8ac8a7e6 100644 --- a/storage/xtradb/ChangeLog +++ b/storage/xtradb/ChangeLog @@ -1,7 +1,73 @@ +2010-10-24 The InnoDB Team + + * row/row0mysql.c + Fix Bug #57700 Latching order violation in + row_truncate_table_for_mysql() + +2010-10-20 The InnoDB Team + + * dict/dict0load.c + Fix Bug #57616 Sig 11 in dict_load_table() when failed to load + index or foreign key + +2010-10-19 The InnoDB Team + + * btr/btr0cur.c, buf/buf0buf.c, buf/buf0flu.c, handler/ha_innodb.cc, + ibuf/ibuf0ibuf.c, include/btr0cur.h, include/buf0flu.h, + include/ibuf0ibuf.h, include/row0mysql.h, + row/row0mysql.c, row/row0sel.c, + innodb_bug56680.test, innodb_bug56680.result: + Fix Bug #56680 InnoDB may return wrong results from a + case-insensitive covering index + +2010-10-18 The InnoDB Team + + * handler/ha_innodb.cc, handler/ha_innodb.h, innodb_bug57252.result, + innodb_bug57252.test: + Fix Bug#57252 disabling innobase_stats_on_metadata disables ANALYZE + +2010-10-14 The InnoDB Team + + * handler/ha_innodb.cc, innodb_bug56143.result, innodb_bug56143.test: + Fix Bug#56143 too many foreign keys causes output of show create + table to become invalid + +2010-10-14 The InnoDB Team + + * srv/srv0start.c: + Fix Bug#57397 io_handler_thread() will never cleanup + +2010-10-11 The InnoDB Team + + * row/row0sel.c + Fix Bug #57345 btr_pcur_store_position abort for load with + concurrent lock/unlock tables + +2010-10-11 The InnoDB Team + + * row/row0mysql.c, innodb_bug56947.result, innodb_bug56947.test: + Fix Bug #56947 InnoDB leaks memory when failing to create a table + +2010-10-06 The InnoDB Team + + * row/row0mysql.c, innodb_bug57255.result, innodb_bug57255.test + Fix Bug #57255 Cascade Delete results in "Got error -1 from + storage engine" + +2010-09-27 The InnoDB Team + + * row/row0sel.c, innodb_bug56716.result, innodb_bug56716.test: + Fix Bug#56716 InnoDB locks a record gap without locking the table + +2010-09-06 The InnoDB Team + + * dict/dict0load.c, innodb_bug53756.test innodb_bug53756.result: + Fix Bug#53756 ALTER TABLE ADD PRIMARY KEY affects crash recovery + 2010-08-24 The InnoDB Team * handler/ha_innodb.c, dict/dict0dict.c: - Fix Bug #55832 selects crash too easily when innodb_force_recovery>3 + Fix Bug#55832 selects crash too easily when innodb_force_recovery>3 2010-08-03 The InnoDB Team @@ -19,15 +85,14 @@ 2010-08-03 The InnoDB Team * include/ut0mem.h, ut/ut0mem.c: - Fix Bug #55627 segv in ut_free pars_lexer_close innobase_shutdown + Fix Bug#55627 segv in ut_free pars_lexer_close innobase_shutdown innodb-use-sys-malloc=0 2010-08-01 The InnoDB Team - * handler/ha_innodb.cc - Fix Bug #55382 Assignment with SELECT expressions takes unexpected + * handler/ha_innodb.cc: + Fix Bug#55382 Assignment with SELECT expressions takes unexpected S locks in READ COMMITTED ->>>>>>> MERGE-SOURCE 2010-07-27 The InnoDB Team @@ -48,8 +113,8 @@ 2010-06-29 The InnoDB Team - * btr/btr0cur.c, include/btr0cur.h, - include/row0mysql.h, row/row0merge.c, row/row0sel.c: + * btr/btr0cur.c, include/btr0cur.h, include/row0mysql.h, + row/row0merge.c, row/row0sel.c: Fix Bug#54358 READ UNCOMMITTED access failure of off-page DYNAMIC or COMPRESSED columns diff --git a/storage/xtradb/Makefile.am b/storage/xtradb/Makefile.am index cb1e20436f4..02eeaa1e456 100644 --- a/storage/xtradb/Makefile.am +++ b/storage/xtradb/Makefile.am @@ -339,6 +339,3 @@ ha_xtradb_la_SOURCES= $(libxtradb_la_SOURCES) EXTRA_DIST= CMakeLists.txt plug.in \ pars/make_bison.sh pars/make_flex.sh \ pars/pars0grm.y pars/pars0lex.l - -# Don't update the files from bitkeeper -%::SCCS/s.% diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c index ff047095aa4..4d6cd8d80fc 100644 --- a/storage/xtradb/btr/btr0btr.c +++ b/storage/xtradb/btr/btr0btr.c @@ -1925,7 +1925,6 @@ btr_page_split_and_insert( buf_block_t* left_block; buf_block_t* right_block; buf_block_t* insert_block; - page_t* insert_page; page_cur_t* page_cursor; rec_t* first_rec; byte* buf = 0; /* remove warning */ @@ -2183,8 +2182,6 @@ insert_empty: insert_block = right_block; } - insert_page = buf_block_get_frame(insert_block); - /* 7. Reposition the cursor for insert and try insertion */ page_cursor = btr_cur_get_page_cur(cursor); @@ -2196,8 +2193,12 @@ insert_empty: #ifdef UNIV_ZIP_DEBUG { + page_t* insert_page + = buf_block_get_frame(insert_block); + page_zip_des_t* insert_page_zip = buf_block_get_page_zip(insert_block); + ut_a(!insert_page_zip || page_zip_validate(insert_page_zip, insert_page)); } @@ -2590,7 +2591,6 @@ btr_compress( ulint n_recs; ulint max_ins_size; ulint max_ins_size_reorg; - ulint level; block = btr_cur_get_block(cursor); page = btr_cur_get_page(cursor); @@ -2600,7 +2600,6 @@ btr_compress( ut_ad(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)); - level = btr_page_get_level(page, mtr); space = dict_index_get_space(index); zip_size = dict_table_zip_size(index->table); diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c index 3fc2b48162a..daa94a549a0 100644 --- a/storage/xtradb/btr/btr0cur.c +++ b/storage/xtradb/btr/btr0cur.c @@ -1803,7 +1803,7 @@ func_exit: See if there is enough place in the page modification log to log an update-in-place. @return TRUE if enough place */ -static +UNIV_INTERN ibool btr_cur_update_alloc_zip( /*=====================*/ @@ -2013,7 +2013,6 @@ btr_cur_optimistic_update( page_t* page; page_zip_des_t* page_zip; rec_t* rec; - rec_t* orig_rec; ulint max_size; ulint new_rec_size; ulint old_rec_size; @@ -2027,7 +2026,7 @@ btr_cur_optimistic_update( block = btr_cur_get_block(cursor); page = buf_block_get_frame(block); - orig_rec = rec = btr_cur_get_rec(cursor); + 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)); @@ -4673,12 +4672,17 @@ btr_free_externally_stored_field( } for (;;) { +#ifdef UNIV_SYNC_DEBUG buf_block_t* rec_block; +#endif /* UNIV_SYNC_DEBUG */ buf_block_t* ext_block; mtr_start(&mtr); - rec_block = buf_page_get(page_get_space_id( +#ifdef UNIV_SYNC_DEBUG + rec_block = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(page_get_space_id( page_align(field_ref)), rec_zip_size, page_get_page_no( diff --git a/storage/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c index 537c26f6bf2..f95a5487c94 100644 --- a/storage/xtradb/btr/btr0pcur.c +++ b/storage/xtradb/btr/btr0pcur.c @@ -467,7 +467,6 @@ btr_pcur_move_backward_from_page( mtr_t* mtr) /*!< in: mtr */ { ulint prev_page_no; - ulint space; page_t* page; buf_block_t* prev_block; ulint latch_mode; @@ -503,7 +502,6 @@ btr_pcur_move_backward_from_page( page = btr_pcur_get_page(cursor); prev_page_no = btr_page_get_prev(page, mtr); - space = buf_block_get_space(btr_pcur_get_block(cursor)); if (prev_page_no == FIL_NULL) { } else if (btr_pcur_is_before_first_on_page(cursor)) { diff --git a/storage/xtradb/btr/btr0sea.c b/storage/xtradb/btr/btr0sea.c index 6628333d32a..c78f791480c 100644 --- a/storage/xtradb/btr/btr0sea.c +++ b/storage/xtradb/btr/btr0sea.c @@ -1620,7 +1620,6 @@ btr_search_update_hash_on_delete( rec_t* rec; ulint fold; dulint index_id; - ibool found; ulint offsets_[REC_OFFS_NORMAL_SIZE]; mem_heap_t* heap = NULL; rec_offs_init(offsets_); @@ -1653,7 +1652,7 @@ btr_search_update_hash_on_delete( } rw_lock_x_lock(&btr_search_latch); - found = ha_search_and_delete_if_found(table, fold, rec); + ha_search_and_delete_if_found(table, fold, rec); rw_lock_x_unlock(&btr_search_latch); } diff --git a/storage/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c index 1c08bd6d0bf..1e9624fce50 100644 --- a/storage/xtradb/buf/buf0buf.c +++ b/storage/xtradb/buf/buf0buf.c @@ -53,10 +53,6 @@ Created 11/5/1995 Heikki Tuuri #include "page0zip.h" #include "trx0trx.h" #include "srv0start.h" -#include "que0que.h" -#include "read0read.h" -#include "row0row.h" -#include "ha_prototypes.h" /* prototypes for new functions added to ha_innodb.cc */ trx_t* innobase_get_trx(); @@ -314,30 +310,6 @@ read-ahead or flush occurs */ UNIV_INTERN ibool buf_debug_prints = FALSE; #endif /* UNIV_DEBUG */ -/* Buffer pool shared memory segment information */ -typedef struct buf_shm_info_struct buf_shm_info_t; - -struct buf_shm_info_struct { - char head_str[8]; - ulint binary_id; - ibool is_new; /* during initializing */ - ibool clean; /* clean shutdowned and free */ - ibool reusable; /* reusable */ - ulint buf_pool_size; /* backup value */ - ulint page_size; /* backup value */ - ulint frame_offset; /* offset of the first frame based on chunk->mem */ - ulint zip_hash_offset; - ulint zip_hash_n; - - ulint checksum; - - buf_pool_t buf_pool_backup; - buf_chunk_t chunk_backup; - - ib_uint64_t dummy; -}; - -#define BUF_SHM_INFO_HEAD "XTRA_SHM" #endif /* !UNIV_HOTBACKUP */ /********************************************************************//** @@ -784,45 +756,6 @@ buf_block_init( #endif /* UNIV_SYNC_DEBUG */ } -static -void -buf_block_reuse( -/*============*/ - buf_block_t* block, - ptrdiff_t frame_offset) -{ - /* block_init */ - block->frame += frame_offset; - - UNIV_MEM_DESC(block->frame, UNIV_PAGE_SIZE, block); - - block->index = NULL; - -#ifdef UNIV_DEBUG - /* recreate later */ - block->page.in_page_hash = FALSE; - block->page.in_zip_hash = FALSE; -#endif /* UNIV_DEBUG */ - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - block->n_pointers = 0; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - - if (block->page.zip.data) - block->page.zip.data += frame_offset; - - block->is_hashed = FALSE; - - mutex_create(&block->mutex, SYNC_BUF_BLOCK); - - rw_lock_create(&block->lock, SYNC_LEVEL_VARYING); - ut_ad(rw_lock_validate(&(block->lock))); - -#ifdef UNIV_SYNC_DEBUG - rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK); -#endif /* UNIV_SYNC_DEBUG */ -} - /********************************************************************//** Allocates a chunk of buffer frames. @return chunk, or NULL on failure */ @@ -835,188 +768,26 @@ buf_chunk_init( { buf_block_t* block; byte* frame; - ulint zip_hash_n = 0; - ulint zip_hash_mem_size = 0; - hash_table_t* zip_hash_tmp = NULL; ulint i; - buf_shm_info_t* shm_info = NULL; /* Round down to a multiple of page size, although it already should be. */ mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE); - - srv_buffer_pool_shm_is_reused = FALSE; - - if (srv_buffer_pool_shm_key) { - /* zip_hash size */ - zip_hash_n = (mem_size / UNIV_PAGE_SIZE) * 2; - zip_hash_mem_size = ut_2pow_round(hash_create_needed(zip_hash_n) - + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE); - } - /* Reserve space for the block descriptors. */ mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block) + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE); - if (srv_buffer_pool_shm_key) { - mem_size += ut_2pow_round(sizeof(buf_shm_info_t) - + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE); - mem_size += zip_hash_mem_size; - } chunk->mem_size = mem_size; - - if (srv_buffer_pool_shm_key) { - ulint binary_id; - ibool is_new; - - ut_a(buf_pool->n_chunks == 1); - - fprintf(stderr, - "InnoDB: Warning: The innodb_buffer_pool_shm_key option has been specified.\n" - "InnoDB: Do not change the following between restarts of the server while this option is being used:\n" - "InnoDB: * the mysqld executable between restarts of the server.\n" - "InnoDB: * the value of innodb_buffer_pool_size.\n" - "InnoDB: * the value of innodb_page_size.\n" - "InnoDB: * datafiles created by InnoDB during this session.\n" - "InnoDB: Otherwise, data corruption in datafiles may result.\n"); - - /* FIXME: This is vague id still */ - binary_id = (ulint) ((byte*)mtr_commit - (byte*)btr_root_get) - + (ulint) ((byte*)os_get_os_version - (byte*)buf_calc_page_new_checksum) - + (ulint) ((byte*)page_dir_find_owner_slot - (byte*)dfield_data_is_binary_equal) - + (ulint) ((byte*)que_graph_publish - (byte*)dict_casedn_str) - + (ulint) ((byte*)read_view_oldest_copy_or_open_new - (byte*)fil_space_get_version) - + (ulint) ((byte*)rec_get_n_extern_new - (byte*)fsp_get_size_low) - + (ulint) ((byte*)row_get_trx_id_offset - (byte*)ha_create_func) - + (ulint) ((byte*)srv_set_io_thread_op_info - (byte*)thd_is_replication_slave_thread) - + (ulint) ((byte*)mutex_create_func - (byte*)ibuf_inside) - + (ulint) ((byte*)trx_set_detailed_error - (byte*)lock_check_trx_id_sanity) - + (ulint) ((byte*)ut_time - (byte*)mem_heap_strdup); - - chunk->mem = os_shm_alloc(&chunk->mem_size, srv_buffer_pool_shm_key, &is_new); - - if (UNIV_UNLIKELY(chunk->mem == NULL)) { - return(NULL); - } -init_again: -#ifdef UNIV_SET_MEM_TO_ZERO - if (is_new) { - memset(chunk->mem, '\0', chunk->mem_size); - } -#endif - /* for ut_fold_binary_32(), these values should be 32-bit aligned */ - ut_a(sizeof(buf_shm_info_t) % 4 == 0); - ut_a((ulint)chunk->mem % 4 == 0); - ut_a(chunk->mem_size % 4 == 0); - - shm_info = chunk->mem; - - zip_hash_tmp = (hash_table_t*)((byte*)chunk->mem + chunk->mem_size - zip_hash_mem_size); - - if (is_new) { - strncpy(shm_info->head_str, BUF_SHM_INFO_HEAD, 8); - shm_info->binary_id = binary_id; - shm_info->is_new = TRUE; /* changed to FALSE when the initialization is finished */ - shm_info->clean = FALSE; /* changed to TRUE when free the segment. */ - shm_info->reusable = FALSE; /* changed to TRUE when validation is finished. */ - shm_info->buf_pool_size = srv_buf_pool_size; - shm_info->page_size = srv_page_size; - shm_info->zip_hash_offset = chunk->mem_size - zip_hash_mem_size; - shm_info->zip_hash_n = zip_hash_n; - } else { - ulint checksum; - - if (strncmp(shm_info->head_str, BUF_SHM_INFO_HEAD, 8)) { - fprintf(stderr, - "InnoDB: Error: The shared memory segment seems not to be for buffer pool.\n"); - return(NULL); - } - if (shm_info->binary_id != binary_id) { - fprintf(stderr, - "InnoDB: Error: The shared memory segment seems not to be for this binary.\n"); - return(NULL); - } - if (shm_info->is_new) { - fprintf(stderr, - "InnoDB: Error: The shared memory was not initialized yet.\n"); - return(NULL); - } - if (shm_info->buf_pool_size != srv_buf_pool_size) { - fprintf(stderr, - "InnoDB: Error: srv_buf_pool_size is different (shm=%lu current=%lu).\n", - shm_info->buf_pool_size, srv_buf_pool_size); - return(NULL); - } - if (shm_info->page_size != srv_page_size) { - fprintf(stderr, - "InnoDB: Error: srv_page_size is different (shm=%lu current=%lu).\n", - shm_info->page_size, srv_page_size); - return(NULL); - } - if (!shm_info->reusable) { - fprintf(stderr, - "InnoDB: Warning: The shared memory has unrecoverable contents.\n" - "InnoDB: The shared memory segment is initialized.\n"); - is_new = TRUE; - goto init_again; - } - if (!shm_info->clean) { - fprintf(stderr, - "InnoDB: Warning: The shared memory was not shut down cleanly.\n" - "InnoDB: The shared memory segment is initialized.\n"); - is_new = TRUE; - goto init_again; - } - - ut_a(shm_info->zip_hash_offset == chunk->mem_size - zip_hash_mem_size); - ut_a(shm_info->zip_hash_n == zip_hash_n); - - /* check checksum */ - if (srv_buffer_pool_shm_checksum) { - checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t), - chunk->mem_size - sizeof(buf_shm_info_t)); - } else { - checksum = BUF_NO_CHECKSUM_MAGIC; - } - - if (shm_info->checksum != BUF_NO_CHECKSUM_MAGIC - && shm_info->checksum != checksum) { - fprintf(stderr, - "InnoDB: Error: checksum of the shared memory is not match. " - "(stored=%lu calculated=%lu)\n", - shm_info->checksum, checksum); - return(NULL); - } - - /* flag to use the segment. */ - shm_info->clean = FALSE; /* changed to TRUE when free the segment. */ - } - - /* init zip_hash contents */ - if (is_new) { - hash_create_init(zip_hash_tmp, zip_hash_n); - } else { - /* adjust offset is done later */ - hash_create_reuse(zip_hash_tmp); - - srv_buffer_pool_shm_is_reused = TRUE; - } - } else { chunk->mem = os_mem_alloc_large(&chunk->mem_size); if (UNIV_UNLIKELY(chunk->mem == NULL)) { return(NULL); } - } /* Allocate the block descriptors from the start of the memory block. */ - if (srv_buffer_pool_shm_key) { - chunk->blocks = (buf_block_t*)((byte*)chunk->mem + sizeof(buf_shm_info_t)); - } else { chunk->blocks = chunk->mem; - } /* Align a pointer to the first frame. Note that when os_large_page_size is smaller than UNIV_PAGE_SIZE, @@ -1024,13 +795,8 @@ init_again: it is bigger, we may allocate more blocks than requested. */ frame = ut_align(chunk->mem, UNIV_PAGE_SIZE); - if (srv_buffer_pool_shm_key) { - /* reserve zip_hash space and always -1 for reproductibity */ - chunk->size = (chunk->mem_size - zip_hash_mem_size) / UNIV_PAGE_SIZE - 1; - } else { chunk->size = chunk->mem_size / UNIV_PAGE_SIZE - (frame != chunk->mem); - } /* Subtract the space needed for block descriptors. */ { @@ -1044,98 +810,6 @@ init_again: chunk->size = size; } - if (shm_info && !(shm_info->is_new)) { - /* convert the shared memory segment for reuse */ - ptrdiff_t phys_offset; - ptrdiff_t logi_offset; - ptrdiff_t blocks_offset; - byte* previous_frame_address; - - if (chunk->size < shm_info->chunk_backup.size) { - fprintf(stderr, - "InnoDB: Error: The buffer pool became smaller because of allocated address.\n" - "InnoDB: Retrying may avoid this situation.\n"); - shm_info->clean = TRUE; /* release the flag for retrying */ - return(NULL); - } - - chunk->size = shm_info->chunk_backup.size; - phys_offset = frame - ((byte*)chunk->mem + shm_info->frame_offset); - logi_offset = frame - chunk->blocks[0].frame; - previous_frame_address = chunk->blocks[0].frame; - blocks_offset = (byte*)chunk->blocks - (byte*)shm_info->chunk_backup.blocks; - - if (phys_offset || logi_offset || blocks_offset) { - fprintf(stderr, - "InnoDB: Buffer pool in the shared memory segment should be converted.\n" - "InnoDB: Previous frames in address : %p\n" - "InnoDB: Previous frames were located : %p\n" - "InnoDB: Current frames should be located: %p\n" - "InnoDB: Pysical offset : %ld (%#lx)\n" - "InnoDB: Logical offset (frames) : %ld (%#lx)\n" - "InnoDB: Logical offset (blocks) : %ld (%#lx)\n", - (byte*)chunk->mem + shm_info->frame_offset, - chunk->blocks[0].frame, frame, - (long) phys_offset, (ulong) phys_offset, (long) logi_offset, (ulong) logi_offset, - (long) blocks_offset, (ulong) blocks_offset); - } else { - fprintf(stderr, - "InnoDB: Buffer pool in the shared memory segment can be used as it is.\n"); - } - - if (phys_offset) { - fprintf(stderr, - "InnoDB: Aligning physical offset..."); - - memmove(frame, (byte*)chunk->mem + shm_info->frame_offset, - chunk->size * UNIV_PAGE_SIZE); - - fprintf(stderr, - " Done.\n"); - } - - /* buf_block_t */ - block = chunk->blocks; - for (i = chunk->size; i--; ) { - buf_block_reuse(block, logi_offset); - block++; - } - - if (logi_offset || blocks_offset) { - fprintf(stderr, - "InnoDB: Aligning logical offset..."); - - - /* buf_pool_t buf_pool_backup */ - UT_LIST_OFFSET(flush_list, buf_page_t, shm_info->buf_pool_backup.flush_list, - previous_frame_address, logi_offset, blocks_offset); - UT_LIST_OFFSET(free, buf_page_t, shm_info->buf_pool_backup.free, - previous_frame_address, logi_offset, blocks_offset); - UT_LIST_OFFSET(LRU, buf_page_t, shm_info->buf_pool_backup.LRU, - previous_frame_address, logi_offset, blocks_offset); - if (shm_info->buf_pool_backup.LRU_old) - shm_info->buf_pool_backup.LRU_old = - (buf_page_t*)((byte*)(shm_info->buf_pool_backup.LRU_old) - + (((byte*)shm_info->buf_pool_backup.LRU_old > previous_frame_address) - ? logi_offset : blocks_offset)); - - UT_LIST_OFFSET(unzip_LRU, buf_block_t, shm_info->buf_pool_backup.unzip_LRU, - previous_frame_address, logi_offset, blocks_offset); - - UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_clean, - previous_frame_address, logi_offset, blocks_offset); - for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) { - UT_LIST_OFFSET(zip_list, buf_page_t, shm_info->buf_pool_backup.zip_free[i], - previous_frame_address, logi_offset, blocks_offset); - } - - HASH_OFFSET(zip_hash_tmp, buf_page_t, hash, - previous_frame_address, logi_offset, blocks_offset); - - fprintf(stderr, - " Done.\n"); - } - } else { /* Init block structs and assign frames for them. Then we assign the frames to the first blocks (we already mapped the memory above). */ @@ -1159,11 +833,6 @@ init_again: block++; frame += UNIV_PAGE_SIZE; } - } - - if (shm_info) { - shm_info->frame_offset = chunk->blocks[0].frame - (byte*)chunk->mem; - } return(chunk); } @@ -1345,8 +1014,6 @@ buf_chunk_free( UNIV_MEM_UNDESC(block); } - ut_a(!srv_buffer_pool_shm_key); - os_mem_free_large(chunk->mem, chunk->mem_size); } @@ -1396,10 +1063,7 @@ buf_pool_init(void) srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE; buf_pool->page_hash = hash_create(2 * buf_pool->curr_size); - /* zip_hash is allocated to shm when srv_buffer_pool_shm_key is enabled */ - if (!srv_buffer_pool_shm_key) { buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size); - } buf_pool->last_printout_time = time(NULL); @@ -1414,86 +1078,6 @@ buf_pool_init(void) --------------------------- */ /* All fields are initialized by mem_zalloc(). */ - if (srv_buffer_pool_shm_key) { - buf_shm_info_t* shm_info; - - ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t)); - shm_info = chunk->mem; - - buf_pool->zip_hash = (hash_table_t*)((byte*)chunk->mem + shm_info->zip_hash_offset); - - if(shm_info->is_new) { - shm_info->is_new = FALSE; /* initialization was finished */ - } else { - buf_block_t* block = chunk->blocks; - buf_page_t* b; - - /* shm_info->buf_pool_backup should be converted */ - /* at buf_chunk_init(). So copy simply. */ - buf_pool->flush_list = shm_info->buf_pool_backup.flush_list; - buf_pool->freed_page_clock = shm_info->buf_pool_backup.freed_page_clock; - buf_pool->free = shm_info->buf_pool_backup.free; - buf_pool->LRU = shm_info->buf_pool_backup.LRU; - buf_pool->LRU_old = shm_info->buf_pool_backup.LRU_old; - buf_pool->LRU_old_len = shm_info->buf_pool_backup.LRU_old_len; - buf_pool->unzip_LRU = shm_info->buf_pool_backup.unzip_LRU; - buf_pool->zip_clean = shm_info->buf_pool_backup.zip_clean; - for (i = 0; i < BUF_BUDDY_SIZES_MAX; i++) { - buf_pool->zip_free[i] = shm_info->buf_pool_backup.zip_free[i]; - } - - for (i = 0; i < chunk->size; i++, block++) { - if (buf_block_get_state(block) - == BUF_BLOCK_FILE_PAGE) { - ut_d(block->page.in_page_hash = TRUE); - HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, - buf_page_address_fold( - block->page.space, - block->page.offset), - &block->page); - } - } - - for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b; - b = UT_LIST_GET_NEXT(zip_list, b)) { - ut_ad(!b->in_flush_list); - ut_ad(b->in_LRU_list); - - ut_d(b->in_page_hash = TRUE); - HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, - buf_page_address_fold(b->space, b->offset), b); - } - - 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); - - switch (buf_page_get_state(b)) { - case BUF_BLOCK_ZIP_DIRTY: - ut_d(b->in_page_hash = TRUE); - HASH_INSERT(buf_page_t, hash, buf_pool->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; - } - } - - - } - } - mutex_exit(&LRU_list_mutex); rw_lock_x_unlock(&page_hash_latch); buf_pool_mutex_exit(); @@ -1518,34 +1102,6 @@ buf_pool_free(void) buf_chunk_t* chunk; buf_chunk_t* chunks; - if (srv_buffer_pool_shm_key) { - buf_shm_info_t* shm_info; - - ut_a(buf_pool->n_chunks == 1); - - chunk = buf_pool->chunks; - shm_info = chunk->mem; - ut_a((byte*)chunk->blocks == (byte*)chunk->mem + sizeof(buf_shm_info_t)); - - /* validation the shared memory segment doesn't have unrecoverable contents. */ - /* Currently, validation became not needed */ - shm_info->reusable = TRUE; - - memcpy(&(shm_info->buf_pool_backup), buf_pool, sizeof(buf_pool_t)); - memcpy(&(shm_info->chunk_backup), chunk, sizeof(buf_chunk_t)); - - if (srv_fast_shutdown < 2) { - if (srv_buffer_pool_shm_checksum) { - shm_info->checksum = ut_fold_binary_32((byte*)chunk->mem + sizeof(buf_shm_info_t), - chunk->mem_size - sizeof(buf_shm_info_t)); - } else { - shm_info->checksum = BUF_NO_CHECKSUM_MAGIC; - } - shm_info->clean = TRUE; - } - - os_shm_free(chunk->mem, chunk->mem_size); - } else { chunks = buf_pool->chunks; chunk = chunks + buf_pool->n_chunks; @@ -1554,13 +1110,10 @@ buf_pool_free(void) would fail at shutdown. */ os_mem_free_large(chunk->mem, chunk->mem_size); } - } mem_free(buf_pool->chunks); hash_table_free(buf_pool->page_hash); - if (!srv_buffer_pool_shm_key) { hash_table_free(buf_pool->zip_hash); - } mem_free(buf_pool); buf_pool = NULL; } @@ -1755,11 +1308,6 @@ try_again: //buf_pool_mutex_enter(); mutex_enter(&LRU_list_mutex); - if (srv_buffer_pool_shm_key) { - /* Cannot support shrink */ - goto func_done; - } - shrink_again: if (buf_pool->n_chunks <= 1) { @@ -2003,11 +1551,6 @@ void buf_pool_resize(void) /*=================*/ { - if (srv_buffer_pool_shm_key) { - /* Cannot support resize */ - return; - } - //buf_pool_mutex_enter(); mutex_enter(&LRU_list_mutex); @@ -2968,6 +2511,30 @@ wait_until_unfixed: bytes. */ UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page); #endif +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + if (mode == BUF_GET_IF_IN_POOL && ibuf_debug) { + /* Try to evict the block from the buffer pool, to use the + insert buffer as much as possible. */ + + if (buf_LRU_free_block(&block->page, TRUE, NULL) + == BUF_LRU_FREED) { + buf_pool_mutex_exit(); + mutex_exit(&block->mutex); + fprintf(stderr, + "innodb_change_buffering_debug evict %u %u\n", + (unsigned) space, (unsigned) offset); + return(NULL); + } else if (buf_flush_page_try(block)) { + fprintf(stderr, + "innodb_change_buffering_debug flush %u %u\n", + (unsigned) space, (unsigned) offset); + guess = block; + goto loop; + } + + /* Failed to evict the page; change it directly */ + } +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ buf_block_buf_fix_inc(block, file, line); diff --git a/storage/xtradb/buf/buf0flu.c b/storage/xtradb/buf/buf0flu.c index 0a03d583549..0ef91137aef 100644 --- a/storage/xtradb/buf/buf0flu.c +++ b/storage/xtradb/buf/buf0flu.c @@ -129,11 +129,16 @@ buf_flush_delete_from_flush_rbt( buf_page_t* bpage) /*!< in: bpage to be removed. */ { +#ifdef UNIV_DEBUG ibool ret = FALSE; +#endif /* UNIV_DEBUG */ //ut_ad(buf_pool_mutex_own()); ut_ad(mutex_own(&flush_list_mutex)); - ret = rbt_delete(buf_pool->flush_rbt, &bpage); +#ifdef UNIV_DEBUG + ret = +#endif /* UNIV_DEBUG */ + rbt_delete(buf_pool->flush_rbt, &bpage); ut_ad(ret); } @@ -1059,6 +1064,82 @@ buf_flush_write_block_low( } } +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************//** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_page(). +@return TRUE if the page was flushed and the mutexes released */ +UNIV_INTERN +ibool +buf_flush_page_try( +/*===============*/ + buf_block_t* block) /*!< in/out: buffer control block */ +{ + ut_ad(buf_pool_mutex_own()); + ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE); + ut_ad(mutex_own(&block->mutex)); + + if (!buf_flush_ready_for_flush(&block->page, BUF_FLUSH_LRU)) { + return(FALSE); + } + + if (buf_pool->n_flush[BUF_FLUSH_LRU] > 0 + || buf_pool->init_flush[BUF_FLUSH_LRU]) { + /* There is already a flush batch of the same type running */ + return(FALSE); + } + + buf_pool->init_flush[BUF_FLUSH_LRU] = TRUE; + + buf_page_set_io_fix(&block->page, BUF_IO_WRITE); + + buf_page_set_flush_type(&block->page, BUF_FLUSH_LRU); + + if (buf_pool->n_flush[BUF_FLUSH_LRU]++ == 0) { + + os_event_reset(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + /* VERY IMPORTANT: + Because any thread may call the LRU flush, even when owning + locks on pages, to avoid deadlocks, we must make sure that the + s-lock is acquired on the page without waiting: this is + accomplished because buf_flush_ready_for_flush() must hold, + and that requires the page not to be bufferfixed. */ + + rw_lock_s_lock_gen(&block->lock, BUF_IO_WRITE); + + /* Note that the s-latch is acquired before releasing the + buf_pool mutex: this ensures that the latch is acquired + immediately. */ + + mutex_exit(&block->mutex); + buf_pool_mutex_exit(); + + /* Even though block is not protected by any mutex at this + point, it is safe to access block, because it is io_fixed and + oldest_modification != 0. Thus, it cannot be relocated in the + buffer pool or removed from flush_list or LRU_list. */ + + buf_flush_write_block_low(&block->page); + + buf_pool_mutex_enter(); + buf_pool->init_flush[BUF_FLUSH_LRU] = FALSE; + + if (buf_pool->n_flush[BUF_FLUSH_LRU] == 0) { + /* The running flush batch has ended */ + os_event_set(buf_pool->no_flush[BUF_FLUSH_LRU]); + } + + buf_pool_mutex_exit(); + buf_flush_buffered_writes(); + + return(TRUE); +} +# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /********************************************************************//** Writes a flushable page asynchronously from the buffer pool to a file. NOTE: in simulated aio we must call @@ -1303,7 +1384,6 @@ buf_flush_batch( buf_page_t* bpage; buf_page_t* prev_bpage = NULL; ulint page_count = 0; - ulint old_page_count; ulint space; ulint offset; ulint remaining = 0; @@ -1396,15 +1476,9 @@ flush_next: mutex_exit(&LRU_list_mutex); } - old_page_count = page_count; - /* Try to flush also all the neighbors */ page_count += buf_flush_try_neighbors( space, offset, flush_type, srv_flush_neighbor_pages); - /* fprintf(stderr, - "Flush type %lu, page no %lu, neighb %lu\n", - flush_type, offset, - page_count - old_page_count); */ //buf_pool_mutex_enter(); if (flush_type == BUF_FLUSH_LRU) { diff --git a/storage/xtradb/dict/dict0crea.c b/storage/xtradb/dict/dict0crea.c index a6d0e11740a..992a7000eda 100644 --- a/storage/xtradb/dict/dict0crea.c +++ b/storage/xtradb/dict/dict0crea.c @@ -693,7 +693,6 @@ dict_create_index_tree_step( { dict_index_t* index; dict_table_t* sys_indexes; - dict_table_t* table; dtuple_t* search_tuple; ulint zip_size; btr_pcur_t pcur; @@ -702,7 +701,6 @@ dict_create_index_tree_step( ut_ad(mutex_own(&(dict_sys->mutex))); index = node->index; - table = node->table; sys_indexes = dict_sys->sys_indexes; diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 1d0517f5cc7..40380067bd2 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -4791,7 +4791,6 @@ dict_index_print_low( { ib_int64_t n_vals; ulint i; - const char* type_string; ut_ad(mutex_own(&(dict_sys->mutex))); @@ -4806,14 +4805,6 @@ dict_index_print_low( dict_index_stat_mutex_exit(index); - if (dict_index_is_clust(index)) { - type_string = "clustered index"; - } else if (dict_index_is_unique(index)) { - type_string = "unique index"; - } else { - type_string = "secondary index"; - } - fprintf(stderr, " INDEX: name %s, id %lu %lu, fields %lu/%lu," " uniq %lu, type %lu\n" diff --git a/storage/xtradb/dict/dict0load.c b/storage/xtradb/dict/dict0load.c index 43c0810fe67..19de5bf8264 100644 --- a/storage/xtradb/dict/dict0load.c +++ b/storage/xtradb/dict/dict0load.c @@ -1024,13 +1024,13 @@ err_exit: if (err != DB_SUCCESS) { dict_table_remove_from_cache(table); table = NULL; + } else { + table->fk_max_recusive_level = 0; } } else if (!srv_force_recovery) { dict_table_remove_from_cache(table); table = NULL; } - - table->fk_max_recusive_level = 0; #if 0 if (err != DB_SUCCESS && table != NULL) { diff --git a/storage/xtradb/eval/eval0eval.c b/storage/xtradb/eval/eval0eval.c index 589b0fa1576..dcd416adeee 100644 --- a/storage/xtradb/eval/eval0eval.c +++ b/storage/xtradb/eval/eval0eval.c @@ -384,18 +384,13 @@ eval_notfound( /*==========*/ func_node_t* func_node) /*!< in: function node */ { - que_node_t* arg1; - que_node_t* arg2; sym_node_t* cursor; sel_node_t* sel_node; ibool ibool_val; - arg1 = func_node->args; - arg2 = que_node_get_next(arg1); - ut_ad(func_node->func == PARS_NOTFOUND_TOKEN); - cursor = arg1; + cursor = func_node->args; ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL); diff --git a/storage/xtradb/ha/hash0hash.c b/storage/xtradb/ha/hash0hash.c index 0f4fc55d895..30c304dafcd 100644 --- a/storage/xtradb/ha/hash0hash.c +++ b/storage/xtradb/ha/hash0hash.c @@ -128,70 +128,6 @@ hash_create( } /*************************************************************//** -*/ -UNIV_INTERN -ulint -hash_create_needed( -/*===============*/ - ulint n) -{ - ulint prime; - ulint offset; - - prime = ut_find_prime(n); - - offset = (sizeof(hash_table_t) + 7) / 8; - offset *= 8; - - return(offset + sizeof(hash_cell_t) * prime); -} - -UNIV_INTERN -void -hash_create_init( -/*=============*/ - hash_table_t* table, - ulint n) -{ - ulint prime; - ulint offset; - - prime = ut_find_prime(n); - - offset = (sizeof(hash_table_t) + 7) / 8; - offset *= 8; - - table->array = (hash_cell_t*)(((byte*)table) + offset); - table->n_cells = prime; -# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - table->adaptive = FALSE; -# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - table->n_mutexes = 0; - table->mutexes = NULL; - table->heaps = NULL; - table->heap = NULL; - ut_d(table->magic_n = HASH_TABLE_MAGIC_N); - - /* Initialize the cell array */ - hash_table_clear(table); -} - -UNIV_INTERN -void -hash_create_reuse( -/*==============*/ - hash_table_t* table) -{ - ulint offset; - - offset = (sizeof(hash_table_t) + 7) / 8; - offset *= 8; - - table->array = (hash_cell_t*)(((byte*)table) + offset); - ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); -} - -/*************************************************************//** Frees a hash table. */ UNIV_INTERN void diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ec79c3309f9..42e9c99b95c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -194,7 +194,6 @@ 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_use_sys_stats_table = FALSE; -static my_bool innobase_buffer_pool_shm_checksum = TRUE; static char* internal_innobase_data_file_path = NULL; @@ -2427,7 +2426,6 @@ innobase_change_buffering_inited_ok: srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_checksums = (ibool) innobase_use_checksums; srv_fast_checksum = (ibool) innobase_fast_checksum; - srv_buffer_pool_shm_checksum = (ibool) innobase_buffer_pool_shm_checksum; #ifdef HAVE_LARGE_PAGES if ((os_use_large_pages = (ibool) my_use_large_pages)) @@ -4633,7 +4631,7 @@ build_template( ulint n_requested_fields = 0; ibool fetch_all_in_key = FALSE; ibool fetch_primary_key_cols = FALSE; - ulint i, sql_idx, innodb_idx=0; + ulint sql_idx, innodb_idx=0; /* byte offset of the end of last requested column */ ulint mysql_prefix_len = 0; @@ -4756,17 +4754,18 @@ include_field: n_requested_fields++; templ->col_no = innodb_idx; + templ->clust_rec_field_no = dict_col_get_clust_pos( + &index->table->cols[innodb_idx], clust_index); + ut_ad(templ->clust_rec_field_no != ULINT_UNDEFINED); if (index == clust_index) { - templ->rec_field_no = dict_col_get_clust_pos( - &index->table->cols[innodb_idx], index); + templ->rec_field_no = templ->clust_rec_field_no; } else { templ->rec_field_no = dict_index_get_nth_col_pos( index, innodb_idx); - } - - if (templ->rec_field_no == ULINT_UNDEFINED) { - prebuilt->need_to_access_clustered = TRUE; + if (templ->rec_field_no == ULINT_UNDEFINED) { + prebuilt->need_to_access_clustered = TRUE; + } } if (field->null_ptr) { @@ -4817,12 +4816,10 @@ skip_field: if (index != clust_index && prebuilt->need_to_access_clustered) { /* Change rec_field_no's to correspond to the clustered index record */ - for (i = 0; i < n_requested_fields; i++) { + for (ulint i = 0; i < n_requested_fields; i++) { templ = prebuilt->mysql_template + i; - templ->rec_field_no = dict_col_get_clust_pos( - &index->table->cols[templ->col_no], - clust_index); + templ->rec_field_no = templ->clust_rec_field_no; } } } @@ -6769,8 +6766,8 @@ create_options_are_valid( ? "COMPRESSED" : "DYNAMIC"; - /* These two ROW_FORMATs require - srv_file_per_table and srv_file_format */ + /* These two ROW_FORMATs require srv_file_per_table + and srv_file_format > Antelope */ if (!srv_file_per_table) { push_warning_printf( thd, @@ -6780,7 +6777,6 @@ create_options_are_valid( " requires innodb_file_per_table.", row_format_name); ret = FALSE; - } if (srv_file_format < DICT_TF_FORMAT_ZIP) { @@ -6979,6 +6975,8 @@ ha_innobase::create( ulint ssize, ksize; ulint key_block_size = create_info->key_block_size; + /* Set 'flags' to the correct key_block_size. + It will be zero if key_block_size is an invalid number.*/ for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX; ssize++, ksize <<= 1) { if (key_block_size == ksize) { @@ -7019,10 +7017,10 @@ ha_innobase::create( row_type = form->s->row_type; if (flags) { - /* KEY_BLOCK_SIZE was specified. */ - if (!(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) { - /* ROW_FORMAT was not specified; - default to ROW_FORMAT=COMPRESSED */ + /* if KEY_BLOCK_SIZE was specified on this statement and + ROW_FORMAT was not, automatically change ROW_FORMAT to COMPRESSED.*/ + if ( (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE) + && !(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) { row_type = ROW_TYPE_COMPRESSED; } else if (row_type != ROW_TYPE_COMPRESSED) { /* ROW_FORMAT other than COMPRESSED @@ -7041,7 +7039,7 @@ ha_innobase::create( flags = 0; } } else { - /* No KEY_BLOCK_SIZE */ + /* flags == 0 means no KEY_BLOCK_SIZE.*/ if (row_type == ROW_TYPE_COMPRESSED) { /* ROW_FORMAT=COMPRESSED without KEY_BLOCK_SIZE implies half the @@ -7429,7 +7427,6 @@ innobase_drop_database( ulint len = 0; trx_t* trx; char* ptr; - int error; char* namebuf; THD* thd = current_thd; @@ -7472,7 +7469,7 @@ innobase_drop_database( #else trx = innobase_trx_allocate(thd); #endif - error = row_drop_database_for_mysql(namebuf, trx); + row_drop_database_for_mysql(namebuf, trx); my_free(namebuf, MYF(0)); /* Flush the log to reduce probability that the .frm files and @@ -7937,9 +7934,12 @@ Returns statistics information of the table to the MySQL interpreter, in various fields of the handle object. */ UNIV_INTERN int -ha_innobase::info( -/*==============*/ - uint flag) /*!< in: what information MySQL requests */ +ha_innobase::info_low( +/*==================*/ + uint flag, /*!< in: what information MySQL + requests */ + bool called_from_analyze) /* in: TRUE if called from + ::analyze() */ { dict_table_t* ib_table; dict_index_t* index; @@ -7970,8 +7970,7 @@ ha_innobase::info( ib_table = prebuilt->table; if (flag & HA_STATUS_TIME) { - if ((innobase_stats_on_metadata - || thd_sql_command(user_thd) == SQLCOM_ANALYZE) + if ((called_from_analyze || innobase_stats_on_metadata) && !share->ib_table->is_corrupt) { /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ @@ -8242,6 +8241,18 @@ func_exit: DBUG_RETURN(0); } +/*********************************************************************//** +Returns statistics information of the table to the MySQL interpreter, +in various fields of the handle object. */ +UNIV_INTERN +int +ha_innobase::info( +/*==============*/ + uint flag) /*!< in: what information MySQL requests */ +{ + return(info_low(flag, false /* not called from analyze */)); +} + /**********************************************************************//** Updates index cardinalities of the table, based on 8 random dives into each index tree. This does NOT calculate exact statistics on the table. @@ -8258,7 +8269,8 @@ ha_innobase::analyze( } /* Simply call ::info() with all the flags */ - info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + info_low(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE, + true /* called from analyze */); if (share->ib_table->is_corrupt) { return(HA_ADMIN_CORRUPT); @@ -8567,8 +8579,6 @@ ha_innobase::get_foreign_key_create_info(void) flen = ftell(srv_dict_tmpfile); if (flen < 0) { flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; } /* allocate buffer for the string, and @@ -9341,12 +9351,9 @@ innodb_show_status( mutex_exit(&srv_monitor_file_mutex); - bool result = FALSE; + stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), + STRING_WITH_LEN(""), str, flen); - if (stat_print(thd, innobase_hton_name, (uint) strlen(innobase_hton_name), - STRING_WITH_LEN(""), str, flen)) { - result= TRUE; - } my_free(str, MYF(0)); DBUG_RETURN(FALSE); @@ -9884,7 +9891,11 @@ ha_innobase::innobase_peek_autoinc(void) auto_inc = dict_table_autoinc_read(innodb_table); - ut_a(auto_inc > 0); + if (auto_inc == 0) { + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: AUTOINC next value generation " + "is disabled for '%s'\n", innodb_table->name); + } dict_table_autoinc_unlock(innodb_table); @@ -11394,16 +11405,6 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size, "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", NULL, NULL, 128*1024*1024L, 32*1024*1024L, LONGLONG_MAX, 1024*1024L); -static MYSQL_SYSVAR_UINT(buffer_pool_shm_key, srv_buffer_pool_shm_key, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "[experimental] The key value of shared memory segment for the buffer pool. 0 (default) disables the feature.", - NULL, NULL, 0, 0, INT_MAX32, 0); - -static MYSQL_SYSVAR_BOOL(buffer_pool_shm_checksum, innobase_buffer_pool_shm_checksum, - PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Enable buffer_pool_shm checksum validation (enabled by default).", - NULL, NULL, TRUE); - static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency, PLUGIN_VAR_RQCMDARG, "Helps in performance tuning in heavily concurrent environments.", @@ -11535,6 +11536,13 @@ static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering, innodb_change_buffering_validate, innodb_change_buffering_update, "inserts"); +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, + PLUGIN_VAR_RQCMDARG, + "Debug flags for InnoDB change buffering (0=none)", + NULL, NULL, 0, 0, 1, 0); +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + 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 " @@ -11669,8 +11677,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), MYSQL_SYSVAR(buffer_pool_size), - MYSQL_SYSVAR(buffer_pool_shm_key), - MYSQL_SYSVAR(buffer_pool_shm_checksum), MYSQL_SYSVAR(checksums), MYSQL_SYSVAR(fast_checksum), MYSQL_SYSVAR(commit_concurrency), @@ -11746,6 +11752,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(dict_size_limit), MYSQL_SYSVAR(use_sys_malloc), MYSQL_SYSVAR(change_buffering), +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + MYSQL_SYSVAR(change_buffering_debug), +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), MYSQL_SYSVAR(auto_lru_dump), diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 2c14549cbfc..deb72307df0 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -110,6 +110,7 @@ class ha_innobase: public handler ulint innobase_update_autoinc(ulonglong auto_inc); void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); + int info_low(uint flag, bool called_from_analyze); /* Init values for the class: */ public: diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc index 0f656528315..0793daf7650 100644 --- a/storage/xtradb/handler/i_s.cc +++ b/storage/xtradb/handler/i_s.cc @@ -816,7 +816,7 @@ i_s_innodb_buffer_pool_pages_index_fill( if (fil_page_get_type(frame) == FIL_PAGE_INDEX) { index_id = btr_page_get_index_id(frame); - table->field[0]->store(ut_conv_dulint_to_longlong(index_id)); + table->field[0]->store(ut_conv_dulint_to_longlong(index_id), 0); table->field[1]->store(block->page.space); table->field[2]->store(block->page.offset); table->field[3]->store(page_get_n_recs(frame)); @@ -2248,6 +2248,7 @@ trx_i_s_common_fill_table( deadlock occurs between the mysqld server and mysql client, see http://bugs.mysql.com/29900 ; when that bug is resolved we can enable the DBUG_RETURN(ret) above */ + ret++; // silence a gcc46 warning DBUG_RETURN(0); #endif } diff --git a/storage/xtradb/handler/innodb_patch_info.h b/storage/xtradb/handler/innodb_patch_info.h index e68f12d0fec..38b97411340 100644 --- a/storage/xtradb/handler/innodb_patch_info.h +++ b/storage/xtradb/handler/innodb_patch_info.h @@ -47,6 +47,5 @@ struct innodb_enhancement { {"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"}, {"innodb_sys_tables_sys_indexes","Expose InnoDB SYS_TABLES and SYS_INDEXES schema tables","","http://www.percona.com/docs/wiki/percona-xtradb"}, -{"innodb_buffer_pool_shm","Put buffer pool contents to shared memory segment and reuse it at clean restart [experimental]","","http://www.percona.com/docs/wiki/percona-xtradb"}, {NULL, NULL, NULL, NULL} }; diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c index e01c2d6b800..12dbc29be23 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.c +++ b/storage/xtradb/ibuf/ibuf0ibuf.c @@ -49,6 +49,7 @@ Created 7/19/1997 Heikki Tuuri #include "btr0cur.h" #include "btr0pcur.h" #include "btr0btr.h" +#include "row0upd.h" #include "sync0sync.h" #include "dict0boot.h" #include "fut0lst.h" @@ -170,6 +171,11 @@ access order rules. */ /** Operations that can currently be buffered. */ UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_INSERT; +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/** Flag to control insert buffer debugging. */ +UNIV_INTERN uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /** The insert buffer control structure */ UNIV_INTERN ibuf_t* ibuf = NULL; @@ -2886,9 +2892,80 @@ During merge, inserts to an index page a secondary index entry extracted from the insert buffer. */ static void +ibuf_insert_to_index_page_low( +/*==========================*/ + const dtuple_t* entry, /*!< in: buffered entry to insert */ + buf_block_t* block, /*!< in/out: index page where the buffered + entry should be placed */ + dict_index_t* index, /*!< in: record descriptor */ + mtr_t* mtr, /*!< in/out: mtr */ + page_cur_t* page_cur)/*!< in/out: cursor positioned on the record + after which to insert the buffered entry */ +{ + const page_t* page; + ulint space; + ulint page_no; + ulint zip_size; + const page_t* bitmap_page; + ulint old_bits; + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) { + return; + } + + /* If the record did not fit, reorganize */ + + btr_page_reorganize(block, index, mtr); + page_cur_search(block, index, entry, PAGE_CUR_LE, page_cur); + + /* This time the record must fit */ + + if (UNIV_LIKELY + (page_cur_tuple_insert(page_cur, entry, index, 0, mtr) != NULL)) { + return; + } + + page = buf_block_get_frame(block); + + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: Error: Insert buffer insert fails;" + " page free %lu, dtuple size %lu\n", + (ulong) page_get_max_insert_size(page, 1), + (ulong) rec_get_converted_size(index, entry, 0)); + fputs("InnoDB: Cannot insert index record ", stderr); + dtuple_print(stderr, entry); + fputs("\nInnoDB: The table where this index record belongs\n" + "InnoDB: is now probably corrupt. Please run CHECK TABLE on\n" + "InnoDB: that table.\n", stderr); + + space = page_get_space_id(page); + zip_size = buf_block_get_zip_size(block); + page_no = page_get_page_no(page); + + bitmap_page = ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr); + old_bits = ibuf_bitmap_page_get_bits(bitmap_page, page_no, zip_size, + IBUF_BITMAP_FREE, mtr); + + fprintf(stderr, + "InnoDB: space %lu, page %lu, zip_size %lu, bitmap bits %lu\n", + (ulong) space, (ulong) page_no, + (ulong) zip_size, (ulong) old_bits); + + fputs("InnoDB: Submit a detailed bug report" + " to http://bugs.mysql.com\n", stderr); +} + +/************************************************************************ +During merge, inserts to an index page a secondary index entry extracted +from the insert buffer. */ +static +void ibuf_insert_to_index_page( /*======================*/ - dtuple_t* entry, /*!< in: buffered entry to insert */ + const dtuple_t* entry, /*!< in: buffered entry to insert */ buf_block_t* block, /*!< in/out: index page where the buffered entry should be placed */ dict_index_t* index, /*!< in: record descriptor */ @@ -2898,11 +2975,10 @@ ibuf_insert_to_index_page( ulint low_match; page_t* page = buf_block_get_frame(block); rec_t* rec; - page_t* bitmap_page; - ulint old_bits; ut_ad(ibuf_inside()); ut_ad(dtuple_check_typed(entry)); + ut_ad(!buf_block_align(page)->is_hashed); if (UNIV_UNLIKELY(dict_table_is_comp(index->table) != (ibool)!!page_is_comp(page))) { @@ -2940,71 +3016,86 @@ dump: low_match = page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur); - if (low_match == dtuple_get_n_fields(entry)) { + if (UNIV_UNLIKELY(low_match == dtuple_get_n_fields(entry))) { + mem_heap_t* heap; + upd_t* update; + ulint* offsets; page_zip_des_t* page_zip; rec = page_cur_get_rec(&page_cur); - page_zip = buf_block_get_page_zip(block); - btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr); - } else { - rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr); + /* This is based on + row_ins_sec_index_entry_by_modify(BTR_MODIFY_LEAF). */ + ut_ad(rec_get_deleted_flag(rec, page_is_comp(page))); - if (UNIV_LIKELY(rec != NULL)) { + heap = mem_heap_create(1024); + + offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, + &heap); + update = row_upd_build_sec_rec_difference_binary( + index, entry, rec, NULL, heap); + + page_zip = buf_block_get_page_zip(block); + + if (update->n_fields == 0) { + /* The records only differ in the delete-mark. + Clear the delete-mark, like we did before + Bug #56680 was fixed. */ + btr_cur_del_unmark_for_ibuf(rec, page_zip, mtr); +updated_in_place: + mem_heap_free(heap); return; } - /* If the record did not fit, reorganize */ - - btr_page_reorganize(block, index, mtr); - page_cur_search(block, index, entry, PAGE_CUR_LE, &page_cur); + /* Copy the info bits. Clear the delete-mark. */ + update->info_bits = rec_get_info_bits(rec, page_is_comp(page)); + update->info_bits &= ~REC_INFO_DELETED_FLAG; + + /* We cannot invoke btr_cur_optimistic_update() here, + because we do not have a btr_cur_t or que_thr_t, + as the insert buffer merge occurs at a very low level. */ + if (!row_upd_changes_field_size_or_external(index, offsets, + update) + && (!page_zip || btr_cur_update_alloc_zip( + page_zip, block, index, + rec_offs_size(offsets), FALSE, mtr))) { + /* This is the easy case. Do something similar + to btr_cur_update_in_place(). */ + row_upd_rec_in_place(rec, index, offsets, + update, page_zip); + goto updated_in_place; + } - /* This time the record must fit */ - if (UNIV_UNLIKELY - (!page_cur_tuple_insert(&page_cur, entry, index, - 0, mtr))) { - ulint space; - ulint page_no; - ulint zip_size; + /* A collation may identify values that differ in + storage length. + Some examples (1 or 2 bytes): + utf8_turkish_ci: I = U+0131 LATIN SMALL LETTER DOTLESS I + utf8_general_ci: S = U+00DF LATIN SMALL LETTER SHARP S + utf8_general_ci: A = U+00E4 LATIN SMALL LETTER A WITH DIAERESIS - ut_print_timestamp(stderr); + latin1_german2_ci: SS = U+00DF LATIN SMALL LETTER SHARP S - fprintf(stderr, - " InnoDB: Error: Insert buffer insert" - " fails; page free %lu," - " dtuple size %lu\n", - (ulong) page_get_max_insert_size( - page, 1), - (ulong) rec_get_converted_size( - index, entry, 0)); - fputs("InnoDB: Cannot insert index record ", - stderr); - dtuple_print(stderr, entry); - fputs("\nInnoDB: The table where" - " this index record belongs\n" - "InnoDB: is now probably corrupt." - " Please run CHECK TABLE on\n" - "InnoDB: that table.\n", stderr); + Examples of a character (3-byte UTF-8 sequence) + identified with 2 or 4 characters (1-byte UTF-8 sequences): - space = page_get_space_id(page); - zip_size = buf_block_get_zip_size(block); - page_no = page_get_page_no(page); + utf8_unicode_ci: 'II' = U+2171 SMALL ROMAN NUMERAL TWO + utf8_unicode_ci: '(10)' = U+247D PARENTHESIZED NUMBER TEN + */ - bitmap_page = ibuf_bitmap_get_map_page( - space, page_no, zip_size, mtr); - old_bits = ibuf_bitmap_page_get_bits( - bitmap_page, page_no, zip_size, - IBUF_BITMAP_FREE, mtr); + /* Delete the different-length record, and insert the + buffered one. */ - fprintf(stderr, - "InnoDB: space %lu, page %lu," - " zip_size %lu, bitmap bits %lu\n", - (ulong) space, (ulong) page_no, - (ulong) zip_size, (ulong) old_bits); + lock_rec_store_on_page_infimum(block, rec); + page_cur_delete_rec(&page_cur, index, offsets, mtr); + page_cur_move_to_prev(&page_cur); + mem_heap_free(heap); - fputs("InnoDB: Submit a detailed bug report" - " to http://bugs.mysql.com\n", stderr); - } + ibuf_insert_to_index_page_low(entry, block, index, mtr, + &page_cur); + lock_rec_restore_from_page_infimum(block, rec, block); + } else { + ibuf_insert_to_index_page_low(entry, block, index, mtr, + &page_cur); } } diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h index e151fdcb563..7f6bff11f84 100644 --- a/storage/xtradb/include/btr0cur.h +++ b/storage/xtradb/include/btr0cur.h @@ -242,6 +242,22 @@ btr_cur_pessimistic_insert( que_thr_t* thr, /*!< in: query thread or NULL */ mtr_t* mtr); /*!< in: mtr */ /*************************************************************//** +See if there is enough place in the page modification log to log +an update-in-place. +@return TRUE if enough place */ +UNIV_INTERN +ibool +btr_cur_update_alloc_zip( +/*=====================*/ + page_zip_des_t* page_zip,/*!< in/out: compressed page */ + buf_block_t* block, /*!< in/out: buffer page */ + dict_index_t* index, /*!< in: the index corresponding to the block */ + ulint length, /*!< in: size needed */ + ibool create, /*!< in: TRUE=delete-and-insert, + FALSE=update-in-place */ + mtr_t* mtr) /*!< in: mini-transaction */ + __attribute__((nonnull, warn_unused_result)); +/*************************************************************//** Updates a record when the update causes no size changes in its fields. @return DB_SUCCESS or error number */ UNIV_INTERN diff --git a/storage/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h index e06927f42f0..d6cc63bb6af 100644 --- a/storage/xtradb/include/buf0buf.h +++ b/storage/xtradb/include/buf0buf.h @@ -36,7 +36,6 @@ Created 11/5/1995 Heikki Tuuri #include "ut0rbt.h" #ifndef UNIV_HOTBACKUP #include "os0proc.h" -#include "srv0srv.h" /** @name Modes for buf_page_get_gen */ /* @{ */ @@ -1302,10 +1301,7 @@ struct buf_block_struct{ /**********************************************************************//** Compute the hash fold value for blocks in buf_pool->zip_hash. */ /* @{ */ -/* the fold should be relative when srv_buffer_pool_shm_key is enabled */ -#define BUF_POOL_ZIP_FOLD_PTR(ptr) (!srv_buffer_pool_shm_key\ - ?((ulint) (ptr) / UNIV_PAGE_SIZE)\ - :((ulint) ((byte*)ptr - (byte*)(buf_pool->chunks->blocks->frame)) / UNIV_PAGE_SIZE)) +#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE) #define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame) #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b)) /* @} */ diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h index 2f7108fda1b..85957f5c448 100644 --- a/storage/xtradb/include/buf0flu.h +++ b/storage/xtradb/include/buf0flu.h @@ -76,6 +76,20 @@ buf_flush_init_for_writing( ib_uint64_t newest_lsn); /*!< in: newest modification lsn to the page */ #ifndef UNIV_HOTBACKUP +# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/********************************************************************//** +Writes a flushable page asynchronously from the buffer pool to a file. +NOTE: buf_pool_mutex and block->mutex must be held upon entering this +function, and they will be released by this function after flushing. +This is loosely based on buf_flush_batch() and buf_flush_page(). +@return TRUE if the page was flushed and the mutexes released */ +UNIV_INTERN +ibool +buf_flush_page_try( +/*===============*/ + buf_block_t* block) /*!< in/out: buffer control block */ + __attribute__((nonnull, warn_unused_result)); +# endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ /*******************************************************************//** This utility flushes dirty blocks from the end of the LRU list or flush_list. NOTE 1: in the case of an LRU flush the calling thread may own latches to diff --git a/storage/xtradb/include/hash0hash.h b/storage/xtradb/include/hash0hash.h index 492c767acc4..b17c21a45ef 100644 --- a/storage/xtradb/include/hash0hash.h +++ b/storage/xtradb/include/hash0hash.h @@ -49,28 +49,6 @@ hash_table_t* hash_create( /*========*/ ulint n); /*!< in: number of array cells */ - -/*************************************************************//** -*/ -UNIV_INTERN -ulint -hash_create_needed( -/*===============*/ - ulint n); - -UNIV_INTERN -void -hash_create_init( -/*=============*/ - hash_table_t* table, - ulint n); - -UNIV_INTERN -void -hash_create_reuse( -/*==============*/ - hash_table_t* table); - #ifndef UNIV_HOTBACKUP /*************************************************************//** Creates a mutex array to protect a hash table. */ @@ -350,33 +328,6 @@ do {\ }\ } while (0) -/********************************************************************//** -Align nodes with moving location.*/ -#define HASH_OFFSET(TABLE, NODE_TYPE, PTR_NAME, FADDR, FOFFSET, BOFFSET) \ -do {\ - ulint i2222;\ - ulint cell_count2222;\ -\ - cell_count2222 = hash_get_n_cells(TABLE);\ -\ - for (i2222 = 0; i2222 < cell_count2222; i2222++) {\ - NODE_TYPE* node2222;\ -\ - if ((TABLE)->array[i2222].node) \ - (TABLE)->array[i2222].node = (void*)((byte*)(TABLE)->array[i2222].node \ - + (((TABLE)->array[i2222].node > (void*)FADDR)?FOFFSET:BOFFSET));\ - node2222 = HASH_GET_FIRST((TABLE), i2222);\ -\ - while (node2222) {\ - if (node2222->PTR_NAME) \ - node2222->PTR_NAME = (void*)((byte*)(node2222->PTR_NAME) \ - + ((((void*)node2222->PTR_NAME) > (void*)FADDR)?FOFFSET:BOFFSET));\ -\ - node2222 = node2222->PTR_NAME;\ - }\ - }\ -} while (0) - /************************************************************//** Gets the mutex index for a fold value in a hash table. @return mutex number */ diff --git a/storage/xtradb/include/ibuf0ibuf.h b/storage/xtradb/include/ibuf0ibuf.h index 8aa21fb9d95..f8cc4471d43 100644 --- a/storage/xtradb/include/ibuf0ibuf.h +++ b/storage/xtradb/include/ibuf0ibuf.h @@ -48,6 +48,11 @@ typedef enum { /** Operations that can currently be buffered. */ extern ibuf_use_t ibuf_use; +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG +/** Flag to control insert buffer debugging. */ +extern uint ibuf_debug; +#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ + /** The insert buffer control structure */ extern ibuf_t* ibuf; diff --git a/storage/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h index 582cef6f803..fd46bd7db87 100644 --- a/storage/xtradb/include/os0proc.h +++ b/storage/xtradb/include/os0proc.h @@ -32,11 +32,6 @@ Created 9/30/1995 Heikki Tuuri #ifdef UNIV_LINUX #include <sys/ipc.h> #include <sys/shm.h> -#else -# if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H -#include <sys/ipc.h> -#include <sys/shm.h> -# endif #endif typedef void* os_process_t; @@ -75,29 +70,6 @@ os_mem_free_large( ulint size); /*!< in: size returned by os_mem_alloc_large() */ - -/****************************************************************//** -Allocates or attaches and reuses shared memory segment. -The content is not cleared automatically. -@return allocated memory */ -UNIV_INTERN -void* -os_shm_alloc( -/*=========*/ - ulint* n, /*!< in/out: number of bytes */ - uint key, - ibool* is_new); - -/****************************************************************//** -Detach shared memory segment. */ -UNIV_INTERN -void -os_shm_free( -/*========*/ - void *ptr, /*!< in: pointer returned by - os_shm_alloc() */ - ulint size); /*!< in: size returned by - os_shm_alloc() */ #ifndef UNIV_NONINL #include "os0proc.ic" #endif diff --git a/storage/xtradb/include/os0sync.h b/storage/xtradb/include/os0sync.h index c230a03b6db..2cf9ea0ec84 100644 --- a/storage/xtradb/include/os0sync.h +++ b/storage/xtradb/include/os0sync.h @@ -330,7 +330,7 @@ amount of increment. */ Returns the old value of *ptr, atomically sets *ptr to new_val */ # define os_atomic_test_and_set_byte(ptr, new_val) \ - __sync_lock_test_and_set(ptr, new_val) + __sync_lock_test_and_set(ptr, (byte) new_val) #elif defined(HAVE_IB_SOLARIS_ATOMICS) diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index f8fab59ef80..141f4beb81e 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -535,6 +535,10 @@ struct mysql_row_templ_struct { Innobase record in the current index; not defined if template_type is ROW_MYSQL_WHOLE_ROW */ + ulint clust_rec_field_no; /*!< field number of the column in an + Innobase record in the clustered index; + not defined if template_type is + ROW_MYSQL_WHOLE_ROW */ ulint mysql_col_offset; /*!< offset of the column in the MySQL row format */ ulint mysql_col_len; /*!< length of the column in the MySQL diff --git a/storage/xtradb/include/row0upd.h b/storage/xtradb/include/row0upd.h index 635d746d5a1..4e2de9bd2ec 100644 --- a/storage/xtradb/include/row0upd.h +++ b/storage/xtradb/include/row0upd.h @@ -167,8 +167,11 @@ row_upd_changes_field_size_or_external( const upd_t* update);/*!< in: update vector */ #endif /* !UNIV_HOTBACKUP */ /***********************************************************//** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ UNIV_INTERN void row_upd_rec_in_place( diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index f4c9704741c..8148dffd13b 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -159,10 +159,6 @@ extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */ extern ulint srv_mem_pool_size; extern ulint srv_lock_table_size; -extern uint srv_buffer_pool_shm_key; -extern ibool srv_buffer_pool_shm_is_reused; -extern ibool srv_buffer_pool_shm_checksum; - extern ibool srv_thread_concurrency_timer_based; extern ulint srv_n_file_io_threads; diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 8691e3cf337..487c291ef80 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -46,8 +46,8 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 12 -#define PERCONA_INNODB_VERSION 12.1 +#define INNODB_VERSION_BUGFIX 13 +#define PERCONA_INNODB_VERSION 11.6 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/storage/xtradb/include/ut0lst.h b/storage/xtradb/include/ut0lst.h index 245dfc226c3..7b15c052978 100644 --- a/storage/xtradb/include/ut0lst.h +++ b/storage/xtradb/include/ut0lst.h @@ -257,48 +257,5 @@ do { \ ut_a(ut_list_node_313 == NULL); \ } while (0) -/********************************************************************//** -Align nodes with moving location. -@param NAME the name of the list -@param TYPE node type -@param BASE base node (not a pointer to it) -@param OFFSET offset moved */ -#define UT_LIST_OFFSET(NAME, TYPE, BASE, FADDR, FOFFSET, BOFFSET) \ -do { \ - ulint ut_list_i_313; \ - TYPE* ut_list_node_313; \ - \ - if ((BASE).start) \ - (BASE).start = (void*)((byte*)((BASE).start) \ - + (((void*)((BASE).start) > (void*)FADDR)?FOFFSET:BOFFSET));\ - if ((BASE).end) \ - (BASE).end = (void*)((byte*)((BASE).end) \ - + (((void*)((BASE).end) > (void*)FADDR)?FOFFSET:BOFFSET));\ - \ - ut_list_node_313 = (BASE).start; \ - \ - for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \ - ut_a(ut_list_node_313); \ - if ((ut_list_node_313->NAME).prev) \ - (ut_list_node_313->NAME).prev = (void*)((byte*)((ut_list_node_313->NAME).prev)\ - + (((void*)((ut_list_node_313->NAME).prev) > (void*)FADDR)?FOFFSET:BOFFSET));\ - if ((ut_list_node_313->NAME).next) \ - (ut_list_node_313->NAME).next = (void*)((byte*)((ut_list_node_313->NAME).next)\ - + (((void*)((ut_list_node_313->NAME).next)> (void*)FADDR)?FOFFSET:BOFFSET));\ - ut_list_node_313 = (ut_list_node_313->NAME).next; \ - } \ - \ - ut_a(ut_list_node_313 == NULL); \ - \ - ut_list_node_313 = (BASE).end; \ - \ - for (ut_list_i_313 = (BASE).count; ut_list_i_313--; ) { \ - ut_a(ut_list_node_313); \ - ut_list_node_313 = (ut_list_node_313->NAME).prev; \ - } \ - \ - ut_a(ut_list_node_313 == NULL); \ -} while (0) - #endif diff --git a/storage/xtradb/include/ut0rnd.ic b/storage/xtradb/include/ut0rnd.ic index c2043660efd..d17036d83fc 100644 --- a/storage/xtradb/include/ut0rnd.ic +++ b/storage/xtradb/include/ut0rnd.ic @@ -85,9 +85,6 @@ ut_rnd_gen_ulint(void) /*==================*/ { ulint rnd; - ulint n_bits; - - n_bits = 8 * sizeof(ulint); ut_rnd_ulint_counter = UT_RND1 * ut_rnd_ulint_counter + UT_RND2; diff --git a/storage/xtradb/log/log0recv.c b/storage/xtradb/log/log0recv.c index 200b3b088a7..2aaffe4c031 100644 --- a/storage/xtradb/log/log0recv.c +++ b/storage/xtradb/log/log0recv.c @@ -567,10 +567,8 @@ recv_synchronize_groups( ib_uint64_t start_lsn; ib_uint64_t end_lsn; ib_uint64_t recovered_lsn; - ib_uint64_t limit_lsn; recovered_lsn = recv_sys->recovered_lsn; - limit_lsn = recv_sys->limit_lsn; /* Read the last recovered log block to the recovery system buffer: the block is always incomplete */ @@ -2901,7 +2899,6 @@ recv_init_crash_recovery(void) /*==========================*/ { ut_a(!recv_needed_recovery); - ut_a(!srv_buffer_pool_shm_is_reused); recv_needed_recovery = TRUE; @@ -2964,7 +2961,9 @@ recv_recovery_from_checkpoint_start_func( ib_uint64_t old_scanned_lsn; ib_uint64_t group_scanned_lsn; ib_uint64_t contiguous_lsn; +#ifdef UNIV_LOG_ARCHIVE ib_uint64_t archived_lsn; +#endif /* UNIV_LOG_ARCHIVE */ byte* buf; byte* log_hdr_buf; byte log_hdr_buf_base[LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE]; @@ -3022,7 +3021,9 @@ recv_recovery_from_checkpoint_start_func( checkpoint_lsn = mach_read_ull(buf + LOG_CHECKPOINT_LSN); checkpoint_no = mach_read_ull(buf + LOG_CHECKPOINT_NO); +#ifdef UNIV_LOG_ARCHIVE archived_lsn = mach_read_ull(buf + LOG_CHECKPOINT_ARCHIVED_LSN); +#endif /* UNIV_LOG_ARCHIVE */ /* Read the first log file header to print a note if this is a recovery from a restored InnoDB Hot Backup */ diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index 48d796c38e1..7d47203e992 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -1222,10 +1222,12 @@ UNIV_INTERN void os_file_set_nocache( /*================*/ - int fd, /*!< in: file descriptor to alter */ - const char* file_name, /*!< in: file name, used in the - diagnostic message */ - const char* operation_name) /*!< in: "open" or "create"; used in the + int fd /*!< in: file descriptor to alter */ + __attribute__((unused)), + const char* file_name /*!< in: used in the diagnostic message */ + __attribute__((unused)), + const char* operation_name __attribute__((unused))) + /*!< in: "open" or "create"; used in the diagnostic message */ { /* some versions of Solaris may not have DIRECTIO_ON */ @@ -1407,8 +1409,6 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; - const char* type_str = NULL; - const char* purpose_str = NULL; try_again: ut_a(name); @@ -1428,26 +1428,9 @@ try_again: ut_error; } - if (type == OS_LOG_FILE) { - type_str = "LOG"; - } else if (type == OS_DATA_FILE) { - type_str = "DATA"; - } else { - ut_error; - } - - if (purpose == OS_FILE_AIO) { - purpose_str = "AIO"; - } else if (purpose == OS_FILE_NORMAL) { - purpose_str = "NORMAL"; - } else { - ut_error; - } + ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE); + ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL); -#if 0 - fprintf(stderr, "Opening file %s, mode %s, type %s, purpose %s\n", - name, mode_str, type_str, purpose_str); -#endif #ifdef O_SYNC /* We let O_SYNC only affect log files; note that we map O_DSYNC to O_SYNC because the datasync options seemed to corrupt files in 2001 @@ -2374,7 +2357,10 @@ _os_file_read( ulint i; #endif /* !UNIV_HOTBACKUP */ + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2498,7 +2484,10 @@ os_file_read_no_error_handling( ulint i; #endif /* !UNIV_HOTBACKUP */ + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_reads++; os_bytes_read_since_printout += n; @@ -2628,7 +2617,10 @@ os_file_write( ulint i; #endif /* !UNIV_HOTBACKUP */ - ut_a((offset & 0xFFFFFFFF) == offset); + /* On 64-bit Windows, ulint is 64 bits. But offset and n should be + no more than 32 bits. */ + ut_a((offset & 0xFFFFFFFFUL) == offset); + ut_a((n & 0xFFFFFFFFUL) == n); os_n_file_writes++; @@ -3398,16 +3390,17 @@ os_aio_array_reserve_slot( offset */ ulint offset_high, /*!< in: most significant 32 bits of offset */ - ulint len, /*!< in: length of the block to read or write */ - trx_t* trx) + ulint len) /*!< in: length of the block to read or write */ { os_aio_slot_t* slot; -#ifdef WIN_ASYNC_IO - OVERLAPPED* control; -#endif ulint i; ulint slots_per_seg; ulint local_seg; +#ifdef WIN_ASYNC_IO + OVERLAPPED* control; + + ut_a((len & 0xFFFFFFFFUL) == len); +#endif /* No need of a mutex. Only reading constant fields */ slots_per_seg = array->n_slots / array->n_segments; @@ -3709,6 +3702,9 @@ os_aio( ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(os_aio_validate()); +#ifdef WIN_ASYNC_IO + ut_ad((n & 0xFFFFFFFFUL) == n); +#endif wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); @@ -3766,7 +3762,7 @@ try_again: trx->io_read += n; } slot = os_aio_array_reserve_slot(type, array, message1, message2, file, - name, buf, offset, offset_high, n, trx); + name, buf, offset, offset_high, n); if (type == OS_FILE_READ) { if (os_aio_use_native_aio) { #ifdef WIN_ASYNC_IO @@ -3954,16 +3950,18 @@ os_aio_windows_handle( /* retry failed read/write operation synchronously. No need to hold array->mutex. */ + ut_a((slot->len & 0xFFFFFFFFUL) == slot->len); + switch (slot->type) { case OS_FILE_WRITE: ret = WriteFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; case OS_FILE_READ: ret = ReadFile(slot->file, slot->buf, - slot->len, &len, + (DWORD) slot->len, &len, &(slot->control)); break; diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c index 4567d96b6f4..48922886f23 100644 --- a/storage/xtradb/os/os0proc.c +++ b/storage/xtradb/os/os0proc.c @@ -229,173 +229,3 @@ os_mem_free_large( } #endif } - -/****************************************************************//** -Allocates or attaches and reuses shared memory segment. -The content is not cleared automatically. -@return allocated memory */ -UNIV_INTERN -void* -os_shm_alloc( -/*=========*/ - ulint* n, /*!< in/out: number of bytes */ - uint key, - ibool* is_new) -{ - void* ptr; -#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H - ulint size; - int shmid; - - *is_new = FALSE; - fprintf(stderr, - "InnoDB: The shared memory segment containing the buffer pool is: key %#x (%d).\n", - key, key); -# if defined HAVE_LARGE_PAGES && defined UNIV_LINUX - if (!os_use_large_pages || !os_large_page_size) { - goto skip; - } - - /* Align block size to os_large_page_size */ - ut_ad(ut_is_2pow(os_large_page_size)); - size = ut_2pow_round(*n + (os_large_page_size - 1), - os_large_page_size); - - shmid = shmget((key_t)key, (size_t)size, - IPC_CREAT | IPC_EXCL | SHM_HUGETLB | SHM_R | SHM_W); - if (shmid < 0) { - if (errno == EEXIST) { - fprintf(stderr, - "InnoDB: HugeTLB: The shared memory segment exists.\n"); - shmid = shmget((key_t)key, (size_t)size, - SHM_HUGETLB | SHM_R | SHM_W); - if (shmid < 0) { - fprintf(stderr, - "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n", - size, errno); - goto skip; - } else { - fprintf(stderr, - "InnoDB: HugeTLB: The existent shared memory segment is used.\n"); - } - } else { - fprintf(stderr, - "InnoDB: HugeTLB: Warning: Failed to allocate %lu bytes. (new) errno %d\n", - size, errno); - goto skip; - } - } else { - *is_new = TRUE; - fprintf(stderr, - "InnoDB: HugeTLB: A new shared memory segment has been created .\n"); - } - - ptr = shmat(shmid, NULL, 0); - if (ptr == (void *)-1) { - fprintf(stderr, - "InnoDB: HugeTLB: Warning: Failed to attach shared memory segment, errno %d\n", - errno); - ptr = NULL; - } - - if (ptr) { - *n = size; - os_fast_mutex_lock(&ut_list_mutex); - ut_total_allocated_memory += size; - os_fast_mutex_unlock(&ut_list_mutex); - UNIV_MEM_ALLOC(ptr, size); - return(ptr); - } -skip: - *is_new = FALSE; -# endif /* HAVE_LARGE_PAGES && defined UNIV_LINUX */ -# ifdef HAVE_GETPAGESIZE - size = getpagesize(); -# else - size = UNIV_PAGE_SIZE; -# endif - /* Align block size to system page size */ - ut_ad(ut_is_2pow(size)); - size = *n = ut_2pow_round(*n + (size - 1), size); - - shmid = shmget((key_t)key, (size_t)size, - IPC_CREAT | IPC_EXCL | SHM_R | SHM_W); - if (shmid < 0) { - if (errno == EEXIST) { - fprintf(stderr, - "InnoDB: A shared memory segment containing the buffer pool seems to already exist.\n"); - shmid = shmget((key_t)key, (size_t)size, - SHM_R | SHM_W); - if (shmid < 0) { - fprintf(stderr, - "InnoDB: Warning: Failed to allocate %lu bytes. (reuse) errno %d\n", - size, errno); - ptr = NULL; - goto end; - } else { - fprintf(stderr, - "InnoDB: The existent shared memory segment is used.\n"); - } - } else { - fprintf(stderr, - "InnoDB: Warning: Failed to allocate %lu bytes. (new) errno %d\n", - size, errno); - ptr = NULL; - goto end; - } - } else { - *is_new = TRUE; - fprintf(stderr, - "InnoDB: A new shared memory segment has been created.\n"); - } - - ptr = shmat(shmid, NULL, 0); - if (ptr == (void *)-1) { - fprintf(stderr, - "InnoDB: Warning: Failed to attach shared memory segment, errno %d\n", - errno); - ptr = NULL; - } - - if (ptr) { - *n = size; - os_fast_mutex_lock(&ut_list_mutex); - ut_total_allocated_memory += size; - os_fast_mutex_unlock(&ut_list_mutex); - UNIV_MEM_ALLOC(ptr, size); - } -end: -#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */ - fprintf(stderr, "InnoDB: shared memory segment is not supported.\n"); - ptr = NULL; -#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */ - return(ptr); -} - -/****************************************************************//** -Detach shared memory segment. */ -UNIV_INTERN -void -os_shm_free( -/*========*/ - void *ptr, /*!< in: pointer returned by - os_shm_alloc() */ - ulint size) /*!< in: size returned by - os_shm_alloc() */ -{ - os_fast_mutex_lock(&ut_list_mutex); - ut_a(ut_total_allocated_memory >= size); - os_fast_mutex_unlock(&ut_list_mutex); - -#if defined HAVE_SYS_IPC_H && HAVE_SYS_SHM_H - if (!shmdt(ptr)) { - os_fast_mutex_lock(&ut_list_mutex); - ut_a(ut_total_allocated_memory >= size); - ut_total_allocated_memory -= size; - os_fast_mutex_unlock(&ut_list_mutex); - UNIV_MEM_FREE(ptr, size); - } -#else /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */ - fprintf(stderr, "InnoDB: shared memory segment is not supported.\n"); -#endif /* HAVE_SYS_IPC_H && HAVE_SYS_SHM_H */ -} diff --git a/storage/xtradb/plug.in b/storage/xtradb/plug.in index 67f25755762..b68b59725d4 100644 --- a/storage/xtradb/plug.in +++ b/storage/xtradb/plug.in @@ -141,10 +141,11 @@ MYSQL_PLUGIN_ACTIONS(xtradb, [ AC_MSG_CHECKING(whether Solaris libc atomic functions are available) # either define HAVE_IB_SOLARIS_ATOMICS or not - AC_CHECK_FUNCS(atomic_add_long \ + AC_CHECK_FUNCS(atomic_cas_ulong \ atomic_cas_32 \ atomic_cas_64 \ - atomic_cas_ulong, + atomic_add_long_nv \ + atomic_swap_uchar, AC_DEFINE([HAVE_IB_SOLARIS_ATOMICS], [1], [Define to 1 if Solaris libc atomic functions \ diff --git a/storage/xtradb/que/que0que.c b/storage/xtradb/que/que0que.c index 5c85a04d139..9c1d61c1731 100644 --- a/storage/xtradb/que/que0que.c +++ b/storage/xtradb/que/que0que.c @@ -1298,18 +1298,13 @@ que_run_threads_low( que_thr_t* thr) /*!< in: query thread */ { que_thr_t* next_thr; - ulint cumul_resource; ulint loop_count; ut_ad(thr->state == QUE_THR_RUNNING); ut_a(thr_get_trx(thr)->error_state == DB_SUCCESS); ut_ad(!mutex_own(&kernel_mutex)); - /* cumul_resource counts how much resources the OS thread (NOT the - query thread) has spent in this function */ - loop_count = QUE_MAX_LOOPS_WITHOUT_CHECK; - cumul_resource = 0; loop: /* Check that there is enough space in the log to accommodate possible log entries by this query step; if the operation can touch diff --git a/storage/xtradb/row/row0mysql.c b/storage/xtradb/row/row0mysql.c index 56754404b65..e9b272abab4 100644 --- a/storage/xtradb/row/row0mysql.c +++ b/storage/xtradb/row/row0mysql.c @@ -445,7 +445,7 @@ row_mysql_convert_row_to_innobase( row is used, as row may contain pointers to this record! */ { - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; dfield_t* dfield; ulint i; @@ -1444,7 +1444,12 @@ run_again: srv_n_rows_updated++; } - row_update_statistics_if_needed(prebuilt->table); + /* We update table statistics only if it is a DELETE or UPDATE + 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)) { + row_update_statistics_if_needed(prebuilt->table); + } trx->op_info = ""; @@ -1599,6 +1604,9 @@ row_update_cascade_for_mysql( trx = thr_get_trx(thr); + /* Increment fk_cascade_depth to record the recursive call depth on + a single update/delete that affects multiple tables chained + together with foreign key relations. */ thr->fk_cascade_depth++; if (thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) { @@ -1610,6 +1618,12 @@ run_again: row_upd_step(thr); + /* The recursive call for cascading update/delete happens + in above row_upd_step(), reset the counter once we come + out of the recursive call, so it does not accumulate for + different row deletes */ + thr->fk_cascade_depth = 0; + err = trx->error_state; /* Note that the cascade node is a subnode of another InnoDB @@ -1876,15 +1890,13 @@ err_exit: err = trx->error_state; - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + switch (err) { + case DB_SUCCESS: + break; + case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); - /* TO DO: free table? The code below will dereference - table->name, though. */ - } - switch (err) { - case DB_OUT_OF_FILE_SPACE: ut_print_timestamp(stderr); fputs(" InnoDB: Warning: cannot create table ", stderr); @@ -1899,9 +1911,13 @@ err_exit: break; case DB_DUPLICATE_KEY: + default: /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, NULL); + dict_mem_table_free(table); break; } @@ -2816,15 +2832,6 @@ row_truncate_table_for_mysql( trx->table_id = table->id; - /* Lock all index trees for this table, as we will - truncate the table/index and possibly change their metadata. - All DML/DDL are blocked by table level lock, with - a few exceptions such as queries into information schema - about the table, MySQL could try to access index stats - for this kind of query, we need to use index locks to - sync up */ - dict_table_x_lock_indexes(table); - if (table->space && !table->dir_path_of_temp_table) { /* Discard and create the single-table tablespace. */ ulint space = table->space; @@ -2837,6 +2844,11 @@ row_truncate_table_for_mysql( dict_hdr_get_new_id(NULL, NULL, &space); + /* Lock all index trees for this table. We must + do so after dict_hdr_get_new_id() to preserve + the latch order */ + dict_table_x_lock_indexes(table); + if (space == ULINT_UNDEFINED || fil_create_new_single_table_tablespace( space, table->name, FALSE, flags, @@ -2870,6 +2882,15 @@ row_truncate_table_for_mysql( FIL_IBD_FILE_INITIAL_SIZE, &mtr); mtr_commit(&mtr); } + } else { + /* Lock all index trees for this table, as we will + truncate the table/index and possibly change their metadata. + All DML/DDL are blocked by table level lock, with + a few exceptions such as queries into information schema + about the table, MySQL could try to access index stats + for this kind of query, we need to use index locks to + sync up */ + dict_table_x_lock_indexes(table); } /* scan SYS_INDEXES for all indexes of the table */ diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c index 835af990672..31b255cf2d4 100644 --- a/storage/xtradb/row/row0purge.c +++ b/storage/xtradb/row/row0purge.c @@ -684,7 +684,9 @@ row_purge_step( que_thr_t* thr) /*!< in: query thread */ { purge_node_t* node; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ ut_ad(thr); @@ -692,7 +694,10 @@ row_purge_step( ut_ad(que_node_get_type(node) == QUE_NODE_PURGE); - err = row_purge(node, thr); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + row_purge(node, thr); ut_ad(err == DB_SUCCESS); diff --git a/storage/xtradb/row/row0sel.c b/storage/xtradb/row/row0sel.c index a1511e35435..82ad30bb390 100644 --- a/storage/xtradb/row/row0sel.c +++ b/storage/xtradb/row/row0sel.c @@ -2675,39 +2675,39 @@ row_sel_store_mysql_rec( row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ const rec_t* rec, /*!< in: Innobase record in the index which was described in prebuilt's - template; must be protected by - a page latch */ + template, or in the clustered index; + must be protected by a page latch */ + ibool rec_clust, /*!< in: TRUE if rec is in the + clustered index instead of + prebuilt->index */ const ulint* offsets) /*!< in: array returned by - rec_get_offsets() */ + rec_get_offsets(rec) */ { - mysql_row_templ_t* templ; - mem_heap_t* extern_field_heap = NULL; - mem_heap_t* heap; - const byte* data; - ulint len; - ulint i; + mem_heap_t* extern_field_heap = NULL; + mem_heap_t* heap; + ulint i; ut_ad(prebuilt->mysql_template); ut_ad(prebuilt->default_rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) { mem_heap_free(prebuilt->blob_heap); prebuilt->blob_heap = NULL; } - /* init null bytes with default values as they might be - left uninitialized in some cases and these uninited bytes - might be copied into mysql record buffer that leads to - valgrind warnings */ - memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); - for (i = 0; i < prebuilt->n_template; i++) { - templ = prebuilt->mysql_template + i; + const mysql_row_templ_t*templ = prebuilt->mysql_template + i; + const byte* data; + ulint len; + ulint field_no; + + field_no = rec_clust + ? templ->clust_rec_field_no : templ->rec_field_no; - if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, - templ->rec_field_no))) { + if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, field_no))) { /* Copy an externally stored field to the temporary heap */ @@ -2735,7 +2735,7 @@ row_sel_store_mysql_rec( data = btr_rec_copy_externally_stored_field( rec, offsets, dict_table_zip_size(prebuilt->table), - templ->rec_field_no, &len, heap); + field_no, &len, heap); if (UNIV_UNLIKELY(!data)) { /* The externally stored field @@ -2756,8 +2756,7 @@ row_sel_store_mysql_rec( } else { /* Field is stored in the row. */ - data = rec_get_nth_field(rec, offsets, - templ->rec_field_no, &len); + data = rec_get_nth_field(rec, offsets, field_no, &len); if (UNIV_UNLIKELY(templ->type == DATA_BLOB) && len != UNIV_SQL_NULL) { @@ -3119,7 +3118,7 @@ row_sel_pop_cached_row_for_mysql( row_prebuilt_t* prebuilt) /*!< in: prebuilt struct */ { ulint i; - mysql_row_templ_t* templ; + const mysql_row_templ_t*templ; byte* cached_rec; ut_ad(prebuilt->n_fetch_cached > 0); ut_ad(prebuilt->mysql_prefix_len <= prebuilt->mysql_row_len); @@ -3176,15 +3175,21 @@ ibool row_sel_push_cache_row_for_mysql( /*=============================*/ row_prebuilt_t* prebuilt, /*!< in: prebuilt struct */ - const rec_t* rec, /*!< in: record to push; must - be protected by a page latch */ - const ulint* offsets) /*!< in: rec_get_offsets() */ + const rec_t* rec, /*!< in: record to push, in the index + which was described in prebuilt's + template, or in the clustered index; + must be protected by a page latch */ + ibool rec_clust, /*!< in: TRUE if rec is in the + clustered index instead of + prebuilt->index */ + const ulint* offsets) /*!< in: rec_get_offsets(rec) */ { byte* buf; ulint i; ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE); ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(!rec_get_deleted_flag(rec, rec_offs_comp(offsets))); ut_a(!prebuilt->templ_contains_blob); if (prebuilt->fetch_cache[0] == NULL) { @@ -3213,7 +3218,7 @@ row_sel_push_cache_row_for_mysql( if (UNIV_UNLIKELY(!row_sel_store_mysql_rec( prebuilt->fetch_cache[ prebuilt->n_fetch_cached], - prebuilt, rec, offsets))) { + prebuilt, rec, rec_clust, offsets))) { return(FALSE); } @@ -3356,6 +3361,7 @@ row_search_for_mysql( mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; + ibool table_lock_waited = FALSE; ibool problematic_use = FALSE; rec_offs_init(offsets_); @@ -3399,6 +3405,12 @@ row_search_for_mysql( ut_error; } + /* init null bytes with default values as they might be + left uninitialized in some cases and these uninited bytes + might be copied into mysql record buffer that leads to + valgrind warnings */ + memcpy(buf, prebuilt->default_rec, prebuilt->null_bitmap_len); + #if 0 /* August 19, 2005 by Heikki: temporarily disable this error print until the cursor lock count is done correctly. @@ -3614,7 +3626,8 @@ row_search_for_mysql( ut_ad(!rec_get_deleted_flag(rec, comp)); if (!row_sel_store_mysql_rec(buf, prebuilt, - rec, offsets)) { + rec, FALSE, + offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -3720,6 +3733,61 @@ release_search_latch_if_needed: clust_index = dict_table_get_first_index(index->table); + /* Do some start-of-statement preparations */ + + if (!prebuilt->mysql_has_locked) { + fprintf(stderr, "InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock()\n"); + if (trx->mysql_thd != NULL) { + innobase_mysql_print_thd(stderr, trx->mysql_thd, 600); + } + problematic_use = TRUE; + } +retry_check: + + if (!prebuilt->sql_stat_start) { + /* No need to set an intention lock or assign a read view */ + + if (trx->read_view == NULL + && prebuilt->select_lock_type == LOCK_NONE) { + + fputs("InnoDB: Error: MySQL is trying to" + " perform a consistent read\n" + "InnoDB: but the read view is not assigned!\n", + stderr); + if (problematic_use) { + fprintf(stderr, "InnoDB: It may be caused by calling " + "without ha_innobase::external_lock()\n" + "InnoDB: For the first-aid, avoiding the crash. " + "But it should be fixed ASAP.\n"); + prebuilt->sql_stat_start = TRUE; + goto retry_check; + } + trx_print(stderr, trx, 600); + fputc('\n', stderr); + ut_error; + } + } else if (prebuilt->select_lock_type == LOCK_NONE) { + /* This is a consistent read */ + /* Assign a read view for the query */ + + trx_assign_read_view(trx); + prebuilt->sql_stat_start = FALSE; + } else { +wait_table_again: + err = lock_table(0, index->table, + prebuilt->select_lock_type == LOCK_S + ? LOCK_IS : LOCK_IX, thr); + + if (err != DB_SUCCESS) { + + table_lock_waited = TRUE; + goto lock_table_wait; + } + prebuilt->sql_stat_start = FALSE; + } + + /* Open or restore index cursor position */ + if (UNIV_LIKELY(direction != 0)) { ibool need_to_process = sel_restore_position_for_mysql( &same_user_rec, BTR_SEARCH_LEAF, @@ -3795,59 +3863,6 @@ release_search_latch_if_needed: } } - if (!prebuilt->mysql_has_locked) { - fprintf(stderr, "InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock()\n"); - if (trx->mysql_thd != NULL) { - innobase_mysql_print_thd(stderr, trx->mysql_thd, 600); - } - problematic_use = TRUE; - } -retry_check: - - if (!prebuilt->sql_stat_start) { - /* No need to set an intention lock or assign a read view */ - - if (trx->read_view == NULL - && prebuilt->select_lock_type == LOCK_NONE) { - - fputs("InnoDB: Error: MySQL is trying to" - " perform a consistent read\n" - "InnoDB: but the read view is not assigned!\n", - stderr); - if (problematic_use) { - fprintf(stderr, "InnoDB: It may be caused by calling " - "without ha_innobase::external_lock()\n" - "InnoDB: For the first-aid, avoiding the crash. " - "But it should be fixed ASAP.\n"); - prebuilt->sql_stat_start = TRUE; - goto retry_check; - } - trx_print(stderr, trx, 600); - fputc('\n', stderr); - ut_a(0); - } - } else if (prebuilt->select_lock_type == LOCK_NONE) { - /* This is a consistent read */ - /* Assign a read view for the query */ - - trx_assign_read_view(trx); - prebuilt->sql_stat_start = FALSE; - } else { - ulint lock_mode; - if (prebuilt->select_lock_type == LOCK_S) { - lock_mode = LOCK_IS; - } else { - lock_mode = LOCK_IX; - } - err = lock_table(0, index->table, lock_mode, thr); - - if (err != DB_SUCCESS) { - - goto lock_wait_or_error; - } - prebuilt->sql_stat_start = FALSE; - } - rec_loop: /*-------------------------------------------------------------*/ /* PHASE 4: Look for matching records in a loop */ @@ -4270,7 +4285,6 @@ no_gap_lock: is necessary, because we can only get the undo information via the clustered index record. */ - ut_ad(index != clust_index); ut_ad(!dict_index_is_clust(index)); if (!lock_sec_rec_cons_read_sees( @@ -4386,26 +4400,10 @@ requires_clust_rec: goto next_rec; } - if (prebuilt->need_to_access_clustered) { - - result_rec = clust_rec; - - ut_ad(rec_offs_validate(result_rec, clust_index, - offsets)); - } else { - /* We used 'offsets' for the clust rec, recalculate - them for 'rec' */ - offsets = rec_get_offsets(rec, index, offsets, - ULINT_UNDEFINED, &heap); - result_rec = rec; - } - - /* result_rec can legitimately be delete-marked - now that it has been established that it points to a - clustered index record that exists in the read view. */ + result_rec = clust_rec; + ut_ad(rec_offs_validate(result_rec, clust_index, offsets)); } else { result_rec = rec; - ut_ad(!rec_get_deleted_flag(rec, comp)); } /* We found a qualifying record 'result_rec'. At this point, @@ -4414,6 +4412,7 @@ requires_clust_rec: ut_ad(rec_offs_validate(result_rec, result_rec != rec ? clust_index : index, offsets)); + ut_ad(!rec_get_deleted_flag(result_rec, comp)); /* At this point, the clustered index record is protected by a page latch that was acquired when pcur was positioned. @@ -4438,6 +4437,7 @@ requires_clust_rec: cursor. */ if (!row_sel_push_cache_row_for_mysql(prebuilt, result_rec, + result_rec != rec, offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such @@ -4455,15 +4455,31 @@ requires_clust_rec: goto next_rec; } else { - if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) { + if (UNIV_UNLIKELY + (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE)) { + /* CHECK TABLE: fetch the row */ + + if (result_rec != rec + && !prebuilt->need_to_access_clustered) { + /* We used 'offsets' for the clust + rec, recalculate them for 'rec' */ + offsets = rec_get_offsets(rec, index, offsets, + ULINT_UNDEFINED, + &heap); + result_rec = rec; + } + memcpy(buf + 4, result_rec - rec_offs_extra_size(offsets), rec_offs_size(offsets)); mach_write_to_4(buf, rec_offs_extra_size(offsets) + 4); } else { - if (!row_sel_store_mysql_rec(buf, prebuilt, - result_rec, offsets)) { + /* Returning a row to MySQL */ + + if (!row_sel_store_mysql_rec(buf, prebuilt, result_rec, + result_rec != rec, + offsets)) { /* Only fresh inserts may contain incomplete externally stored columns. Pretend that such records do @@ -4584,6 +4600,7 @@ lock_wait_or_error: btr_pcur_store_position(pcur, &mtr); +lock_table_wait: mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; @@ -4601,6 +4618,14 @@ lock_wait_or_error: thr->lock_state = QUE_THR_LOCK_NOLOCK; mtr_start(&mtr); + /* Table lock waited, go try to obtain table lock + again */ + if (table_lock_waited) { + table_lock_waited = FALSE; + + goto wait_table_again; + } + sel_restore_position_for_mysql(&same_user_rec, BTR_SEARCH_LEAF, pcur, moves_up, &mtr); diff --git a/storage/xtradb/row/row0umod.c b/storage/xtradb/row/row0umod.c index 8464b0f95cc..5998dadd16d 100644 --- a/storage/xtradb/row/row0umod.c +++ b/storage/xtradb/row/row0umod.c @@ -114,12 +114,17 @@ row_undo_mod_clust_low( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; +#ifdef UNIV_DEBUG ibool success; +#endif /* UNIV_DEBUG */ pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); - success = btr_pcur_restore_position(mode, pcur, mtr); +#ifdef UNIV_DEBUG + success = +#endif /* UNIV_DEBUG */ + btr_pcur_restore_position(mode, pcur, mtr); ut_ad(success); diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index 04c3139fcc7..444003ba3f0 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -466,8 +466,11 @@ row_upd_changes_field_size_or_external( #endif /* !UNIV_HOTBACKUP */ /***********************************************************//** -Replaces the new column values stored in the update vector to the record -given. No field size changes are allowed. */ +Replaces the new column values stored in the update vector to the +record given. No field size changes are allowed. This function is +usually invoked on a clustered index. The only use case for a +secondary index is row_ins_sec_index_entry_by_modify() or its +counterpart in ibuf_insert_to_index_page(). */ UNIV_INTERN void row_upd_rec_in_place( diff --git a/storage/xtradb/row/row0vers.c b/storage/xtradb/row/row0vers.c index a4fbb5289aa..b6d35363f08 100644 --- a/storage/xtradb/row/row0vers.c +++ b/storage/xtradb/row/row0vers.c @@ -71,7 +71,9 @@ row_vers_impl_x_locked_off_kernel( warning */ trx_t* trx; ulint rec_del; +#ifdef UNIV_DEBUG ulint err; +#endif /* UNIV_DEBUG */ mtr_t mtr; ulint comp; @@ -169,9 +171,12 @@ row_vers_impl_x_locked_off_kernel( heap2 = heap; heap = mem_heap_create(1024); - err = trx_undo_prev_version_build(clust_rec, &mtr, version, - clust_index, clust_offsets, - heap, &prev_version); +#ifdef UNIV_DEBUG + err = +#endif /* UNIV_DEBUG */ + trx_undo_prev_version_build(clust_rec, &mtr, version, + clust_index, clust_offsets, + heap, &prev_version); mem_heap_free(heap2); /* free version and clust_offsets */ if (prev_version == NULL) { diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 35745072445..637b9e2df28 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -211,11 +211,6 @@ UNIV_INTERN ulint srv_buf_pool_curr_size = 0; UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX; UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX; -/* key value for shm */ -UNIV_INTERN uint srv_buffer_pool_shm_key = 0; -UNIV_INTERN ibool srv_buffer_pool_shm_is_reused = FALSE; -UNIV_INTERN ibool srv_buffer_pool_shm_checksum = TRUE; - /* This parameter is deprecated. Use srv_n_io_[read|write]_threads instead. */ UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX; @@ -1130,7 +1125,7 @@ retry: enter_innodb_with_tickets(trx); return; } - os_atomic_increment_lint(&srv_conc_n_threads, -1); + (void) os_atomic_increment_lint(&srv_conc_n_threads, -1); } if (!has_yielded) { @@ -1160,7 +1155,7 @@ retry: static void srv_conc_exit_innodb_timer_based(trx_t* trx) { - os_atomic_increment_lint(&srv_conc_n_threads, -1); + (void) os_atomic_increment_lint(&srv_conc_n_threads, -1); trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; return; @@ -1367,7 +1362,7 @@ srv_conc_force_enter_innodb( ut_ad(srv_conc_n_threads >= 0); #ifdef HAVE_ATOMIC_BUILTINS if (srv_thread_concurrency_timer_based) { - os_atomic_increment_lint(&srv_conc_n_threads, 1); + (void) os_atomic_increment_lint(&srv_conc_n_threads, 1); trx->declared_to_be_inside_innodb = TRUE; trx->n_tickets_to_enter_innodb = 1; return; diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c index b36faf2d2d7..27804e78a32 100644 --- a/storage/xtradb/srv/srv0start.c +++ b/storage/xtradb/srv/srv0start.c @@ -463,7 +463,6 @@ io_handler_thread( the aio array */ { ulint segment; - ulint i; segment = *((ulint*)arg); @@ -471,7 +470,7 @@ io_handler_thread( fprintf(stderr, "Io handler thread %lu starts, id %lu\n", segment, os_thread_pf(os_thread_get_curr_id())); #endif - for (i = 0;; i++) { + while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) { fil_aio_wait(segment); mutex_enter(&ios_mutex); @@ -479,8 +478,6 @@ io_handler_thread( mutex_exit(&ios_mutex); } - thr_local_free(os_thread_get_curr_id()); - /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. The thread actually never comes here because it is exited in an @@ -1719,8 +1716,6 @@ innobase_start_or_create_for_mysql(void) Note that this is not as heavy weight as it seems. At this point there will be only ONE page in the buf_LRU and there must be no page in the buf_flush list. */ - /* buffer_pool_shm should not be reused when recovery was needed. */ - if (!srv_buffer_pool_shm_is_reused) buf_pool_invalidate(); /* We always try to do a recovery, even if the database had @@ -2093,7 +2088,7 @@ innobase_shutdown_for_mysql(void) #ifdef __NETWARE__ if (!panic_shutdown) #endif - logs_empty_and_mark_files_at_shutdown(); + logs_empty_and_mark_files_at_shutdown(); if (srv_conc_n_threads != 0) { fprintf(stderr, diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c index 9e10f6e943b..5dc6b28d4bf 100644 --- a/storage/xtradb/sync/sync0rw.c +++ b/storage/xtradb/sync/sync0rw.c @@ -248,10 +248,8 @@ rw_lock_create_func( lock->mutex.cmutex_name = cmutex_name; ut_d(lock->mutex.mutex_type = 1); #else /* INNODB_RW_LOCKS_USE_ATOMICS */ -# ifdef UNIV_DEBUG - UT_NOT_USED(cfile_name); - UT_NOT_USED(cline); -# endif + (void) cfile_name; + (void) cline; #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ lock->lock_word = X_LOCK_DECR; diff --git a/storage/xtradb/sync/sync0sync.c b/storage/xtradb/sync/sync0sync.c index 225f28df78e..71b444dbe54 100644 --- a/storage/xtradb/sync/sync0sync.c +++ b/storage/xtradb/sync/sync0sync.c @@ -266,6 +266,9 @@ mutex_create_func( #ifdef UNIV_DEBUG mutex->cfile_name = cfile_name; mutex->cline = cline; +#else + (void) cfile_name; + (void) cline; #endif /* UNIV_DEBUG */ mutex->count_os_wait = 0; mutex->cmutex_name= cmutex_name; diff --git a/storage/xtradb/trx/trx0purge.c b/storage/xtradb/trx/trx0purge.c index 1c317665878..5a8b42af3af 100644 --- a/storage/xtradb/trx/trx0purge.c +++ b/storage/xtradb/trx/trx0purge.c @@ -330,9 +330,10 @@ trx_purge_add_update_undo_to_history( trx_undo_t* undo; trx_rseg_t* rseg; trx_rsegf_t* rseg_header; +#ifdef UNIV_DEBUG trx_usegf_t* seg_header; +#endif /* UNIV_DEBUG */ trx_ulogf_t* undo_header; - trx_upagef_t* page_header; ulint hist_size; undo = trx->update_undo; @@ -347,8 +348,9 @@ trx_purge_add_update_undo_to_history( rseg->page_no, mtr); undo_header = undo_page + undo->hdr_offset; +#ifdef UNIV_DEBUG seg_header = undo_page + TRX_UNDO_SEG_HDR; - page_header = undo_page + TRX_UNDO_PAGE_HDR; +#endif /* UNIV_DEBUG */ if (undo->state != TRX_UNDO_CACHED) { /* The undo log segment will not be reused */ @@ -681,7 +683,6 @@ trx_purge_rseg_get_next_history_log( { page_t* undo_page; trx_ulogf_t* log_hdr; - trx_usegf_t* seg_hdr; fil_addr_t prev_log_addr; trx_id_t trx_no; ibool del_marks; @@ -702,7 +703,6 @@ trx_purge_rseg_get_next_history_log( undo_page = trx_undo_page_get_s_latched(rseg->space, rseg->zip_size, rseg->last_page_no, &mtr); log_hdr = undo_page + rseg->last_offset; - seg_hdr = undo_page + TRX_UNDO_SEG_HDR; /* Increase the purge page count by one for every handled log */ @@ -1094,12 +1094,8 @@ trx_purge_rec_release( /*==================*/ trx_undo_inf_t* cell) /*!< in: storage cell */ { - trx_undo_arr_t* arr; - mutex_enter(&(purge_sys->mutex)); - arr = purge_sys->arr; - trx_purge_arr_remove_info(cell); mutex_exit(&(purge_sys->mutex)); diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c index c925478cdf4..1a43e419214 100644 --- a/storage/xtradb/trx/trx0roll.c +++ b/storage/xtradb/trx/trx0roll.c @@ -740,13 +740,8 @@ trx_undo_arr_remove_info( undo_no_t undo_no)/*!< in: undo number */ { trx_undo_inf_t* cell; - ulint n_used; - ulint n; ulint i; - n_used = arr->n_used; - n = 0; - for (i = 0;; i++) { cell = trx_undo_arr_get_nth_info(arr, i); diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index 11581a3f2ae..566f7c95793 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -245,7 +245,9 @@ trx_sys_create_doublewrite_buf(void) { buf_block_t* block; buf_block_t* block2; +#ifdef UNIV_SYNC_DEBUG buf_block_t* new_block; +#endif /* UNIV_SYNC_DEBUG */ byte* doublewrite; byte* fseg_header; ulint page_no; @@ -348,8 +350,11 @@ start_again: the page position in the tablespace, then the page has not been written to in doublewrite. */ - new_block = buf_page_get(TRX_SYS_SPACE, 0, page_no, - RW_X_LATCH, &mtr); +#ifdef UNIV_SYNC_DEBUG + new_block = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(TRX_SYS_SPACE, 0, page_no, + RW_X_LATCH, &mtr); buf_block_dbg_add_level(new_block, SYNC_NO_ORDER_CHECK); @@ -492,7 +497,10 @@ start_again: the page position in the tablespace, then the page has not been written to in doublewrite. */ - new_block = buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, page_no, +#ifdef UNIV_SYNC_DEBUG + new_block = +#endif /* UNIV_SYNC_DEBUG */ + buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, page_no, RW_X_LATCH, &mtr); buf_block_dbg_add_level(new_block, SYNC_NO_ORDER_CHECK); diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index 9584f0c4c46..75bbe1b342a 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -1893,7 +1893,6 @@ trx_prepare_off_kernel( /*===================*/ trx_t* trx) /*!< in: transaction */ { - page_t* update_hdr_page; trx_rseg_t* rseg; ib_uint64_t lsn = 0; mtr_t mtr; @@ -1926,7 +1925,7 @@ trx_prepare_off_kernel( } if (trx->update_undo) { - update_hdr_page = trx_undo_set_state_at_prepare( + trx_undo_set_state_at_prepare( trx, trx->update_undo, &mtr); } diff --git a/storage/xtradb/trx/trx0undo.c b/storage/xtradb/trx/trx0undo.c index ec4beb5660a..6f06de593a9 100644 --- a/storage/xtradb/trx/trx0undo.c +++ b/storage/xtradb/trx/trx0undo.c @@ -1066,14 +1066,11 @@ trx_undo_truncate_end( ulint last_page_no; trx_undo_rec_t* rec; trx_undo_rec_t* trunc_here; - trx_rseg_t* rseg; mtr_t mtr; ut_ad(mutex_own(&(trx->undo_mutex))); ut_ad(mutex_own(&(trx->rseg->mutex))); - rseg = trx->rseg; - for (;;) { mtr_start(&mtr); @@ -1864,21 +1861,11 @@ trx_undo_set_state_at_finish( if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) - < TRX_UNDO_PAGE_REUSE_LIMIT) { + < TRX_UNDO_PAGE_REUSE_LIMIT + && UT_LIST_GET_LEN(rseg->update_undo_list) < 500 + && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - /* This is a heuristic to avoid the problem of all UNDO - slots ending up in one of the UNDO lists. Previously if - the server crashed with all the slots in one of the lists, - transactions that required the slots of a different type - would fail for lack of slots. */ - - if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500 - && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { - - state = TRX_UNDO_CACHED; - } else { - state = TRX_UNDO_TO_FREE; - } + state = TRX_UNDO_CACHED; } else if (undo->type == TRX_UNDO_INSERT) { @@ -1906,7 +1893,6 @@ trx_undo_set_state_at_prepare( mtr_t* mtr) /*!< in: mtr */ { trx_usegf_t* seg_hdr; - trx_upagef_t* page_hdr; trx_ulogf_t* undo_header; page_t* undo_page; ulint offset; @@ -1924,7 +1910,6 @@ trx_undo_set_state_at_prepare( undo->hdr_page_no, mtr); seg_hdr = undo_page + TRX_UNDO_SEG_HDR; - page_hdr = undo_page + TRX_UNDO_PAGE_HDR; /*------------------------------*/ undo->state = TRX_UNDO_PREPARED; |