summaryrefslogtreecommitdiff
path: root/storage/innodb_plugin
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2010-10-29 14:02:49 +0300
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2010-10-29 14:02:49 +0300
commitfd46de026d59c97e2e1628a252b71744c1e877da (patch)
tree298a4692281c6b166983dadf8cf3ba8067115956 /storage/innodb_plugin
parent64044fdf19f2b7c75f864156cc65db0026171527 (diff)
parent23552ecd41ec6679fd90f57ad982db8abf09c4ea (diff)
downloadmariadb-git-fd46de026d59c97e2e1628a252b71744c1e877da.tar.gz
merge to 5.1-security
Diffstat (limited to 'storage/innodb_plugin')
-rw-r--r--storage/innodb_plugin/ChangeLog45
-rw-r--r--storage/innodb_plugin/btr/btr0cur.c2
-rw-r--r--storage/innodb_plugin/buf/buf0buf.c24
-rw-r--r--storage/innodb_plugin/buf/buf0flu.c76
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.cc72
-rw-r--r--storage/innodb_plugin/handler/ha_innodb.h1
-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/row0mysql.h4
-rw-r--r--storage/innodb_plugin/include/row0upd.h7
-rw-r--r--storage/innodb_plugin/os/os0file.c38
-rw-r--r--storage/innodb_plugin/plug.in5
-rw-r--r--storage/innodb_plugin/row/row0mysql.c2
-rw-r--r--storage/innodb_plugin/row/row0sel.c105
-rw-r--r--storage/innodb_plugin/row/row0upd.c7
-rw-r--r--storage/innodb_plugin/srv/srv0start.c7
-rw-r--r--storage/innodb_plugin/trx/trx0undo.c18
19 files changed, 473 insertions, 172 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog
index 20d0fc86d00..0cd8ac8a7e6 100644
--- a/storage/innodb_plugin/ChangeLog
+++ b/storage/innodb_plugin/ChangeLog
@@ -10,6 +10,33 @@
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
@@ -30,17 +57,17 @@
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
+ 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
+ * 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
@@ -58,13 +85,13 @@
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
2010-07-27 The InnoDB Team
@@ -86,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/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c
index 9812e91e8a5..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(
/*=====================*/
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 747ce65879d..2123f8a060d 100644
--- a/storage/innodb_plugin/buf/buf0flu.c
+++ b/storage/innodb_plugin/buf/buf0flu.c
@@ -1039,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
diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
index 350eb8ae026..99d4f294f81 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;
}
}
}
@@ -6375,8 +6374,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,
@@ -6386,7 +6385,6 @@ create_options_are_valid(
" requires innodb_file_per_table.",
row_format_name);
ret = FALSE;
-
}
if (srv_file_format < DICT_TF_FORMAT_ZIP) {
@@ -6585,6 +6583,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) {
@@ -6625,10 +6625,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
@@ -6647,7 +6647,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
@@ -7522,9 +7522,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;
@@ -7555,7 +7558,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 */
@@ -7803,6 +7806,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.
@@ -7815,7 +7830,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);
}
@@ -8116,8 +8132,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
@@ -10930,6 +10944,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 "
@@ -10990,6 +11011,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/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/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/os/os0file.c b/storage/innodb_plugin/os/os0file.c
index 6a0d6ea5363..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 */
@@ -2278,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;
@@ -2402,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;
@@ -2532,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++;
@@ -3302,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;
@@ -3587,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);
@@ -3827,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 e638332d74a..2ee45389e9c 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/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
index 24b7a983878..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;
diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c
index cc7a7a6fe9b..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);
}
@@ -3614,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
@@ -4248,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(
@@ -4364,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,
@@ -4392,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.
@@ -4416,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
@@ -4433,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
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/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/trx0undo.c b/storage/innodb_plugin/trx/trx0undo.c
index c8a4b15e48b..76e88948e41 100644
--- a/storage/innodb_plugin/trx/trx0undo.c
+++ b/storage/innodb_plugin/trx/trx0undo.c
@@ -1823,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) {