summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvicentiu <vicentiu@mariadb.org>2017-01-07 14:38:21 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-01-10 12:20:38 +0200
commit682d4849ff6faa5089579c9b34563e3a85e6ff06 (patch)
tree134a6f400fe215b972cd98c24eabd1c0f4193e5c
parent1a55455566c98d095f0f15020cb047858053ff8e (diff)
parent6ac84d9824ec384c4489b68b8087369aef147ff9 (diff)
downloadmariadb-git-682d4849ff6faa5089579c9b34563e3a85e6ff06.tar.gz
Merge remote-tracking branch 'merge/merge-innodb-5.6' into 10.0
-rw-r--r--storage/innobase/dict/dict0stats.cc13
-rw-r--r--storage/innobase/fts/fts0opt.cc7
-rw-r--r--storage/innobase/handler/ha_innodb.cc38
-rw-r--r--storage/innobase/handler/handler0alter.cc79
-rw-r--r--storage/innobase/include/os0thread.h13
-rw-r--r--storage/innobase/include/srv0srv.h1
-rw-r--r--storage/innobase/mach/mach0data.cc53
-rw-r--r--storage/innobase/os/os0thread.cc32
-rw-r--r--storage/innobase/row/row0ftsort.cc2
-rw-r--r--storage/innobase/row/row0merge.cc7
-rw-r--r--storage/innobase/row/row0mysql.cc2
-rw-r--r--storage/innobase/srv/srv0srv.cc1
12 files changed, 188 insertions, 60 deletions
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index a4aa43651f8..c0a83c951a5 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1109,7 +1109,8 @@ dict_stats_analyze_index_level(
them away) which brings non-determinism. We skip only
leaf-level delete marks because delete marks on
non-leaf level do not make sense. */
- if (level == 0 &&
+
+ if (level == 0 && srv_stats_include_delete_marked? 0:
rec_get_deleted_flag(
rec,
page_is_comp(btr_pcur_get_page(&pcur)))) {
@@ -1295,8 +1296,12 @@ enum page_scan_method_t {
the given page and count the number of
distinct ones, also ignore delete marked
records */
- QUIT_ON_FIRST_NON_BORING/* quit when the first record that differs
+ QUIT_ON_FIRST_NON_BORING,/* quit when the first record that differs
from its right neighbor is found */
+ COUNT_ALL_NON_BORING_INCLUDE_DEL_MARKED/* scan all records on
+ the given page and count the number of
+ distinct ones, include delete marked
+ records */
};
/* @} */
@@ -1572,6 +1577,8 @@ dict_stats_analyze_index_below_cur(
offsets_rec = dict_stats_scan_page(
&rec, offsets1, offsets2, index, page, n_prefix,
+ srv_stats_include_delete_marked ?
+ COUNT_ALL_NON_BORING_INCLUDE_DEL_MARKED:
COUNT_ALL_NON_BORING_AND_SKIP_DEL_MARKED, n_diff,
n_external_pages);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index ea937c20752..455e2669c0d 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -578,9 +578,6 @@ fts_zip_read_word(
fts_zip_t* zip, /*!< in: Zip state + data */
fts_string_t* word) /*!< out: uncompressed word */
{
-#ifdef UNIV_DEBUG
- ulint i;
-#endif
short len = 0;
void* null = NULL;
byte* ptr = word->f_str;
@@ -655,10 +652,9 @@ fts_zip_read_word(
}
}
-#ifdef UNIV_DEBUG
/* All blocks must be freed at end of inflate. */
if (zip->status != Z_OK) {
- for (i = 0; i < ib_vector_size(zip->blocks); ++i) {
+ for (ulint i = 0; i < ib_vector_size(zip->blocks); ++i) {
if (ib_vector_getp(zip->blocks, i)) {
ut_free(ib_vector_getp(zip->blocks, i));
ib_vector_set(zip->blocks, i, &null);
@@ -669,7 +665,6 @@ fts_zip_read_word(
if (ptr != NULL) {
ut_ad(word->f_len == strlen((char*) ptr));
}
-#endif /* UNIV_DEBUG */
return(zip->status == Z_OK || zip->status == Z_STREAM_END ? ptr : NULL);
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 59ebc411db0..f94c564c8b3 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -13938,6 +13938,37 @@ ha_innobase::get_auto_increment(
ulonglong col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
+ /** The following logic is needed to avoid duplicate key error
+ for autoincrement column.
+
+ (1) InnoDB gives the current autoincrement value with respect
+ to increment and offset value.
+
+ (2) Basically it does compute_next_insert_id() logic inside InnoDB
+ to avoid the current auto increment value changed by handler layer.
+
+ (3) It is restricted only for insert operations. */
+
+ if (increment > 1 && thd_sql_command(user_thd) != SQLCOM_ALTER_TABLE
+ && autoinc < col_max_value) {
+
+ ulonglong prev_auto_inc = autoinc;
+
+ autoinc = ((autoinc - 1) + increment - offset)/ increment;
+
+ autoinc = autoinc * increment + offset;
+
+ /* If autoinc exceeds the col_max_value then reset
+ to old autoinc value. Because in case of non-strict
+ sql mode, boundary value is not considered as error. */
+
+ if (autoinc >= col_max_value) {
+ autoinc = prev_auto_inc;
+ }
+
+ ut_ad(autoinc > 0);
+ }
+
/* Called for the first time ? */
if (trx->n_autoinc_rows == 0) {
@@ -16462,6 +16493,12 @@ static MYSQL_SYSVAR_BOOL(use_fallocate, innobase_use_fallocate,
"Preallocate files fast, using operating system functionality. On POSIX systems, posix_fallocate system call is used.",
NULL, NULL, FALSE);
+static MYSQL_SYSVAR_BOOL(stats_include_delete_marked,
+ srv_stats_include_delete_marked,
+ PLUGIN_VAR_OPCMDARG,
+ "Scan delete marked records for persistent stat",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
PLUGIN_VAR_RQCMDARG,
"Number of IOPs the server can do. Tunes the background IO rate",
@@ -17293,6 +17330,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(doublewrite),
MYSQL_SYSVAR(use_atomic_writes),
MYSQL_SYSVAR(use_fallocate),
+ MYSQL_SYSVAR(stats_include_delete_marked),
MYSQL_SYSVAR(api_enable_binlog),
MYSQL_SYSVAR(api_enable_mdl),
MYSQL_SYSVAR(api_disable_rowlock),
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 89a58d83a60..cc00b841579 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1838,6 +1838,7 @@ innobase_fts_check_doc_id_index_in_def(
return(FTS_NOT_EXIST_DOC_ID_INDEX);
}
+
/*******************************************************************//**
Create an index table where indexes are ordered as follows:
@@ -1906,26 +1907,11 @@ innobase_create_key_defs(
(only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
- if (n_add > 0 && !new_primary && got_default_clust
- && (key_info[*add].flags & HA_NOSAME)
- && !(key_info[*add].flags & HA_KEY_HAS_PART_KEY_SEG)) {
- uint key_part = key_info[*add].user_defined_key_parts;
-
- new_primary = true;
+ ut_ad(altered_table->s->primary_key == 0
+ || altered_table->s->primary_key == MAX_KEY);
- while (key_part--) {
- const uint maybe_null
- = key_info[*add].key_part[key_part].key_type
- & FIELDFLAG_MAYBE_NULL;
- DBUG_ASSERT(!maybe_null
- == !key_info[*add].key_part[key_part].
- field->real_maybe_null());
-
- if (maybe_null) {
- new_primary = false;
- break;
- }
- }
+ if (got_default_clust && !new_primary) {
+ new_primary = (altered_table->s->primary_key != MAX_KEY);
}
const bool rebuild = new_primary || add_fts_doc_id
@@ -1944,8 +1930,14 @@ innobase_create_key_defs(
ulint primary_key_number;
if (new_primary) {
- DBUG_ASSERT(n_add > 0);
- primary_key_number = *add;
+ if (n_add == 0) {
+ DBUG_ASSERT(got_default_clust);
+ DBUG_ASSERT(altered_table->s->primary_key
+ == 0);
+ primary_key_number = 0;
+ } else {
+ primary_key_number = *add;
+ }
} else if (got_default_clust) {
/* Create the GEN_CLUST_INDEX */
index_def_t* index = indexdef++;
@@ -3053,6 +3045,8 @@ prepare_inplace_alter_table_dict(
ctx->add_cols = add_cols;
} else {
DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info, old_table));
+ DBUG_ASSERT(old_table->s->primary_key
+ == altered_table->s->primary_key);
if (!ctx->new_table->fts
&& innobase_fulltext_exist(altered_table)) {
@@ -4073,6 +4067,27 @@ found_col:
add_fts_doc_id_idx));
}
+/** Get the name of an erroneous key.
+@param[in] error_key_num InnoDB number of the erroneus key
+@param[in] ha_alter_info changes that were being performed
+@param[in] table InnoDB table
+@return the name of the erroneous key */
+static
+const char*
+get_error_key_name(
+ ulint error_key_num,
+ const Alter_inplace_info* ha_alter_info,
+ const dict_table_t* table)
+{
+ if (error_key_num == ULINT_UNDEFINED) {
+ return(FTS_DOC_ID_INDEX_NAME);
+ } else if (ha_alter_info->key_count == 0) {
+ return(dict_table_get_first_index(table)->name);
+ } else {
+ return(ha_alter_info->key_info_buffer[error_key_num].name);
+ }
+}
+
/** Alter the table structure in-place with operations
specified using Alter_inplace_info.
The level of concurrency allowed during this operation depends
@@ -4190,17 +4205,13 @@ oom:
case DB_ONLINE_LOG_TOO_BIG:
DBUG_ASSERT(ctx->online);
my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
- (prebuilt->trx->error_key_num == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[
- prebuilt->trx->error_key_num].name);
+ get_error_key_name(prebuilt->trx->error_key_num,
+ ha_alter_info, prebuilt->table));
break;
case DB_INDEX_CORRUPT:
my_error(ER_INDEX_CORRUPT, MYF(0),
- (prebuilt->trx->error_key_num == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[
- prebuilt->trx->error_key_num].name);
+ get_error_key_name(prebuilt->trx->error_key_num,
+ ha_alter_info, prebuilt->table));
break;
default:
my_error_innodb(error,
@@ -5013,7 +5024,6 @@ innobase_update_foreign_cache(
"Foreign key constraints for table '%s'"
" are loaded with charset check off",
user_table->name);
-
}
}
@@ -5113,14 +5123,13 @@ commit_try_rebuild(
DBUG_RETURN(true);
case DB_ONLINE_LOG_TOO_BIG:
my_error(ER_INNODB_ONLINE_LOG_TOO_BIG, MYF(0),
- ha_alter_info->key_info_buffer[0].name);
+ get_error_key_name(err_key, ha_alter_info,
+ rebuilt_table));
DBUG_RETURN(true);
case DB_INDEX_CORRUPT:
my_error(ER_INDEX_CORRUPT, MYF(0),
- (err_key == ULINT_UNDEFINED)
- ? FTS_DOC_ID_INDEX_NAME
- : ha_alter_info->key_info_buffer[err_key]
- .name);
+ get_error_key_name(err_key, ha_alter_info,
+ rebuilt_table));
DBUG_RETURN(true);
default:
my_error_innodb(error, table_name, user_table->flags);
diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h
index 9a1ada8fa0d..54f3d7554bf 100644
--- a/storage/innobase/include/os0thread.h
+++ b/storage/innobase/include/os0thread.h
@@ -117,14 +117,25 @@ os_thread_create_func(
os_thread_id_t* thread_id); /*!< out: id of the created
thread, or NULL */
+/** Waits until the specified thread completes and joins it.
+Its return value is ignored.
+@param[in,out] thread thread to join */
+UNIV_INTERN
+void
+os_thread_join(
+ os_thread_t thread);
+
/*****************************************************************//**
Exits the current thread. */
UNIV_INTERN
void
os_thread_exit(
/*===========*/
- void* exit_value) /*!< in: exit value; in Windows this void*
+ void* exit_value, /*!< in: exit value; in Windows this void*
is cast as a DWORD */
+ bool detach = true) /*!< in: if true, the thread will be detached
+ right before exiting. If false, another thread
+ is responsible for joining this thread. */
UNIV_COLD MY_ATTRIBUTE((noreturn));
/*****************************************************************//**
Returns the thread identifier of current thread.
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index b8e1fcbbaf6..6389efa7b84 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -364,6 +364,7 @@ extern unsigned long long srv_stats_persistent_sample_pages;
extern my_bool srv_stats_auto_recalc;
extern unsigned long long srv_stats_modified_counter;
extern my_bool srv_stats_sample_traditional;
+extern my_bool srv_stats_include_delete_marked;
extern ibool srv_use_doublewrite_buf;
extern ulong srv_doublewrite_batch_size;
diff --git a/storage/innobase/mach/mach0data.cc b/storage/innobase/mach/mach0data.cc
index df68aab8a18..feeedb01609 100644
--- a/storage/innobase/mach/mach0data.cc
+++ b/storage/innobase/mach/mach0data.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2009, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -55,8 +55,22 @@ mach_parse_compressed(
if (flag < 0x80UL) {
*val = flag;
return(ptr + 1);
+ }
+
+ /* Workaround GCC bug
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77673:
+ the compiler moves mach_read_from_4 right to the beginning of the
+ function, causing and out-of-bounds read if we are reading a short
+ integer close to the end of buffer. */
+#if defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__clang__)
+#define DEPLOY_FENCE
+#endif
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
- } else if (flag < 0xC0UL) {
+ if (flag < 0xC0UL) {
if (end_ptr < ptr + 2) {
return(NULL);
}
@@ -64,8 +78,13 @@ mach_parse_compressed(
*val = mach_read_from_2(ptr) & 0x7FFFUL;
return(ptr + 2);
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
- } else if (flag < 0xE0UL) {
+ if (flag < 0xE0UL) {
if (end_ptr < ptr + 3) {
return(NULL);
}
@@ -73,7 +92,13 @@ mach_parse_compressed(
*val = mach_read_from_3(ptr) & 0x3FFFFFUL;
return(ptr + 3);
- } else if (flag < 0xF0UL) {
+ }
+
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+ if (flag < 0xF0UL) {
if (end_ptr < ptr + 4) {
return(NULL);
}
@@ -81,14 +106,20 @@ mach_parse_compressed(
*val = mach_read_from_4(ptr) & 0x1FFFFFFFUL;
return(ptr + 4);
- } else {
- ut_ad(flag == 0xF0UL);
+ }
- if (end_ptr < ptr + 5) {
- return(NULL);
- }
+#ifdef DEPLOY_FENCE
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+#endif
+
+#undef DEPLOY_FENCE
+
+ ut_ad(flag == 0xF0UL);
- *val = mach_read_from_4(ptr + 1);
- return(ptr + 5);
+ if (end_ptr < ptr + 5) {
+ return(NULL);
}
+
+ *val = mach_read_from_4(ptr + 1);
+ return(ptr + 5);
}
diff --git a/storage/innobase/os/os0thread.cc b/storage/innobase/os/os0thread.cc
index a5b0f7de6ae..a6bef176ba4 100644
--- a/storage/innobase/os/os0thread.cc
+++ b/storage/innobase/os/os0thread.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -191,14 +191,38 @@ os_thread_create_func(
#endif
}
+/** Waits until the specified thread completes and joins it.
+Its return value is ignored.
+@param[in,out] thread thread to join */
+UNIV_INTERN
+void
+os_thread_join(
+ os_thread_t thread)
+{
+#ifdef __WIN__
+ /* Do nothing. */
+#else
+#ifdef UNIV_DEBUG
+ const int ret =
+#endif /* UNIV_DEBUG */
+ pthread_join(thread, NULL);
+
+ /* Waiting on already-quit threads is allowed. */
+ ut_ad(ret == 0 || ret == ESRCH);
+#endif /* __WIN__ */
+}
+
/*****************************************************************//**
Exits the current thread. */
UNIV_INTERN
void
os_thread_exit(
/*===========*/
- void* exit_value) /*!< in: exit value; in Windows this void*
+ void* exit_value, /*!< in: exit value; in Windows this void*
is cast as a DWORD */
+ bool detach) /*!< in: if true, the thread will be detached
+ right before exiting. If false, another thread
+ is responsible for joining this thread. */
{
#ifdef UNIV_DEBUG_THREAD_CREATION
fprintf(stderr, "Thread exits, id %lu\n",
@@ -216,7 +240,9 @@ os_thread_exit(
#ifdef __WIN__
ExitThread((DWORD) exit_value);
#else
- pthread_detach(pthread_self());
+ if (detach) {
+ pthread_detach(pthread_self());
+ }
pthread_exit(exit_value);
#endif
}
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 1ce99acaef8..e4a88047955 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -958,7 +958,7 @@ fts_parallel_merge(
CloseHandle(psort_info->thread_hdl);
#endif /*__WIN__ */
- os_thread_exit(NULL);
+ os_thread_exit(NULL, false);
OS_THREAD_DUMMY_RETURN;
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 9cd6e63e031..9518712e160 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -3824,6 +3824,13 @@ wait_again:
" exited when creating FTS"
" index '%s'",
indexes[i]->name);
+ } else {
+ for (j = 0; j < FTS_NUM_AUX_INDEX;
+ j++) {
+
+ os_thread_join(merge_info[j]
+ .thread_hdl);
+ }
}
} else {
/* This cannot report duplicates; an
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 07b841de300..6eb93f9e22d 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1365,6 +1365,8 @@ run_again:
row_ins_step(thr);
+ DEBUG_SYNC_C("ib_after_row_insert_step");
+
err = trx->error_state;
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index e9eeda9acb1..4c58a3e84fb 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -343,6 +343,7 @@ this many index pages, there are 2 ways to calculate statistics:
table/index are not found in the innodb database */
UNIV_INTERN unsigned long long srv_stats_transient_sample_pages = 8;
UNIV_INTERN my_bool srv_stats_persistent = TRUE;
+UNIV_INTERN my_bool srv_stats_include_delete_marked = FALSE;
UNIV_INTERN unsigned long long srv_stats_persistent_sample_pages = 20;
UNIV_INTERN my_bool srv_stats_auto_recalc = TRUE;