summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innodb_plugin')
-rw-r--r--storage/innodb_plugin/ChangeLog79
-rw-r--r--storage/innodb_plugin/Makefile.am3
-rw-r--r--storage/innodb_plugin/btr/btr0btr.c9
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c12
-rw-r--r--storage/innodb_plugin/btr/btr0pcur.c2
-rw-r--r--storage/innodb_plugin/btr/btr0sea.c3
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c24
-rw-r--r--storage/innodb_plugin/buf/buf0flu.c90
-rw-r--r--storage/innodb_plugin/dict/dict0crea.c2
-rw-r--r--storage/innodb_plugin/dict/dict0dict.c9
-rw-r--r--storage/innodb_plugin/dict/dict0load.c31
-rw-r--r--storage/innodb_plugin/eval/eval0eval.c7
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc88
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h1
-rw-r--r--storage/innodb_plugin/handler/i_s.cc1
-rw-r--r--storage/innodb_plugin/ibuf/ibuf0ibuf.c197
-rw-r--r--storage/innodb_plugin/include/btr0cur.h16
-rw-r--r--storage/innodb_plugin/include/buf0flu.h14
-rw-r--r--storage/innodb_plugin/include/ibuf0ibuf.h5
-rw-r--r--storage/innodb_plugin/include/os0sync.h2
-rw-r--r--storage/innodb_plugin/include/row0mysql.h4
-rw-r--r--storage/innodb_plugin/include/row0upd.h7
-rw-r--r--storage/innodb_plugin/include/univ.i2
-rw-r--r--storage/innodb_plugin/include/ut0rnd.ic3
-rw-r--r--storage/innodb_plugin/log/log0recv.c6
-rw-r--r--storage/innodb_plugin/os/os0file.c61
-rw-r--r--storage/innodb_plugin/plug.in5
-rw-r--r--storage/innodb_plugin/que/que0que.c5
-rw-r--r--storage/innodb_plugin/row/row0mysql.c55
-rw-r--r--storage/innodb_plugin/row/row0purge.c7
-rw-r--r--storage/innodb_plugin/row/row0sel.c189
-rw-r--r--storage/innodb_plugin/row/row0umod.c7
-rw-r--r--storage/innodb_plugin/row/row0upd.c7
-rw-r--r--storage/innodb_plugin/row/row0vers.c11
-rw-r--r--storage/innodb_plugin/srv/srv0start.c7
-rw-r--r--storage/innodb_plugin/trx/trx0purge.c12
-rw-r--r--storage/innodb_plugin/trx/trx0roll.c5
-rw-r--r--storage/innodb_plugin/trx/trx0sys.c9
-rw-r--r--storage/innodb_plugin/trx/trx0trx.c3
-rw-r--r--storage/innodb_plugin/trx/trx0undo.c23
40 files changed, 677 insertions, 346 deletions
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;