summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/CMakeLists.txt2
-rw-r--r--storage/innobase/api/api0api.cc223
-rw-r--r--storage/innobase/btr/btr0cur.cc12
-rw-r--r--storage/innobase/buf/buf0buf.cc277
-rw-r--r--storage/innobase/buf/buf0checksum.cc11
-rw-r--r--storage/innobase/dict/dict0dict.cc148
-rw-r--r--storage/innobase/dict/dict0mem.cc74
-rw-r--r--storage/innobase/fil/fil0fil.cc8
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc40
-rw-r--r--storage/innobase/fts/fts0ast.cc48
-rw-r--r--storage/innobase/fts/fts0fts.cc109
-rw-r--r--storage/innobase/fts/fts0opt.cc11
-rw-r--r--storage/innobase/fts/fts0que.cc49
-rw-r--r--storage/innobase/handler/ha_innodb.cc99
-rw-r--r--storage/innobase/handler/handler0alter.cc39
-rw-r--r--storage/innobase/handler/i_s.cc18
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc10
-rw-r--r--storage/innobase/include/api0api.h10
-rw-r--r--storage/innobase/include/buf0buf.h8
-rw-r--r--storage/innobase/include/buf0buf.ic12
-rw-r--r--storage/innobase/include/db0err.h5
-rw-r--r--storage/innobase/include/dict0dict.h11
-rw-r--r--storage/innobase/include/dict0mem.h123
-rw-r--r--storage/innobase/include/fts0ast.h7
-rw-r--r--storage/innobase/include/ha_prototypes.h2
-rw-r--r--storage/innobase/include/lock0priv.h7
-rw-r--r--storage/innobase/include/os0file.h8
-rw-r--r--storage/innobase/include/os0sync.h2
-rw-r--r--storage/innobase/include/page0page.h16
-rw-r--r--storage/innobase/include/page0zip.h15
-rw-r--r--storage/innobase/include/row0merge.h3
-rw-r--r--storage/innobase/include/sync0rw.ic7
-rw-r--r--storage/innobase/include/trx0roll.h4
-rw-r--r--storage/innobase/include/trx0trx.h13
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/lock/lock0lock.cc52
-rw-r--r--storage/innobase/log/log0log.cc10
-rw-r--r--storage/innobase/log/log0recv.cc5
-rw-r--r--storage/innobase/os/os0file.cc93
-rw-r--r--storage/innobase/os/os0sync.cc20
-rw-r--r--storage/innobase/page/page0page.cc44
-rw-r--r--storage/innobase/page/page0zip.cc103
-rw-r--r--storage/innobase/que/que0que.cc28
-rw-r--r--storage/innobase/row/row0ftsort.cc2
-rw-r--r--storage/innobase/row/row0log.cc23
-rw-r--r--storage/innobase/row/row0merge.cc168
-rw-r--r--storage/innobase/row/row0mysql.cc176
-rw-r--r--storage/innobase/row/row0quiesce.cc3
-rw-r--r--storage/innobase/srv/srv0mon.cc5
-rw-r--r--storage/innobase/srv/srv0srv.cc6
-rw-r--r--storage/innobase/srv/srv0start.cc32
-rw-r--r--storage/innobase/sync/sync0arr.cc8
-rw-r--r--storage/innobase/sync/sync0rw.cc14
-rw-r--r--storage/innobase/sync/sync0sync.cc108
-rw-r--r--storage/innobase/trx/trx0roll.cc7
-rw-r--r--storage/innobase/trx/trx0sys.cc4
-rw-r--r--storage/innobase/trx/trx0trx.cc5
-rw-r--r--storage/innobase/ut/ut0ut.cc4
58 files changed, 1424 insertions, 929 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index f88cc12b1f2..eb94f6ba703 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -210,6 +210,8 @@ IF(HAVE_IB_ATOMIC_PTHREAD_T_GCC)
ADD_DEFINITIONS(-DHAVE_IB_ATOMIC_PTHREAD_T_GCC=1)
ENDIF()
+CHECK_C_SOURCE_COMPILES("struct t1{ int a; char *b; }; struct t1 c= { .a=1, .b=0 }; main() { }" HAVE_C99_INITIALIZERS)
+
ENDIF(NOT MSVC)
CHECK_FUNCTION_EXISTS(asprintf HAVE_ASPRINTF)
diff --git a/storage/innobase/api/api0api.cc b/storage/innobase/api/api0api.cc
index 3859fb84b81..0fe21423232 100644
--- a/storage/innobase/api/api0api.cc
+++ b/storage/innobase/api/api0api.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2008, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2008, 2015, 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
@@ -318,35 +318,6 @@ ib_wake_master_thread(void)
}
}
-/*********************************************************************//**
-Calculate the max row size of the columns in a cluster index.
-@return max row length */
-UNIV_INLINE
-ulint
-ib_get_max_row_len(
-/*===============*/
- dict_index_t* cluster) /*!< in: cluster index */
-{
- ulint i;
- ulint max_len = 0;
- ulint n_fields = cluster->n_fields;
-
- /* Add the size of the ordering columns in the
- clustered index. */
- for (i = 0; i < n_fields; ++i) {
- const dict_col_t* col;
-
- col = dict_index_get_nth_col(cluster, i);
-
- /* Use the maximum output size of
- mach_write_compressed(), although the encoded
- length should always fit in 2 bytes. */
- max_len += dict_col_get_max_size(col);
- }
-
- return(max_len);
-}
-
/*****************************************************************//**
Read the columns from a rec into a tuple. */
static
@@ -624,6 +595,21 @@ ib_trx_begin(
return(static_cast<ib_trx_t>(trx));
}
+
+/*****************************************************************//**
+Check if transaction is read_only
+@return transaction read_only status */
+UNIV_INTERN
+ib_u32_t
+ib_trx_read_only(
+/*=============*/
+ ib_trx_t ib_trx) /*!< in: trx handle */
+{
+ trx_t* trx = (trx_t*) ib_trx;
+
+ return(trx->read_only);
+}
+
/*****************************************************************//**
Get the transaction's state.
@return transaction state */
@@ -710,120 +696,6 @@ ib_trx_rollback(
return(err);
}
-/*****************************************************************//**
-Find an index definition from the index vector using index name.
-@return index def. if found else NULL */
-UNIV_INLINE
-const ib_index_def_t*
-ib_table_find_index(
-/*================*/
- ib_vector_t* indexes, /*!< in: vector of indexes */
- const char* name) /*!< in: index name */
-{
- ulint i;
-
- for (i = 0; i < ib_vector_size(indexes); ++i) {
- const ib_index_def_t* index_def;
-
- index_def = (ib_index_def_t*) ib_vector_get(indexes, i);
-
- if (innobase_strcasecmp(name, index_def->name) == 0) {
- return(index_def);
- }
- }
-
- return(NULL);
-}
-
-/*****************************************************************//**
-Get the InnoDB internal precise type from the schema column definition.
-@return precise type in api format */
-UNIV_INLINE
-ulint
-ib_col_get_prtype(
-/*==============*/
- const ib_col_t* ib_col) /*!< in: column definition */
-{
- ulint prtype = 0;
-
- if (ib_col->ib_col_attr & IB_COL_UNSIGNED) {
- prtype |= DATA_UNSIGNED;
-
- ut_a(ib_col->ib_col_type == IB_INT);
- }
-
- if (ib_col->ib_col_attr & IB_COL_NOT_NULL) {
- prtype |= DATA_NOT_NULL;
- }
-
- return(prtype);
-}
-
-/*****************************************************************//**
-Get the InnoDB internal main type from the schema column definition.
-@return column main type */
-UNIV_INLINE
-ulint
-ib_col_get_mtype(
-/*==============*/
- const ib_col_t* ib_col) /*!< in: column definition */
-{
- /* Note: The api0api.h types should map directly to
- the internal numeric codes. */
- return(ib_col->ib_col_type);
-}
-
-/*****************************************************************//**
-Find a column in the the column vector with the same name.
-@return col. def. if found else NULL */
-UNIV_INLINE
-const ib_col_t*
-ib_table_find_col(
-/*==============*/
- const ib_vector_t* cols, /*!< in: column list head */
- const char* name) /*!< in: column name to find */
-{
- ulint i;
-
- for (i = 0; i < ib_vector_size(cols); ++i) {
- const ib_col_t* ib_col;
-
- ib_col = static_cast<const ib_col_t*>(
- ib_vector_get((ib_vector_t*) cols, i));
-
- if (innobase_strcasecmp(ib_col->name, name) == 0) {
- return(ib_col);
- }
- }
-
- return(NULL);
-}
-
-/*****************************************************************//**
-Find a column in the the column list with the same name.
-@return col. def. if found else NULL */
-UNIV_INLINE
-const ib_key_col_t*
-ib_index_find_col(
-/*==============*/
- ib_vector_t* cols, /*!< in: column list head */
- const char* name) /*!< in: column name to find */
-{
- ulint i;
-
- for (i = 0; i < ib_vector_size(cols); ++i) {
- const ib_key_col_t* ib_col;
-
- ib_col = static_cast<ib_key_col_t*>(ib_vector_get(cols, i));
-
- if (innobase_strcasecmp(ib_col->name, name) == 0) {
- return(ib_col);
- }
- }
-
- return(NULL);
-}
-
#ifdef __WIN__
/*****************************************************************//**
Convert a string to lower case. */
@@ -947,34 +819,6 @@ ib_table_name_check(
/*****************************************************************//**
-Get an index definition that is tagged as a clustered index.
-@return cluster index schema */
-UNIV_INLINE
-ib_index_def_t*
-ib_find_clustered_index(
-/*====================*/
- ib_vector_t* indexes) /*!< in: index defs. to search */
-{
- ulint i;
- ulint n_indexes;
-
- n_indexes = ib_vector_size(indexes);
-
- for (i = 0; i < n_indexes; ++i) {
- ib_index_def_t* ib_index_def;
-
- ib_index_def = static_cast<ib_index_def_t*>(
- ib_vector_get(indexes, i));
-
- if (ib_index_def->clustered) {
- return(ib_index_def);
- }
- }
-
- return(NULL);
-}
-
-/*****************************************************************//**
Get a table id. The caller must have acquired the dictionary mutex.
@return DB_SUCCESS if found */
static
@@ -3564,41 +3408,6 @@ ib_cursor_set_cluster_access(
prebuilt->need_to_access_clustered = TRUE;
}
-/*************************************************************//**
-Convert and write an INT column value to an InnoDB tuple.
-@return DB_SUCCESS or error */
-UNIV_INLINE
-ib_err_t
-ib_tuple_write_int(
-/*===============*/
- ib_tpl_t ib_tpl, /*!< in/out: tuple to write to */
- ulint col_no, /*!< in: column number */
- const void* value, /*!< in: integer value */
- ulint value_len) /*!< in: sizeof value type */
-{
- const dfield_t* dfield;
- ulint data_len;
- ulint type_len;
- ib_tuple_t* tuple = (ib_tuple_t*) ib_tpl;
-
- ut_a(col_no < ib_tuple_get_n_cols(ib_tpl));
-
- dfield = ib_col_get_dfield(tuple, col_no);
-
- data_len = dfield_get_len(dfield);
- type_len = dtype_get_len(dfield_get_type(dfield));
-
- if (dtype_get_mtype(dfield_get_type(dfield)) != DATA_INT
- || value_len != data_len) {
-
- return(DB_DATA_MISMATCH);
- }
-
- return(ib_col_set_value(
- ib_tpl, static_cast<ib_ulint_t>(col_no),
- value, static_cast<ib_ulint_t>(type_len), true));
-}
-
/*****************************************************************//**
Write an integer value to a column. Integers are stored in big-endian
format and will need to be converted from the host format.
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index e68179a5c19..315a1d1b558 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -2372,15 +2372,15 @@ btr_cur_pess_upd_restore_supremum(
Check if the total length of the modified blob for the row is within 10%
of the total redo log size. This constraint on the blob length is to
avoid overwriting the redo logs beyond the last checkpoint lsn.
-@return DB_SUCCESS or DB_TOO_BIG_RECORD. */
+@return DB_SUCCESS or DB_TOO_BIG_FOR_REDO. */
static
dberr_t
btr_check_blob_limit(const big_rec_t* big_rec_vec)
{
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
* UNIV_PAGE_SIZE;
- const ulint redo_10p = redo_size / 10;
- ulint total_blob_len = 0;
+ const ib_uint64_t redo_10p = redo_size / 10;
+ ib_uint64_t total_blob_len = 0;
dberr_t err = DB_SUCCESS;
/* Calculate the total number of bytes for blob data */
@@ -2390,11 +2390,11 @@ btr_check_blob_limit(const big_rec_t* big_rec_vec)
if (total_blob_len > redo_10p) {
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
- " length (" ULINTPF ") is greater than"
+ " length (" UINT64PF ") is greater than"
" 10%% of the total redo log size (" UINT64PF
"). Please increase total redo log size.",
total_blob_len, redo_size);
- err = DB_TOO_BIG_RECORD;
+ err = DB_TOO_BIG_FOR_REDO;
}
return(err);
@@ -4457,7 +4457,7 @@ Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand.
The fields are stored on pages allocated from leaf node
file segment of the index tree.
-@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
+@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE or DB_TOO_BIG_FOR_REDO */
UNIV_INTERN
dberr_t
btr_store_big_rec_extern_fields(
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9c569691ef0..46f7f5a49df 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -487,6 +487,79 @@ buf_page_is_zeroes(
return(true);
}
+/** Checks if the page is in crc32 checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in crc32 checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_crc32(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ ib_uint32_t crc32 = buf_calc_page_crc32(read_buf);
+
+ return(checksum_field1 == crc32 && checksum_field2 == crc32);
+}
+
+/** Checks if the page is in innodb checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in innodb checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_innodb(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ /* There are 2 valid formulas for
+ checksum_field2 (old checksum field) which algo=innodb could have
+ written to the page:
+
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the
+ start and the end of the page.
+
+ 2. Newer InnoDB versions store the old formula checksum
+ (buf_calc_page_old_checksum()). */
+
+ if (checksum_field2 != mach_read_from_4(read_buf + FIL_PAGE_LSN)
+ && checksum_field2 != buf_calc_page_old_checksum(read_buf)) {
+ return(false);
+ }
+
+ /* old field is fine, check the new field */
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+
+ if (checksum_field1 != 0
+ && checksum_field1 != buf_calc_page_new_checksum(read_buf)) {
+ return(false);
+ }
+
+ return(true);
+}
+
+/** Checks if the page is in none checksum format.
+@param[in] read_buf database page
+@param[in] checksum_field1 new checksum field
+@param[in] checksum_field2 old checksum field
+@return true if the page is in none checksum format */
+UNIV_INLINE
+bool
+buf_page_is_checksum_valid_none(
+ const byte* read_buf,
+ ulint checksum_field1,
+ ulint checksum_field2)
+{
+ return(checksum_field1 == checksum_field2
+ && checksum_field1 == BUF_NO_CHECKSUM_MAGIC);
+}
+
/********************************************************************//**
Checks if a page is corrupt.
@return TRUE if corrupted */
@@ -502,8 +575,6 @@ buf_page_is_corrupted(
{
ulint checksum_field1;
ulint checksum_field2;
- ibool crc32_inited = FALSE;
- ib_uint32_t crc32 = ULINT32_UNDEFINED;
if (!zip_size
&& memcmp(read_buf + FIL_PAGE_LSN + 4,
@@ -583,148 +654,121 @@ buf_page_is_corrupted(
return(FALSE);
}
- switch ((srv_checksum_algorithm_t) srv_checksum_algorithm) {
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
-
- crc32 = buf_calc_page_crc32(read_buf);
-
- return(checksum_field1 != crc32 || checksum_field2 != crc32);
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
-
- return(checksum_field1
- != buf_calc_page_new_checksum(read_buf)
- || checksum_field2
- != buf_calc_page_old_checksum(read_buf));
-
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
- return(checksum_field1 != BUF_NO_CHECKSUM_MAGIC
- || checksum_field2 != BUF_NO_CHECKSUM_MAGIC);
+ ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET);
+ ulint space_id = mach_read_from_4(read_buf + FIL_PAGE_SPACE_ID);
+ const srv_checksum_algorithm_t curr_algo =
+ static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+ switch (curr_algo) {
case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_INNODB:
- /* There are 3 valid formulas for
- checksum_field2 (old checksum field):
-
- 1. Very old versions of InnoDB only stored 8 byte lsn to the
- start and the end of the page.
-
- 2. InnoDB versions before MySQL 5.6.3 store the old formula
- checksum (buf_calc_page_old_checksum()).
-
- 3. InnoDB versions 5.6.3 and newer with
- innodb_checksum_algorithm=strict_crc32|crc32 store CRC32. */
-
- /* since innodb_checksum_algorithm is not strict_* allow
- any of the algos to match for the old field */
-
- if (checksum_field2
- != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
-
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
-
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
-
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
-
- if (checksum_field2 != crc32
- && checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (checksum_field2
- != buf_calc_page_old_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
+ return(FALSE);
+ }
- if (checksum_field2 != crc32) {
- return(TRUE);
- }
- }
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
}
- }
- /* old field is fine, check the new field */
+ return(FALSE);
+ }
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */
+ return(TRUE);
- if (checksum_field1 != 0
- && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) {
+ case SRV_CHECKSUM_ALGORITHM_INNODB:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- /* The checksum does not match any of the
- fast to check. First check the selected algorithm
- for writing checksums because we assume that the
- chance of it matching is higher. */
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
+ }
- if (srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_CRC32) {
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(read_buf);
- crc32_inited = TRUE;
- }
+ return(FALSE);
+ }
- if (checksum_field1 != crc32
- && checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ }
- return(TRUE);
- }
- } else {
- ut_ad(srv_checksum_algorithm
- == SRV_CHECKSUM_ALGORITHM_INNODB);
+ return(FALSE);
+ }
- if (checksum_field1
- != buf_calc_page_new_checksum(read_buf)) {
+ return(TRUE);
- if (!crc32_inited) {
- crc32 = buf_calc_page_crc32(
- read_buf);
- crc32_inited = TRUE;
- }
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- if (checksum_field1 != crc32) {
- return(TRUE);
- }
- }
- }
+ if (buf_page_is_checksum_valid_none(read_buf,
+ checksum_field1, checksum_field2)) {
+ return(FALSE);
}
- /* If CRC32 is stored in at least one of the fields, then the
- other field must also be CRC32 */
- if (crc32_inited
- && ((checksum_field1 == crc32
- && checksum_field2 != crc32)
- || (checksum_field1 != crc32
- && checksum_field2 == crc32))) {
+ if (buf_page_is_checksum_valid_crc32(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ return(FALSE);
+ }
- return(TRUE);
+ if (buf_page_is_checksum_valid_innodb(read_buf,
+ checksum_field1, checksum_field2)) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ return(FALSE);
}
- break;
+ return(TRUE);
+
case SRV_CHECKSUM_ALGORITHM_NONE:
/* should have returned FALSE earlier */
- ut_error;
+ break;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); );
-
+ ut_error;
return(FALSE);
}
@@ -1679,6 +1723,9 @@ page_found:
goto page_found;
}
+ /* The maximum number of purge threads should never exceed
+ BUF_POOL_WATCH_SIZE. So there is no way for purge thread
+ instance to hold a watch when setting another watch. */
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
bpage = &buf_pool->watch[i];
diff --git a/storage/innobase/buf/buf0checksum.cc b/storage/innobase/buf/buf0checksum.cc
index 4ba65d6f2d0..f95eba39ab4 100644
--- a/storage/innobase/buf/buf0checksum.cc
+++ b/storage/innobase/buf/buf0checksum.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, 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
@@ -139,14 +139,17 @@ buf_checksum_algorithm_name(
{
switch (algo) {
case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
return("crc32");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
+ return("strict_crc32");
case SRV_CHECKSUM_ALGORITHM_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
return("innodb");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
+ return("strict_innodb");
case SRV_CHECKSUM_ALGORITHM_NONE:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return("none");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ return("strict_none");
}
ut_error;
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 56205536a45..52a9bb686df 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -649,7 +649,68 @@ dict_table_get_col_name(
return(s);
}
+/**********************************************************************//**
+Returns a column's name.
+@return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+ const dict_table_t* table, /*!< in: table */
+ const char* col_name)/*! in: MySQL table column name */
+{
+ ulint i;
+ const char* s;
+
+ ut_ad(table);
+ ut_ad(col_name);
+ ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+ s = table->col_names;
+ if (s) {
+ /* If we have many virtual columns MySQL key_part->fieldnr
+ could be larger than number of columns in InnoDB table
+ when creating new indexes. */
+ for (i = 0; i < table->n_def; i++) {
+
+ if (!innobase_strcasecmp(s, col_name)) {
+ break; /* Found */
+ }
+ s += strlen(s) + 1;
+ }
+ }
+
+ return(s);
+}
#ifndef UNIV_HOTBACKUP
+/** Allocate and init the autoinc latch of a given table.
+This function must not be called concurrently on the same table object.
+@param[in,out] table_void table whose autoinc latch to create */
+void
+dict_table_autoinc_alloc(
+ void* table_void)
+{
+ dict_table_t* table = static_cast<dict_table_t*>(table_void);
+ table->autoinc_mutex = new (std::nothrow) ib_mutex_t();
+ ut_a(table->autoinc_mutex != NULL);
+ mutex_create(autoinc_mutex_key,
+ table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
+}
+
+/** Allocate and init the zip_pad_mutex of a given index.
+This function must not be called concurrently on the same index object.
+@param[in,out] index_void index whose zip_pad_mutex to create */
+void
+dict_index_zip_pad_alloc(
+ void* index_void)
+{
+ dict_index_t* index = static_cast<dict_index_t*>(index_void);
+ index->zip_pad.mutex = new (std::nothrow) os_fast_mutex_t;
+ ut_a(index->zip_pad.mutex != NULL);
+ os_fast_mutex_init(zip_pad_mutex_key, index->zip_pad.mutex);
+}
+
/********************************************************************//**
Acquire the autoinc lock. */
UNIV_INTERN
@@ -658,7 +719,32 @@ dict_table_autoinc_lock(
/*====================*/
dict_table_t* table) /*!< in/out: table */
{
- mutex_enter(&table->autoinc_mutex);
+#ifdef HAVE_ATOMIC_BUILTINS
+ os_once::do_or_wait_for_done(
+ &table->autoinc_mutex_created,
+ dict_table_autoinc_alloc, table);
+#else /* HAVE_ATOMIC_BUILTINS */
+ ut_ad(table->autoinc_mutex_created == os_once::DONE);
+#endif /* HAVE_ATOMIC_BUILTINS */
+
+ mutex_enter(table->autoinc_mutex);
+}
+
+/** Acquire the zip_pad_mutex latch.
+@param[in,out] index the index whose zip_pad_mutex to acquire.*/
+void
+dict_index_zip_pad_lock(
+ dict_index_t* index)
+{
+#ifdef HAVE_ATOMIC_BUILTINS
+ os_once::do_or_wait_for_done(
+ &index->zip_pad.mutex_created,
+ dict_index_zip_pad_alloc, index);
+#else /* HAVE_ATOMIC_BUILTINS */
+ ut_ad(index->zip_pad.mutex_created == os_once::DONE);
+#endif /* HAVE_ATOMIC_BUILTINS */
+
+ os_fast_mutex_lock(index->zip_pad.mutex);
}
/********************************************************************//**
@@ -670,7 +756,7 @@ dict_table_autoinc_initialize(
dict_table_t* table, /*!< in/out: table */
ib_uint64_t value) /*!< in: next value to assign to a row */
{
- ut_ad(mutex_own(&table->autoinc_mutex));
+ ut_ad(dict_table_autoinc_own(table));
table->autoinc = value;
}
@@ -712,7 +798,7 @@ dict_table_autoinc_read(
/*====================*/
const dict_table_t* table) /*!< in: table */
{
- ut_ad(mutex_own(&table->autoinc_mutex));
+ ut_ad(dict_table_autoinc_own(table));
return(table->autoinc);
}
@@ -728,7 +814,7 @@ dict_table_autoinc_update_if_greater(
dict_table_t* table, /*!< in/out: table */
ib_uint64_t value) /*!< in: value which was assigned to a row */
{
- ut_ad(mutex_own(&table->autoinc_mutex));
+ ut_ad(dict_table_autoinc_own(table));
if (value > table->autoinc) {
@@ -744,7 +830,7 @@ dict_table_autoinc_unlock(
/*======================*/
dict_table_t* table) /*!< in/out: table */
{
- mutex_exit(&table->autoinc_mutex);
+ mutex_exit(table->autoinc_mutex);
}
#endif /* !UNIV_HOTBACKUP */
@@ -1583,15 +1669,18 @@ dict_table_rename_in_cache(
} else if (table->space != TRX_SYS_SPACE) {
char* new_path = NULL;
- if (table->dir_path_of_temp_table != NULL) {
+ if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: trying to rename a"
" TEMPORARY TABLE ", stderr);
ut_print_name(stderr, NULL, TRUE, old_name);
- fputs(" (", stderr);
- ut_print_filename(stderr,
- table->dir_path_of_temp_table);
- fputs(" )\n", stderr);
+ if (table->dir_path_of_temp_table != NULL) {
+ fputs(" (", stderr);
+ ut_print_filename(
+ stderr, table->dir_path_of_temp_table);
+ fputs(" )\n", stderr);
+ }
+
return(DB_ERROR);
} else if (DICT_TF_HAS_DATA_DIR(table->flags)) {
@@ -2428,10 +2517,10 @@ too_big:
dict_mem_index_free(new_index);
dict_mem_index_free(index);
return(DB_TOO_BIG_RECORD);
- } else {
-
+ } else if (current_thd != NULL) {
+ /* Avoid the warning to be printed
+ during recovery. */
ib_warn_row_too_big(table);
-
}
}
@@ -4111,16 +4200,25 @@ dict_table_get_highest_foreign_id(
for (dict_foreign_set::iterator it = table->foreign_set.begin();
it != table->foreign_set.end();
++it) {
+ char fkid[MAX_TABLE_NAME_LEN+20];
foreign = *it;
- if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
- && 0 == ut_memcmp(foreign->id, table->name, len)
- && 0 == ut_memcmp(foreign->id + len,
+ strcpy(fkid, foreign->id);
+ /* Convert foreign key identifier on dictionary memory
+ cache to filename charset. */
+ innobase_convert_to_filename_charset(
+ strchr(fkid, '/') + 1,
+ strchr(foreign->id, '/') + 1,
+ MAX_TABLE_NAME_LEN);
+
+ if (ut_strlen(fkid) > ((sizeof dict_ibfk) - 1) + len
+ && 0 == ut_memcmp(fkid, table->name, len)
+ && 0 == ut_memcmp(fkid + len,
dict_ibfk, (sizeof dict_ibfk) - 1)
- && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
+ && fkid[len + ((sizeof dict_ibfk) - 1)] != '0') {
/* It is of the >= 4.0.18 format */
- id = strtoul(foreign->id + len
+ id = strtoul(fkid + len
+ ((sizeof dict_ibfk) - 1),
&endp, 10);
if (*endp == '\0') {
@@ -6679,10 +6777,10 @@ dict_index_zip_success(
return;
}
- os_fast_mutex_lock(&index->zip_pad.mutex);
+ dict_index_zip_pad_lock(index);
++index->zip_pad.success;
dict_index_zip_pad_update(&index->zip_pad, zip_threshold);
- os_fast_mutex_unlock(&index->zip_pad.mutex);
+ dict_index_zip_pad_unlock(index);
}
/*********************************************************************//**
@@ -6702,10 +6800,10 @@ dict_index_zip_failure(
return;
}
- os_fast_mutex_lock(&index->zip_pad.mutex);
+ dict_index_zip_pad_lock(index);
++index->zip_pad.failure;
dict_index_zip_pad_update(&index->zip_pad, zip_threshold);
- os_fast_mutex_unlock(&index->zip_pad.mutex);
+ dict_index_zip_pad_unlock(index);
}
@@ -6737,9 +6835,9 @@ dict_index_zip_pad_optimal_page_size(
#ifdef HAVE_ATOMIC_BUILTINS
pad = os_atomic_increment_ulint(&index->zip_pad.pad, 0);
#else /* HAVE_ATOMIC_BUILTINS */
- os_fast_mutex_lock(&index->zip_pad.mutex);
+ dict_index_zip_pad_lock(index);
pad = index->zip_pad.pad;
- os_fast_mutex_unlock(&index->zip_pad.mutex);
+ dict_index_zip_pad_unlock(index);
#endif /* HAVE_ATOMIC_BUILTINS */
ut_ad(pad < UNIV_PAGE_SIZE);
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 58781fce1d4..e830a8430b7 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
This program is free software; you can redistribute it and/or modify it under
@@ -118,8 +118,7 @@ dict_mem_table_create(
table->autoinc_lock = static_cast<ib_lock_t*>(
mem_heap_alloc(heap, lock_get_size()));
- mutex_create(autoinc_mutex_key,
- &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
+ dict_table_autoinc_create_lazy(table);
table->autoinc = 0;
@@ -199,7 +198,7 @@ dict_mem_table_free(
}
}
#ifndef UNIV_HOTBACKUP
- mutex_free(&(table->autoinc_mutex));
+ dict_table_autoinc_destroy(table);
#endif /* UNIV_HOTBACKUP */
dict_table_stats_latch_destroy(table);
@@ -319,6 +318,9 @@ dict_mem_table_col_rename_low(
ut_ad(from_len <= NAME_LEN);
ut_ad(to_len <= NAME_LEN);
+ char from[NAME_LEN];
+ strncpy(from, s, NAME_LEN);
+
if (from_len == to_len) {
/* The easy case: simply replace the column name in
table->col_names. */
@@ -386,14 +388,53 @@ dict_mem_table_col_rename_low(
foreign = *it;
- for (unsigned f = 0; f < foreign->n_fields; f++) {
- /* These can point straight to
- table->col_names, because the foreign key
- constraints will be freed at the same time
- when the table object is freed. */
- foreign->foreign_col_names[f]
- = dict_index_get_nth_field(
- foreign->foreign_index, f)->name;
+ if (foreign->foreign_index == NULL) {
+ /* We may go here when we set foreign_key_checks to 0,
+ and then try to rename a column and modify the
+ corresponding foreign key constraint. The index
+ would have been dropped, we have to find an equivalent
+ one */
+ for (unsigned f = 0; f < foreign->n_fields; f++) {
+ if (strcmp(foreign->foreign_col_names[f], from)
+ == 0) {
+
+ char** rc = const_cast<char**>(
+ foreign->foreign_col_names
+ + f);
+
+ if (to_len <= strlen(*rc)) {
+ memcpy(*rc, to, to_len + 1);
+ } else {
+ *rc = static_cast<char*>(
+ mem_heap_dup(
+ foreign->heap,
+ to,
+ to_len + 1));
+ }
+ }
+ }
+
+ dict_index_t* new_index = dict_foreign_find_index(
+ foreign->foreign_table, NULL,
+ foreign->foreign_col_names,
+ foreign->n_fields, NULL, true, false);
+ /* There must be an equivalent index in this case. */
+ ut_ad(new_index != NULL);
+
+ foreign->foreign_index = new_index;
+
+ } else {
+
+ for (unsigned f = 0; f < foreign->n_fields; f++) {
+ /* These can point straight to
+ table->col_names, because the foreign key
+ constraints will be freed at the same time
+ when the table object is freed. */
+ foreign->foreign_col_names[f]
+ = dict_index_get_nth_field(
+ foreign->foreign_index,
+ f)->name;
+ }
}
}
@@ -403,6 +444,8 @@ dict_mem_table_col_rename_low(
foreign = *it;
+ ut_ad(foreign->referenced_index != NULL);
+
for (unsigned f = 0; f < foreign->n_fields; f++) {
/* foreign->referenced_col_names[] need to be
copies, because the constraint may become
@@ -520,8 +563,7 @@ dict_mem_index_create(
dict_mem_fill_index_struct(index, heap, table_name, index_name,
space, type, n_fields);
- os_fast_mutex_init(zip_pad_mutex_key, &index->zip_pad.mutex);
-
+ dict_index_zip_pad_mutex_create_lazy(index);
return(index);
}
@@ -654,7 +696,7 @@ dict_mem_index_free(
}
#endif /* UNIV_BLOB_DEBUG */
- os_fast_mutex_free(&index->zip_pad.mutex);
+ dict_index_zip_pad_mutex_destroy(index);
mem_heap_free(index->heap);
}
@@ -728,7 +770,7 @@ dict_foreign_set_validate(
{
dict_foreign_not_exists not_exists(fk_set);
- dict_foreign_set::iterator it = std::find_if(
+ dict_foreign_set::const_iterator it = std::find_if(
fk_set.begin(), fk_set.end(), not_exists);
if (it == fk_set.end()) {
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index d93d96de80c..cb43477ed59 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -5052,6 +5052,9 @@ retry:
success = TRUE;
}
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
+
mutex_enter(&fil_system->mutex);
if (success) {
@@ -5095,6 +5098,11 @@ retry:
offset, page_size * n_pages,
node, NULL, 0, FALSE, 0);
#endif /* UNIV_HOTBACKUP */
+
+
+ DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
+ success = FALSE; errno = 28; os_has_said_disk_full = TRUE;);
+
if (success) {
os_has_said_disk_full = FALSE;
} else {
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index d1bb22ed7a9..6ecf97aaeb6 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, 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
@@ -301,44 +301,6 @@ xdes_find_bit(
}
/**********************************************************************//**
-Looks for a descriptor bit having the desired value. Scans the extent in
-a direction opposite to xdes_find_bit.
-@return bit index of the bit, ULINT_UNDEFINED if not found */
-UNIV_INLINE
-ulint
-xdes_find_bit_downward(
-/*===================*/
- xdes_t* descr, /*!< in: descriptor */
- ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
- ibool val, /*!< in: desired bit value */
- ulint hint, /*!< in: hint of which bit position would
- be desirable */
- mtr_t* mtr) /*!< in/out: mini-transaction */
-{
- ulint i;
-
- ut_ad(descr && mtr);
- ut_ad(val <= TRUE);
- ut_ad(hint < FSP_EXTENT_SIZE);
- ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_X_FIX));
- for (i = hint + 1; i > 0; i--) {
- if (val == xdes_mtr_get_bit(descr, bit, i - 1, mtr)) {
-
- return(i - 1);
- }
- }
-
- for (i = FSP_EXTENT_SIZE - 1; i > hint; i--) {
- if (val == xdes_mtr_get_bit(descr, bit, i, mtr)) {
-
- return(i);
- }
- }
-
- return(ULINT_UNDEFINED);
-}
-
-/**********************************************************************//**
Returns the number of used pages in a descriptor.
@return number of pages used */
UNIV_INLINE
diff --git a/storage/innobase/fts/fts0ast.cc b/storage/innobase/fts/fts0ast.cc
index dd48ffee14d..030b972440f 100644
--- a/storage/innobase/fts/fts0ast.cc
+++ b/storage/innobase/fts/fts0ast.cc
@@ -694,3 +694,51 @@ fts_ast_string_print(
printf("\n");
}
+
+#ifdef UNIV_DEBUG
+const char*
+fts_ast_oper_name_get(fts_ast_oper_t oper)
+{
+ switch(oper) {
+ case FTS_NONE:
+ return("FTS_NONE");
+ case FTS_IGNORE:
+ return("FTS_IGNORE");
+ case FTS_EXIST:
+ return("FTS_EXIST");
+ case FTS_NEGATE:
+ return("FTS_NEGATE");
+ case FTS_INCR_RATING:
+ return("FTS_INCR_RATING");
+ case FTS_DECR_RATING:
+ return("FTS_DECR_RATING");
+ case FTS_DISTANCE:
+ return("FTS_DISTANCE");
+ case FTS_IGNORE_SKIP:
+ return("FTS_IGNORE_SKIP");
+ case FTS_EXIST_SKIP:
+ return("FTS_EXIST_SKIP");
+ }
+ ut_ad(0);
+}
+
+const char*
+fts_ast_node_type_get(fts_ast_type_t type)
+{
+ switch (type) {
+ case FTS_AST_OPER:
+ return("FTS_AST_OPER");
+ case FTS_AST_NUMB:
+ return("FTS_AST_NUMB");
+ case FTS_AST_TERM:
+ return("FTS_AST_TERM");
+ case FTS_AST_TEXT:
+ return("FTS_AST_TEXT");
+ case FTS_AST_LIST:
+ return("FTS_AST_LIST");
+ case FTS_AST_SUBEXP_LIST:
+ return("FTS_AST_SUBEXP_LIST");
+ }
+ ut_ad(0);
+}
+#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index e1b9c95c26e..4351dc0b765 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, 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
@@ -81,11 +81,13 @@ ulint n_nodes = 0;
/** Error condition reported by fts_utf8_decode() */
const ulint UTF8_ERROR = 0xFFFFFFFF;
+#ifdef FTS_CACHE_SIZE_DEBUG
/** The cache size permissible lower limit (1K) */
static const ulint FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB = 1;
/** The cache size permissible upper limit (1G) */
static const ulint FTS_CACHE_SIZE_UPPER_LIMIT_IN_MB = 1024;
+#endif /* FTS_CACHE_SIZE_DEBUG */
/** Time to sleep after DEADLOCK error before retrying operation. */
static const ulint FTS_DEADLOCK_RETRY_WAIT = 100000;
@@ -191,7 +193,7 @@ static const char* fts_create_common_tables_sql = {
""
"CREATE TABLE \"%s_CONFIG\" (\n"
" key CHAR(50),\n"
- " value CHAR(50) NOT NULL\n"
+ " value CHAR(200) NOT NULL\n"
") COMPACT;\n"
"CREATE UNIQUE CLUSTERED INDEX IND ON \"%s_CONFIG\"(key);\n"
};
@@ -329,27 +331,6 @@ fts_update_sync_doc_id(
doc_id_t doc_id, /*!< in: last document id */
trx_t* trx) /*!< in: update trx, or NULL */
__attribute__((nonnull(1)));
-/********************************************************************
-Check if we should stop. */
-UNIV_INLINE
-ibool
-fts_is_stop_signalled(
-/*==================*/
- fts_t* fts) /*!< in: fts instance */
-{
- ibool stop_signalled = FALSE;
-
- mutex_enter(&fts->bg_threads_mutex);
-
- if (fts->fts_status & BG_THREAD_STOP) {
-
- stop_signalled = TRUE;
- }
-
- mutex_exit(&fts->bg_threads_mutex);
-
- return(stop_signalled);
-}
/****************************************************************//**
This function loads the default InnoDB stopword list */
@@ -3409,7 +3390,7 @@ fts_fetch_doc_from_rec(
doc->charset = get_doc->index_cache->charset;
/* Null Field */
- if (doc->text.f_len == UNIV_SQL_NULL) {
+ if (doc->text.f_len == UNIV_SQL_NULL || doc->text.f_len == 0) {
continue;
}
@@ -5545,7 +5526,7 @@ fts_savepoint_lookup(
/*********************************************************************//**
Release the savepoint data identified by name. All savepoints created
-after the named savepoint are also released.
+after the named savepoint are kept.
@return DB_SUCCESS or error code */
UNIV_INTERN
void
@@ -5554,81 +5535,37 @@ fts_savepoint_release(
trx_t* trx, /*!< in: transaction */
const char* name) /*!< in: savepoint name */
{
- ulint i;
- ib_vector_t* savepoints;
- ulint top_of_stack = 0;
-
ut_a(name != NULL);
- savepoints = trx->fts_trx->savepoints;
+ ib_vector_t* savepoints = trx->fts_trx->savepoints;
ut_a(ib_vector_size(savepoints) > 0);
- /* Skip the implied savepoint (first element). */
- for (i = 1; i < ib_vector_size(savepoints); ++i) {
- fts_savepoint_t* savepoint;
+ ulint i = fts_savepoint_lookup(savepoints, name);
+ if (i != ULINT_UNDEFINED) {
+ ut_a(i >= 1);
+ fts_savepoint_t* savepoint;
savepoint = static_cast<fts_savepoint_t*>(
ib_vector_get(savepoints, i));
- /* Even though we release the resources that are part
- of the savepoint, we don't (always) actually delete the
- entry. We simply set the savepoint name to NULL. Therefore
- we have to skip deleted/released entries. */
- if (savepoint->name != NULL
- && strcmp(name, savepoint->name) == 0) {
- break;
+ if (i == ib_vector_size(savepoints) - 1) {
+ /* If the savepoint is the last, we save its
+ tables to the previous savepoint. */
+ fts_savepoint_t* prev_savepoint;
+ prev_savepoint = static_cast<fts_savepoint_t*>(
+ ib_vector_get(savepoints, i - 1));
- /* Track the previous savepoint instance that will
- be at the top of the stack after the release. */
- } else if (savepoint->name != NULL) {
- /* We need to delete all entries
- greater than this element. */
- top_of_stack = i;
+ ib_rbt_t* tables = savepoint->tables;
+ savepoint->tables = prev_savepoint->tables;
+ prev_savepoint->tables = tables;
}
- }
-
- /* Only if we found and element to release. */
- if (i < ib_vector_size(savepoints)) {
- fts_savepoint_t* last_savepoint;
- fts_savepoint_t* top_savepoint;
- ib_rbt_t* tables;
-
- ut_a(top_of_stack < ib_vector_size(savepoints));
- /* Exchange tables between last savepoint and top savepoint */
- last_savepoint = static_cast<fts_savepoint_t*>(
- ib_vector_last(trx->fts_trx->savepoints));
- top_savepoint = static_cast<fts_savepoint_t*>(
- ib_vector_get(savepoints, top_of_stack));
- tables = top_savepoint->tables;
- top_savepoint->tables = last_savepoint->tables;
- last_savepoint->tables = tables;
-
- /* Skip the implied savepoint. */
- for (i = ib_vector_size(savepoints) - 1;
- i > top_of_stack;
- --i) {
-
- fts_savepoint_t* savepoint;
-
- savepoint = static_cast<fts_savepoint_t*>(
- ib_vector_get(savepoints, i));
-
- /* Skip savepoints that were released earlier. */
- if (savepoint->name != NULL) {
- savepoint->name = NULL;
- fts_savepoint_free(savepoint);
- }
-
- ib_vector_pop(savepoints);
- }
+ fts_savepoint_free(savepoint);
+ ib_vector_remove(savepoints, *(void**)savepoint);
/* Make sure we don't delete the implied savepoint. */
ut_a(ib_vector_size(savepoints) > 0);
-
- /* This must hold. */
- ut_a(ib_vector_size(savepoints) == (top_of_stack + 1));
}
}
@@ -6330,7 +6267,7 @@ fts_fake_hex_to_dec(
{
ib_id_t dec_id = 0;
char tmp_id[FTS_AUX_MIN_TABLE_ID_LENGTH];
- int ret;
+ int ret __attribute__((unused));
ret = sprintf(tmp_id, UINT64PFx, id);
ut_ad(ret == 16);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 2e2bd061d07..e096b8bf6d6 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2015, 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
@@ -42,9 +42,6 @@ Completed 2011/7/10 Sunny and Jimmy Yang
/** The FTS optimize thread's work queue. */
static ib_wqueue_t* fts_optimize_wq;
-/** The number of document ids to delete in one statement. */
-static const ulint FTS_MAX_DELETE_DOC_IDS = 1000;
-
/** Time to wait for a message. */
static const ulint FTS_QUEUE_WAIT_IN_USECS = 5000000;
@@ -1154,6 +1151,7 @@ fts_optimize_encode_node(
}
/* Calculate the space required to store the ilist. */
+ ut_ad(doc_id > node->last_doc_id);
doc_id_delta = doc_id - node->last_doc_id;
enc_len = fts_get_encoded_len(static_cast<ulint>(doc_id_delta));
@@ -1396,7 +1394,8 @@ fts_optimize_word(
src_node = (fts_node_t*) ib_vector_get(word->nodes, i);
- if (!dst_node) {
+ if (dst_node == NULL
+ || dst_node->last_doc_id > src_node->first_doc_id) {
dst_node = static_cast<fts_node_t*>(
ib_vector_push(nodes, NULL));
@@ -2577,8 +2576,6 @@ fts_optimize_add_table(
return;
}
- ut_ad(table->cached && table->fts != NULL);
-
/* Make sure table with FTS index cannot be evicted */
if (table->can_be_evicted) {
dict_table_move_from_lru_to_non_lru(table);
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 8f4813e4b3f..9fa38cde561 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2015, 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
@@ -57,9 +57,6 @@ Completed 2011/7/10 Sunny and Jimmy Yang
/*Initial byte length for 'words' in fts_ranking_t */
#define RANKING_WORDS_INIT_LEN 4
-/* Coeffecient to use for normalize relevance ranking. */
-static const double FTS_NORMALIZE_COEFF = 0.0115F;
-
// FIXME: Need to have a generic iterator that traverses the ilist.
typedef std::vector<fts_string_t> word_vector_t;
@@ -1534,7 +1531,8 @@ fts_merge_doc_ids(
{
const ib_rbt_node_t* node;
- ut_a(!rbt_empty(doc_ids));
+ DBUG_ENTER("fts_merge_doc_ids");
+
ut_a(!query->intersection);
/* To process FTS_EXIST operation (intersection), we need
@@ -1559,7 +1557,7 @@ fts_merge_doc_ids(
query, ranking->doc_id, ranking->rank);
if (query->error != DB_SUCCESS) {
- return(query->error);
+ DBUG_RETURN(query->error);
}
/* Merge words. Don't need to take operator into account. */
@@ -1578,7 +1576,7 @@ fts_merge_doc_ids(
query->intersection = NULL;
}
- return(DB_SUCCESS);
+ DBUG_RETURN(DB_SUCCESS);
}
/*****************************************************************//**
@@ -2839,11 +2837,11 @@ fts_query_visitor(
fts_query_t* query = static_cast<fts_query_t*>(arg);
ut_a(node);
+ DBUG_ENTER("fts_query_visitor");
+ DBUG_PRINT("fts", ("nodetype: %s", fts_ast_node_type_get(node->type)));
token.f_n_char = 0;
-
query->oper = oper;
-
query->cur_node = node;
switch (node->type) {
@@ -2905,7 +2903,7 @@ fts_query_visitor(
query->multi_exist = true;
}
- return(query->error);
+ DBUG_RETURN(query->error);
}
/*****************************************************************//**
@@ -2929,6 +2927,8 @@ fts_ast_visit_sub_exp(
bool will_be_ignored = false;
bool multi_exist;
+ DBUG_ENTER("fts_ast_visit_sub_exp");
+
ut_a(node->type == FTS_AST_SUBEXP_LIST);
cur_oper = query->oper;
@@ -2957,14 +2957,14 @@ fts_ast_visit_sub_exp(
/* Merge the sub-expression result with the parent result set. */
subexpr_doc_ids = query->doc_ids;
query->doc_ids = parent_doc_ids;
- if (error == DB_SUCCESS && !rbt_empty(subexpr_doc_ids)) {
+ if (error == DB_SUCCESS) {
error = fts_merge_doc_ids(query, subexpr_doc_ids);
}
/* Free current result set. Result already merged into parent. */
fts_query_free_doc_ids(query, subexpr_doc_ids);
- return(error);
+ DBUG_RETURN(error);
}
#if 0
@@ -3440,8 +3440,10 @@ fts_retrieve_ranking(
ib_rbt_bound_t parent;
fts_ranking_t new_ranking;
+ DBUG_ENTER("fts_retrieve_ranking");
+
if (!result || !result->rankings_by_id) {
- return(0);
+ DBUG_RETURN(0);
}
new_ranking.doc_id = doc_id;
@@ -3452,10 +3454,10 @@ fts_retrieve_ranking(
ranking = rbt_value(fts_ranking_t, parent.last);
- return(ranking->rank);
+ DBUG_RETURN(ranking->rank);
}
- return(0);
+ DBUG_RETURN(0);
}
/*****************************************************************//**
@@ -3472,6 +3474,8 @@ fts_query_prepare_result(
const ib_rbt_node_t* node;
bool result_is_null = false;
+ DBUG_ENTER("fts_query_prepare_result");
+
if (result == NULL) {
result = static_cast<fts_result_t*>(ut_malloc(sizeof(*result)));
@@ -3520,7 +3524,7 @@ fts_query_prepare_result(
if (query->total_size > fts_result_cache_limit) {
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
fts_query_free_result(result);
- return(NULL);
+ DBUG_RETURN(NULL);
}
}
@@ -3543,7 +3547,7 @@ fts_query_prepare_result(
ranking->rank * word_freq->idf * word_freq->idf);
}
- return(result);
+ DBUG_RETURN(result);
}
ut_a(rbt_size(query->doc_ids) > 0);
@@ -3570,7 +3574,7 @@ fts_query_prepare_result(
if (query->total_size > fts_result_cache_limit) {
query->error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
fts_query_free_result(result);
- return(NULL);
+ DBUG_RETURN(NULL);
}
}
}
@@ -3582,7 +3586,7 @@ fts_query_prepare_result(
query->doc_ids = NULL;
}
- return(result);
+ DBUG_RETURN(result);
}
/*****************************************************************//**
@@ -3594,6 +3598,8 @@ fts_query_get_result(
fts_query_t* query, /*!< in: query instance */
fts_result_t* result) /*!< in: result */
{
+ DBUG_ENTER("fts_query_get_result");
+
if (rbt_size(query->doc_ids) > 0 || query->flags == FTS_OPT_RANKING) {
/* Copy the doc ids to the result. */
result = fts_query_prepare_result(query, result);
@@ -3603,7 +3609,7 @@ fts_query_get_result(
memset(result, 0, sizeof(*result));
}
- return(result);
+ DBUG_RETURN(result);
}
/*****************************************************************//**
@@ -3681,6 +3687,7 @@ fts_query_parse(
int error;
fts_ast_state_t state;
bool mode = query->boolean_mode;
+ DBUG_ENTER("fts_query_parse");
memset(&state, 0x0, sizeof(state));
@@ -3699,7 +3706,7 @@ fts_query_parse(
query->root = state.root;
}
- return(state.root);
+ DBUG_RETURN(state.root);
}
/*******************************************************************//**
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 2c77e6c9efb..10fc11eff5e 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
@@ -499,7 +499,8 @@ ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_get_idx_field_name,
(ib_cb_t) ib_trx_get_start_time,
(ib_cb_t) ib_cfg_bk_commit_interval,
- (ib_cb_t) ib_cursor_stmt_begin
+ (ib_cb_t) ib_cursor_stmt_begin,
+ (ib_cb_t) ib_trx_read_only
};
/**
@@ -1615,6 +1616,15 @@ convert_error_code_to_mysql(
return(HA_ERR_TO_BIG_ROW);
}
+
+ case DB_TOO_BIG_FOR_REDO:
+ my_printf_error(ER_TOO_BIG_ROWSIZE, "%s" , MYF(0),
+ "The size of BLOB/TEXT data inserted"
+ " in one transaction is greater than"
+ " 10% of redo log size. Increase the"
+ " redo log size using innodb_log_file_size.");
+ return(HA_ERR_TO_BIG_ROW);
+
case DB_TOO_BIG_INDEX_COL:
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
@@ -2835,19 +2845,6 @@ trx_is_strict(
return(trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode));
}
-/**********************************************************************//**
-Determines if the current MySQL thread is running in strict mode.
-If thd==NULL, THDVAR returns the global value of innodb-strict-mode.
-@return TRUE if strict */
-UNIV_INLINE
-ibool
-thd_is_strict(
-/*==========*/
- THD* thd) /*!< in: MySQL thread descriptor */
-{
- return(THDVAR(thd, strict_mode));
-}
-
/**************************************************************//**
Resets some fields of a prebuilt struct. The template is used in fast
retrieval of just those column values MySQL needs in its processing. */
@@ -4238,7 +4235,10 @@ innobase_release_savepoint(
DBUG_ASSERT(hton == innodb_hton_ptr);
trx = check_trx_exists(thd);
- trx_start_if_not_started(trx);
+
+ if (trx->state == TRX_STATE_NOT_STARTED) {
+ trx_start_if_not_started(trx);
+ }
/* TODO: use provided savepoint data area to store savepoint data */
@@ -4907,6 +4907,8 @@ innobase_match_index_columns(
if (innodb_idx_fld >= innodb_idx_fld_end) {
DBUG_RETURN(FALSE);
}
+
+ mtype = innodb_idx_fld->col->mtype;
}
// MariaDB-5.5 compatibility
@@ -6903,12 +6905,15 @@ ha_innobase::innobase_lock_autoinc(void)
break;
case AUTOINC_NEW_STYLE_LOCKING:
- /* For simple (single/multi) row INSERTs, we fallback to the
- old style only if another transaction has already acquired
- the AUTOINC lock on behalf of a LOAD FILE or INSERT ... SELECT
- etc. type of statement. */
+ /* For simple (single/multi) row INSERTs/REPLACEs and RBR
+ events, we fallback to the old style only if another
+ transaction has already acquired the AUTOINC lock on
+ behalf of a LOAD FILE or INSERT ... SELECT etc. type of
+ statement. */
if (thd_sql_command(user_thd) == SQLCOM_INSERT
- || thd_sql_command(user_thd) == SQLCOM_REPLACE) {
+ || thd_sql_command(user_thd) == SQLCOM_REPLACE
+ || thd_sql_command(user_thd) == SQLCOM_END // RBR event
+ ) {
dict_table_t* ib_table = prebuilt->table;
/* Acquire the AUTOINC mutex. */
@@ -6917,9 +6922,11 @@ ha_innobase::innobase_lock_autoinc(void)
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (ib_table->n_waiting_or_granted_auto_inc_locks) {
- /* Release the mutex to avoid deadlocks. */
+ /* Release the mutex to avoid deadlocks and
+ fall back to old style locking. */
dict_table_autoinc_unlock(ib_table);
} else {
+ /* Do not fall back to old style locking. */
break;
}
}
@@ -8312,6 +8319,11 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
+ /* If transaction is not startted do not continue, instead return a error code. */
+ if(!(prebuilt->sql_stat_start || (prebuilt->trx && prebuilt->trx->state == 1))) {
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+
ut_a(prebuilt->trx == thd_to_trx(user_thd));
innobase_srv_conc_enter_innodb(prebuilt->trx);
@@ -11200,6 +11212,13 @@ ha_innobase::estimate_rows_upper_bound()
prebuilt->trx->op_info = "";
+ /* Set num_rows less than MERGEBUFF to simulate the case where we do
+ not have enough space to merge the externally sorted file blocks. */
+ DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF",
+ estimate = 2;
+ DBUG_SET("-d,set_num_rows_lt_MERGEBUFF");
+ );
+
DBUG_RETURN((ha_rows) estimate);
}
@@ -11465,7 +11484,6 @@ ha_innobase::info_low(
dict_table_t* ib_table;
ha_rows rec_per_key;
ib_uint64_t n_rows;
- char path[FN_REFLEN];
os_file_stat_t stat_info;
DBUG_ENTER("info");
@@ -11523,17 +11541,6 @@ ha_innobase::info_low(
"returning various info to MySQL";
}
- my_snprintf(path, sizeof(path), "%s/%s%s",
- mysql_data_home, ib_table->name, reg_ext);
-
- unpack_filename(path,path);
-
- /* Note that we do not know the access time of the table,
- nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
-
- if (os_file_get_status(path, &stat_info, false) == DB_SUCCESS) {
- stats.create_time = (ulong) stat_info.ctime;
- }
}
if (flag & HA_STATUS_VARIABLE) {
@@ -11665,6 +11672,7 @@ ha_innobase::info_low(
if (flag & HA_STATUS_CONST) {
ulong i;
+ char path[FN_REFLEN];
/* Verify the number of index in InnoDB and MySQL
matches up. If prebuilt->clust_index_was_generated
holds, InnoDB defines GEN_CLUST_INDEX internally */
@@ -11818,6 +11826,20 @@ ha_innobase::info_low(
if (!(flag & HA_STATUS_NO_LOCK)) {
dict_table_stats_unlock(ib_table, RW_S_LATCH);
}
+
+ my_snprintf(path, sizeof(path), "%s/%s%s",
+ mysql_data_home,
+ table->s->normalized_path.str,
+ reg_ext);
+
+ unpack_filename(path,path);
+
+ /* Note that we do not know the access time of the table,
+ nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
+
+ if (os_file_get_status(path, &stat_info, false) == DB_SUCCESS) {
+ stats.create_time = (ulong) stat_info.ctime;
+ }
}
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
@@ -14123,10 +14145,8 @@ ha_innobase::cmp_ref(
len1 = innobase_read_from_2_little_endian(ref1);
len2 = innobase_read_from_2_little_endian(ref2);
- ref1 += 2;
- ref2 += 2;
result = ((Field_blob*) field)->cmp(
- ref1, len1, ref2, len2);
+ ref1 + 2, len1, ref2 + 2, len2);
} else {
result = field->key_cmp(ref1, ref2);
}
@@ -18009,6 +18029,7 @@ innodb_compression_algorithm_validate(
/**********************************************************************
Issue a warning that the row is too big. */
+UNIV_INTERN
void
ib_warn_row_too_big(const dict_table_t* table)
{
@@ -18022,6 +18043,10 @@ ib_warn_row_too_big(const dict_table_t* table)
THD* thd = current_thd;
+ if (thd == NULL) {
+ return;
+ }
+
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW,
"Row size too large (> %lu). Changing some columns to TEXT"
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 4291d32b206..96a779868fb 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -129,6 +129,7 @@ my_error_innodb(
break;
case DB_OUT_OF_FILE_SPACE:
my_error(ER_RECORD_FILE_FULL, MYF(0), table);
+ ut_error;
break;
case DB_TEMP_FILE_WRITE_FAILURE:
my_error(ER_GET_ERRMSG, MYF(0),
@@ -1457,8 +1458,9 @@ innobase_create_index_field_def(
if a new clustered index is
not being created */
const KEY_PART_INFO* key_part, /*!< in: MySQL key definition */
- index_field_t* index_field) /*!< out: index field
+ index_field_t* index_field, /*!< out: index field
definition for key_part */
+ const Field** fields) /*!< in: MySQL table fields */
{
const Field* field;
ibool is_unsigned;
@@ -1475,6 +1477,7 @@ innobase_create_index_field_def(
ut_a(field);
index_field->col_no = key_part->fieldnr;
+ index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name;
col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
@@ -1509,8 +1512,9 @@ innobase_create_index_def(
bool key_clustered, /*!< in: true if this is
the new clustered index */
index_def_t* index, /*!< out: index definition */
- mem_heap_t* heap) /*!< in: heap where memory
+ mem_heap_t* heap, /*!< in: heap where memory
is allocated */
+ const Field** fields) /*!z in: MySQL table fields */
{
const KEY* key = &keys[key_number];
ulint i;
@@ -1523,6 +1527,7 @@ innobase_create_index_def(
index->fields = static_cast<index_field_t*>(
mem_heap_alloc(heap, n_fields * sizeof *index->fields));
+ memset(index->fields, 0, n_fields * sizeof *index->fields);
index->ind_type = 0;
index->key_number = key_number;
@@ -1560,7 +1565,7 @@ innobase_create_index_def(
for (i = 0; i < n_fields; i++) {
innobase_create_index_field_def(
- altered_table, &key->key_part[i], &index->fields[i]);
+ altered_table, &key->key_part[i], &index->fields[i], fields);
}
DBUG_VOID_RETURN;
@@ -1891,7 +1896,7 @@ innobase_create_key_defs(
/* Create the PRIMARY key index definition */
innobase_create_index_def(
altered_table, key_info, primary_key_number,
- TRUE, TRUE, indexdef++, heap);
+ TRUE, TRUE, indexdef++, heap, (const Field **)altered_table->field);
created_clustered:
n_add = 1;
@@ -1903,7 +1908,7 @@ created_clustered:
/* Copy the index definitions. */
innobase_create_index_def(
altered_table, key_info, i, TRUE, FALSE,
- indexdef, heap);
+ indexdef, heap, (const Field **)altered_table->field);
if (indexdef->ind_type & DICT_FTS) {
n_fts_add++;
@@ -1948,7 +1953,7 @@ created_clustered:
for (ulint i = 0; i < n_add; i++) {
innobase_create_index_def(
altered_table, key_info, add[i], FALSE, FALSE,
- indexdef, heap);
+ indexdef, heap, (const Field **)altered_table->field);
if (indexdef->ind_type & DICT_FTS) {
n_fts_add++;
@@ -1965,6 +1970,7 @@ created_clustered:
index->fields = static_cast<index_field_t*>(
mem_heap_alloc(heap, sizeof *index->fields));
+ memset(index->fields, 0, sizeof *index->fields);
index->n_fields = 1;
index->fields->col_no = fts_doc_id_col;
index->fields->prefix_len = 0;
@@ -4463,11 +4469,15 @@ err_exit:
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
+ std::list<dict_foreign_t*> fk_evict;
+ bool foreign_modified;
+
for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin();
it != user_table->foreign_set.end();
++it) {
dict_foreign_t* foreign = *it;
+ foreign_modified = false;
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->foreign_col_names[i], from)) {
@@ -4495,6 +4505,11 @@ rename_foreign:
if (error != DB_SUCCESS) {
goto err_exit;
}
+ foreign_modified = true;
+ }
+
+ if (foreign_modified) {
+ fk_evict.push_back(foreign);
}
}
@@ -4503,7 +4518,9 @@ rename_foreign:
it != user_table->referenced_set.end();
++it) {
+ foreign_modified = false;
dict_foreign_t* foreign = *it;
+
for (unsigned i = 0; i < foreign->n_fields; i++) {
if (strcmp(foreign->referenced_col_names[i], from)) {
continue;
@@ -4530,7 +4547,17 @@ rename_foreign:
if (error != DB_SUCCESS) {
goto err_exit;
}
+ foreign_modified = true;
}
+
+ if (foreign_modified) {
+ fk_evict.push_back(foreign);
+ }
+ }
+
+ if (new_clustered) {
+ std::for_each(fk_evict.begin(), fk_evict.end(),
+ dict_foreign_remove_from_cache);
}
trx->op_info = "";
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 20a411a6b08..2211243fbf3 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2015, 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
@@ -158,9 +158,12 @@ do { \
} \
} while (0)
-#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
- !defined __INTEL_COMPILER && !defined __clang__
+#if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER && !defined __clang__
+#ifdef HAVE_C99_INITIALIZERS
+#define STRUCT_FLD(name, value) .name = value
+#else
#define STRUCT_FLD(name, value) name: value
+#endif /* HAVE_C99_INITIALIZERS */
#else
#define STRUCT_FLD(name, value) value
#endif
@@ -3261,8 +3264,6 @@ i_s_fts_index_cache_fill_one_index(
for (rbt_node = rbt_first(index_cache->words);
rbt_node;
rbt_node = rbt_next(index_cache->words, rbt_node)) {
- doc_id_t doc_id = 0;
-
fts_tokenizer_word_t* word;
word = rbt_value(fts_tokenizer_word_t, rbt_node);
@@ -3288,6 +3289,7 @@ i_s_fts_index_cache_fill_one_index(
fts_node_t* node;
byte* ptr;
ulint decoded = 0;
+ doc_id_t doc_id = 0;
node = static_cast<fts_node_t*> (ib_vector_get(
word->nodes, i));
@@ -3961,10 +3963,14 @@ i_s_fts_config_fill(
if (!user_table) {
DBUG_RETURN(0);
+ } else if (!dict_table_has_fts_index(user_table)) {
+ dict_table_close(user_table, FALSE, FALSE);
+
+ DBUG_RETURN(0);
}
trx = trx_allocate_for_background();
- trx->op_info = "Select for FTS DELETE TABLE";
+ trx->op_info = "Select for FTS CONFIG TABLE";
FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table);
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 2082c0d194b..5fd0fdcb10a 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -2837,6 +2837,14 @@ ibuf_contract_in_background(
mutex_exit(&ibuf_mutex);
}
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+ if (ibuf_debug) {
+ return(0);
+ }
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
+
+
while (sum_pages < n_pages) {
ulint n_bytes;
@@ -3885,7 +3893,7 @@ check_watch:
{
buf_page_t* bpage;
buf_pool_t* buf_pool = buf_pool_get(space, page_no);
- bpage = buf_page_hash_get(buf_pool, space, page_no);
+ bpage = buf_page_get_also_watch(buf_pool, space, page_no);
if (UNIV_LIKELY_NULL(bpage)) {
/* A buffer pool watch has been set or the
diff --git a/storage/innobase/include/api0api.h b/storage/innobase/include/api0api.h
index d77d691becc..e4c9c941de5 100644
--- a/storage/innobase/include/api0api.h
+++ b/storage/innobase/include/api0api.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, 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
@@ -494,6 +494,14 @@ ib_trx_state(
/*=========*/
ib_trx_t ib_trx); /*!< in: trx handle */
+
+/*****************************************************************//**
+Check if the transaction is read_only */
+ib_u32_t
+ib_trx_read_only(
+/*=============*/
+ ib_trx_t ib_trx); /*!< in: trx handle */
+
/*****************************************************************//**
Release the resources of the transaction. If the transaction was
selected as a victim by InnoDB and rolled back then use this function
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 16bfaac2efc..ebed2bb62a6 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1269,7 +1269,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
mode value is ignored. It is up to the caller to release the
lock. If the block is found and the lock is NULL then the page_hash
lock is released by this function.
-@return block, NULL if not found */
+@return block, NULL if not found, or watch sentinel (if watch is true) */
UNIV_INLINE
buf_page_t*
buf_page_hash_get_locked(
@@ -1285,9 +1285,11 @@ buf_page_hash_get_locked(
found. NULL otherwise. If NULL
is passed then the hash_lock
is released by this function */
- ulint lock_mode); /*!< in: RW_LOCK_EX or
+ ulint lock_mode, /*!< in: RW_LOCK_EX or
RW_LOCK_SHARED. Ignored if
lock == NULL */
+ bool watch = false); /*!< in: if true, return watch
+ sentinel also. */
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
If the block is found and lock is not NULL then the appropriate
@@ -1327,6 +1329,8 @@ buf_page_hash_get_low() function.
buf_page_hash_get_locked(b, s, o, l, RW_LOCK_EX)
#define buf_page_hash_get(b, s, o) \
buf_page_hash_get_locked(b, s, o, NULL, 0)
+#define buf_page_get_also_watch(b, s, o) \
+ buf_page_hash_get_locked(b, s, o, NULL, 0, true)
#define buf_block_hash_get_s_locked(b, s, o, l) \
buf_block_hash_get_locked(b, s, o, l, RW_LOCK_SHARED)
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 6e419674f98..56616c6deeb 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -1172,7 +1172,7 @@ page_hash lock is acquired in the specified lock mode. Otherwise,
mode value is ignored. It is up to the caller to release the
lock. If the block is found and the lock is NULL then the page_hash
lock is released by this function.
-@return block, NULL if not found */
+@return block, NULL if not found, or watch sentinel (if watch is true) */
UNIV_INLINE
buf_page_t*
buf_page_hash_get_locked(
@@ -1188,9 +1188,11 @@ buf_page_hash_get_locked(
found. NULL otherwise. If NULL
is passed then the hash_lock
is released by this function */
- ulint lock_mode) /*!< in: RW_LOCK_EX or
+ ulint lock_mode, /*!< in: RW_LOCK_EX or
RW_LOCK_SHARED. Ignored if
lock == NULL */
+ bool watch) /*!< in: if true, return watch
+ sentinel also. */
{
buf_page_t* bpage = NULL;
ulint fold;
@@ -1221,7 +1223,9 @@ buf_page_hash_get_locked(
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
if (!bpage || buf_pool_watch_is_sentinel(buf_pool, bpage)) {
- bpage = NULL;
+ if (!watch) {
+ bpage = NULL;
+ }
goto unlock_and_exit;
}
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index 71916cb33f2..1e87ce3fdb8 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, 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
@@ -130,7 +130,8 @@ enum dberr_t {
DB_TEMP_FILE_WRITE_FAILURE, /*!< Temp file write failure */
DB_FTS_TOO_MANY_WORDS_IN_PHRASE,
/*< Too many words in a phrase */
-
+ DB_TOO_BIG_FOR_REDO, /* Record length greater than 10%
+ of redo log */
/* The following are partial failure codes */
DB_FAIL = 1000,
DB_OVERFLOW,
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 8d6243e1aaa..db39d502db6 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -600,6 +600,17 @@ dict_table_get_col_name(
ulint col_nr) /*!< in: column number */
__attribute__((nonnull, warn_unused_result));
/**********************************************************************//**
+Returns a column's name.
+@return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+ const dict_table_t* table, /*!< in: table */
+ const char* col_name)/*!< in: MySQL table column name */
+ __attribute__((nonnull, warn_unused_result));
+/**********************************************************************//**
Prints a table data. */
UNIV_INTERN
void
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 5e690128042..e64b4e18a2e 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -51,6 +51,7 @@ Created 1/8/1996 Heikki Tuuri
#include <set>
#include <algorithm>
#include <iterator>
+#include <ostream>
/* Forward declaration. */
struct ib_rbt_t;
@@ -599,11 +600,12 @@ extern ulong zip_failure_threshold_pct;
compression failures */
extern ulong zip_pad_max;
-/** Data structure to hold information about about how much space in
+/** Data structure to hold information about how much space in
an uncompressed page should be left as padding to avoid compression
failures. This estimate is based on a self-adapting heuristic. */
struct zip_pad_info_t {
- os_fast_mutex_t mutex; /*!< mutex protecting the info */
+ os_fast_mutex_t*
+ mutex; /*!< mutex protecting the info */
ulint pad; /*!< number of bytes used as pad */
ulint success;/*!< successful compression ops during
current round */
@@ -611,6 +613,9 @@ struct zip_pad_info_t {
current round */
ulint n_rounds;/*!< number of currently successful
rounds */
+ volatile os_once::state_t
+ mutex_created;
+ /*!< Creation state of mutex member */
};
/** Data structure for an index. Most fields will be
@@ -1211,9 +1216,14 @@ struct dict_table_t{
space from the lock heap of the trx:
otherwise the lock heap would grow rapidly
if we do a large insert from a select */
- ib_mutex_t autoinc_mutex;
+ ib_mutex_t* autoinc_mutex;
/*!< mutex protecting the autoincrement
counter */
+
+ /** Creation state of autoinc_mutex member */
+ volatile os_once::state_t
+ autoinc_mutex_created;
+
ib_uint64_t autoinc;/*!< autoinc counter value to give to the
next inserted row */
ulong n_waiting_or_granted_auto_inc_locks;
@@ -1276,6 +1286,111 @@ struct dict_foreign_add_to_referenced_table {
}
};
+/** Destroy the autoinc latch of the given table.
+This function is only called from either single threaded environment
+or from a thread that has not shared the table object with other threads.
+@param[in,out] table table whose stats latch to destroy */
+inline
+void
+dict_table_autoinc_destroy(
+ dict_table_t* table)
+{
+ if (table->autoinc_mutex_created == os_once::DONE
+ && table->autoinc_mutex != NULL) {
+ mutex_free(table->autoinc_mutex);
+ delete table->autoinc_mutex;
+ }
+}
+
+/** Allocate and init the autoinc latch of a given table.
+This function must not be called concurrently on the same table object.
+@param[in,out] table_void table whose autoinc latch to create */
+void
+dict_table_autoinc_alloc(
+ void* table_void);
+
+/** Allocate and init the zip_pad_mutex of a given index.
+This function must not be called concurrently on the same index object.
+@param[in,out] index_void index whose zip_pad_mutex to create */
+void
+dict_index_zip_pad_alloc(
+ void* index_void);
+
+/** Request for lazy creation of the autoinc latch of a given table.
+This function is only called from either single threaded environment
+or from a thread that has not shared the table object with other threads.
+@param[in,out] table table whose autoinc latch is to be created. */
+inline
+void
+dict_table_autoinc_create_lazy(
+ dict_table_t* table)
+{
+#ifdef HAVE_ATOMIC_BUILTINS
+ table->autoinc_mutex = NULL;
+ table->autoinc_mutex_created = os_once::NEVER_DONE;
+#else /* HAVE_ATOMIC_BUILTINS */
+ dict_table_autoinc_alloc(table);
+ table->autoinc_mutex_created = os_once::DONE;
+#endif /* HAVE_ATOMIC_BUILTINS */
+}
+
+/** Request a lazy creation of dict_index_t::zip_pad::mutex.
+This function is only called from either single threaded environment
+or from a thread that has not shared the table object with other threads.
+@param[in,out] index index whose zip_pad mutex is to be created */
+inline
+void
+dict_index_zip_pad_mutex_create_lazy(
+ dict_index_t* index)
+{
+#ifdef HAVE_ATOMIC_BUILTINS
+ index->zip_pad.mutex = NULL;
+ index->zip_pad.mutex_created = os_once::NEVER_DONE;
+#else /* HAVE_ATOMIC_BUILTINS */
+ dict_index_zip_pad_alloc(index);
+ index->zip_pad.mutex_created = os_once::DONE;
+#endif /* HAVE_ATOMIC_BUILTINS */
+}
+
+/** Destroy the zip_pad_mutex of the given index.
+This function is only called from either single threaded environment
+or from a thread that has not shared the table object with other threads.
+@param[in,out] table table whose stats latch to destroy */
+inline
+void
+dict_index_zip_pad_mutex_destroy(
+ dict_index_t* index)
+{
+ if (index->zip_pad.mutex_created == os_once::DONE
+ && index->zip_pad.mutex != NULL) {
+ os_fast_mutex_free(index->zip_pad.mutex);
+ delete index->zip_pad.mutex;
+ }
+}
+
+/** Release the zip_pad_mutex of a given index.
+@param[in,out] index index whose zip_pad_mutex is to be released */
+inline
+void
+dict_index_zip_pad_unlock(
+ dict_index_t* index)
+{
+ os_fast_mutex_unlock(index->zip_pad.mutex);
+}
+
+#ifdef UNIV_DEBUG
+/** Check if the current thread owns the autoinc_mutex of a given table.
+@param[in] table the autoinc_mutex belongs to this table
+@return true, if the current thread owns the autoinc_mutex, false otherwise.*/
+inline
+bool
+dict_table_autoinc_own(
+ const dict_table_t* table)
+{
+ return(mutex_own(table->autoinc_mutex));
+}
+#endif /* UNIV_DEBUG */
+
#ifndef UNIV_NONINL
#include "dict0mem.ic"
#endif
diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h
index 50ee587e282..b2380f78b39 100644
--- a/storage/innobase/include/fts0ast.h
+++ b/storage/innobase/include/fts0ast.h
@@ -329,4 +329,11 @@ struct fts_ast_state_t {
tokenization */
};
+#ifdef UNIV_DEBUG
+const char*
+fts_ast_oper_name_get(fts_ast_oper_t oper);
+const char*
+fts_ast_node_type_get(fts_ast_type_t type);
+#endif /* UNIV_DEBUG */
+
#endif /* INNOBASE_FSTS0AST_H */
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index a02b8f1893a..20409f85e0c 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2006, 2014, 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
diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h
index 9f7ab9f76b6..16423e6a282 100644
--- a/storage/innobase/include/lock0priv.h
+++ b/storage/innobase/include/lock0priv.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, MariaDB Corporation
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
@@ -72,6 +73,12 @@ struct lock_t {
hash_node_t hash; /*!< hash chain node for a record
lock */
dict_index_t* index; /*!< index for a record lock */
+
+ /* Statistics for how long lock has been held and time
+ how long this lock had to be waited before it was granted */
+ time_t requested_time; /*!< Lock request time */
+ ulint wait_time; /*!< Time waited this lock or 0 */
+
union {
lock_table_t tab_lock;/*!< table lock */
lock_rec_t rec_lock;/*!< record lock */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index 8f8aef4f45c..4126be51ae9 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -386,10 +386,10 @@ to original un-instrumented file I/O APIs */
enum os_file_type_t {
OS_FILE_TYPE_UNKNOWN = 0,
- OS_FILE_TYPE_FILE, /* regular file */
+ OS_FILE_TYPE_FILE, /* regular file
+ (or a character/block device) */
OS_FILE_TYPE_DIR, /* directory */
- OS_FILE_TYPE_LINK, /* symbolic link */
- OS_FILE_TYPE_BLOCK /* block device */
+ OS_FILE_TYPE_LINK /* symbolic link */
};
/* Maximum path string length in bytes when referring to tables with in the
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index b16a99b51c0..feb64fb1e41 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -452,7 +452,7 @@ Returns the old value of *ptr, atomically sets *ptr to new_val */
# define os_atomic_test_and_set_ulint(ptr, new_val) \
__sync_lock_test_and_set(ptr, new_val)
-#ifdef __powerpc__
+#if defined(__powerpc__) || defined(__aarch64__)
/*
os_atomic_test_and_set_byte_release() should imply a release barrier before
setting, and a full barrier after. But __sync_lock_test_and_set() is only
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index cb6633bb941..bd9bce75e57 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2015, 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
@@ -1121,6 +1121,20 @@ page_find_rec_with_heap_no(
const rec_t*
page_find_rec_max_not_deleted(
const page_t* page);
+
+/** Issue a warning when the checksum that is stored in the page is valid,
+but different than the global setting innodb_checksum_algorithm.
+@param[in] current_algo current checksum algorithm
+@param[in] page_checksum page valid checksum
+@param[in] space_id tablespace id
+@param[in] page_no page number */
+void
+page_warn_strict_checksum(
+ srv_checksum_algorithm_t curr_algo,
+ srv_checksum_algorithm_t page_checksum,
+ ulint space_id,
+ ulint page_no);
+
#ifdef UNIV_MATERIALIZE
#undef UNIV_INLINE
#define UNIV_INLINE UNIV_INLINE_ORIGINAL
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index 6fe6934e35c..0c2abef4b09 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -545,6 +545,21 @@ from outside the buffer pool.
# define UNIV_INLINE UNIV_INLINE_ORIGINAL
#endif
+#ifdef UNIV_INNOCHECKSUM
+/** Issue a warning when the checksum that is stored in the page is valid,
+but different than the global setting innodb_checksum_algorithm.
+@param[in] current_algo current checksum algorithm
+@param[in] page_checksum page valid checksum
+@param[in] space_id tablespace id
+@param[in] page_no page number */
+void
+page_warn_strict_checksum(
+ srv_checksum_algorithm_t curr_algo,
+ srv_checksum_algorithm_t page_checksum,
+ ulint space_id,
+ ulint page_no);
+#endif /* UNIV_INNOCHECKSUM */
+
#ifndef UNIV_INNOCHECKSUM
#ifndef UNIV_NONINL
# include "page0zip.ic"
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 390c0ce038b..de353d46202 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2014, 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
@@ -95,6 +95,7 @@ struct index_field_t {
ulint col_no; /*!< column offset */
ulint prefix_len; /*!< column prefix length, or 0
if indexing the whole column */
+ const char* col_name; /*!< column name or NULL */
};
/** Definition of an index being created */
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index bb05ae7daf1..69251da6e35 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -386,6 +386,7 @@ rw_lock_x_lock_func_nowait(
ulint line) /*!< in: line where requested */
{
ibool success;
+ ibool local_recursive= lock->recursive;
#ifdef INNODB_RW_LOCKS_USE_ATOMICS
success = os_compare_and_swap_lint(&lock->lock_word, X_LOCK_DECR, 0);
@@ -400,10 +401,14 @@ rw_lock_x_lock_func_nowait(
mutex_exit(&(lock->mutex));
#endif
+ /* Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before os_compare_and_swap_lint(),
+ which implies full memory barrier in current implementation. */
if (success) {
rw_lock_set_writer_id_and_recursion_flag(lock, TRUE);
- } else if (lock->recursive
+ } else if (local_recursive
&& os_thread_eq(lock->writer_thread,
os_thread_get_curr_id())) {
/* Relock: this lock_word modification is safe since no other
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index 9d020a10725..d5ab83d7767 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2014, 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
@@ -32,6 +32,8 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
+extern bool trx_rollback_or_clean_is_active;
+
/*******************************************************************//**
Determines if this transaction is rolling back an incomplete transaction
in crash recovery.
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index fcc9ed05081..57b91844aca 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -1009,6 +1009,19 @@ struct trx_t{
/*------------------------------*/
char detailed_error[256]; /*!< detailed error message for last
error, or empty. */
+ /* Lock wait statistics */
+ ulint n_rec_lock_waits;
+ /*!< Number of record lock waits,
+ might not be exactly correct. */
+ ulint n_table_lock_waits;
+ /*!< Number of table lock waits,
+ might not be exactly correct. */
+ ulint total_rec_lock_wait_time;
+ /*!< Total rec lock wait time up
+ to this moment. */
+ ulint total_table_lock_wait_time;
+ /*!< Total table lock wait time
+ up to this moment. */
};
/* Transaction isolation levels (trx->isolation_level) */
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index 9e3a9eda60c..76c0d21fab8 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 22
+#define INNODB_VERSION_BUGFIX 25
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 5ea187bdb3c..7755d6d5ef1 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2014, 2015, MariaDB Corporation
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
@@ -374,7 +375,7 @@ struct lock_stack_t {
ulint heap_no; /*!< heap number if rec lock */
};
-extern "C" void thd_report_wait_for(const MYSQL_THD thd, MYSQL_THD other_thd);
+extern "C" void thd_report_wait_for(MYSQL_THD thd, MYSQL_THD other_thd);
extern "C" int thd_need_wait_for(const MYSQL_THD thd);
extern "C"
int thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd);
@@ -384,8 +385,10 @@ because there is no parallel deadlock check. This stack is protected by
the lock_sys_t::mutex. */
static lock_stack_t* lock_stack;
+#ifdef UNIV_DEBUG
/** The count of the types of locks. */
static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix);
+#endif /* UNIV_DEBUG */
#ifdef UNIV_PFS_MUTEX
/* Key to register mutex with performance schema */
@@ -1886,6 +1889,9 @@ lock_rec_create(
/* Set the bit corresponding to rec */
lock_rec_set_nth_bit(lock, heap_no);
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
+
index->table->n_rec_locks++;
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
@@ -2034,6 +2040,8 @@ lock_rec_enqueue_waiting(
MONITOR_INC(MONITOR_LOCKREC_WAIT);
+ trx->n_rec_lock_waits++;
+
return(DB_LOCK_WAIT);
}
@@ -2066,7 +2074,8 @@ lock_rec_add_to_queue(
ut_ad(lock_mutex_own());
ut_ad(caller_owns_trx_mutex == trx_mutex_own(trx));
- ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
+ ut_ad(dict_index_is_clust(index)
+ || dict_index_get_online_status(index) != ONLINE_INDEX_CREATION);
#ifdef UNIV_DEBUG
switch (type_mode & LOCK_MODE_MASK) {
case LOCK_X:
@@ -2453,6 +2462,17 @@ lock_grant(
}
}
+ /* Cumulate total lock wait time for statistics */
+ if (lock_get_type_low(lock) & LOCK_TABLE) {
+ lock->trx->total_table_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ } else {
+ lock->trx->total_rec_lock_wait_time +=
+ (ulint)difftime(ut_time(), lock->trx->lock.wait_started);
+ }
+
+ lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time);
+
trx_mutex_exit(lock->trx);
}
@@ -4214,6 +4234,8 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
+ lock->requested_time = ut_time();
+ lock->wait_time = 0;
lock->un_member.tab_lock.table = table;
@@ -4457,6 +4479,7 @@ lock_table_enqueue_waiting(
trx->lock.wait_started = ut_time();
trx->lock.was_chosen_as_deadlock_victim = FALSE;
+ trx->n_table_lock_waits++;
ut_a(que_thr_stop(thr));
@@ -5132,6 +5155,10 @@ lock_table_print(
fputs(" waiting", file);
}
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
}
@@ -5163,7 +5190,14 @@ lock_rec_print(
fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
(ulong) space, (ulong) page_no,
(ulong) lock_rec_get_n_bits(lock));
+
dict_index_name_print(file, lock->trx, lock->index);
+
+ /* Print number of table locks */
+ fprintf(file, " trx table locks %lu total table locks %lu ",
+ ib_vector_size(lock->trx->lock.table_locks),
+ UT_LIST_GET_LEN(lock->index->table->locks));
+
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
if (lock_get_mode(lock) == LOCK_S) {
@@ -5192,6 +5226,10 @@ lock_rec_print(
mtr_start(&mtr);
+ fprintf(file, " lock hold time %lu wait time before grant %lu ",
+ (ulint)difftime(ut_time(), lock->requested_time),
+ lock->wait_time);
+
putc('\n', file);
block = buf_page_try_get(space, page_no, &mtr);
@@ -5450,6 +5488,14 @@ loop:
trx->read_view->up_limit_id);
}
+ /* Total trx lock waits and times */
+ fprintf(file, "Trx #rec lock waits %lu #table lock waits %lu\n",
+ trx->n_rec_lock_waits, trx->n_table_lock_waits);
+ fprintf(file, "Trx total rec lock wait time %lu SEC\n",
+ trx->total_rec_lock_wait_time);
+ fprintf(file, "Trx total table lock wait time %lu SEC\n",
+ trx->total_table_lock_wait_time);
+
if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
fprintf(file,
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index d0f17a43cf3..d65baa316d8 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -49,7 +49,7 @@ Created 12/9/1995 Heikki Tuuri
#include "srv0start.h"
#include "trx0sys.h"
#include "trx0trx.h"
-#include "ha_prototypes.h"
+#include "trx0roll.h"
#include "srv0mon.h"
/*
@@ -3213,6 +3213,12 @@ logs_empty_and_mark_files_at_shutdown(void)
ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown...");
+ while (srv_fast_shutdown == 0 && trx_rollback_or_clean_is_active) {
+ /* we should wait until rollback after recovery end
+ for slow shutdown */
+ os_thread_sleep(100000);
+ }
+
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 0143ecf1c1e..3632c45d603 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
@@ -1863,7 +1863,7 @@ loop:
goto loop;
}
- ut_ad(!allow_ibuf == mutex_own(&log_sys->mutex));
+ ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex));
if (!allow_ibuf) {
recv_no_ibuf_operations = TRUE;
@@ -3487,6 +3487,7 @@ recv_recovery_rollback_active(void)
/* Rollback the uncommitted transactions which have no user
session */
+ trx_rollback_or_clean_is_active = true;
os_thread_create(trx_rollback_or_clean_all_recovered, 0, 0);
}
}
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 4c1529ac835..525b537ddd7 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1,6 +1,6 @@
/***********************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2015, MariaDB Corporation.
@@ -800,7 +800,7 @@ os_file_handle_error_cond_exit(
os_has_said_disk_full = TRUE;
fflush(stderr);
-
+ ut_error;
return(FALSE);
case OS_FILE_AIO_RESOURCES_RESERVED:
@@ -2937,13 +2937,18 @@ try_again:
if (fil_page_is_compressed((byte *)buf)) {
fil_decompress_page(NULL, (byte *)buf, n, NULL);
}
-
return(TRUE);
+ } else if (ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in system call pread(). The operating"
+ " system error number is %lu.",(ulint) errno);
+ } else {
+ /* Partial read occured */
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tried to read " ULINTPF " bytes at offset "
+ UINT64PF ". Was only able to read %ld.",
+ n, offset, (lint) ret);
}
-
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Tried to read " ULINTPF " bytes at offset " UINT64PF ". "
- "Was only able to read %ld.", n, offset, (lint) ret);
#endif /* __WIN__ */
#ifdef __WIN__
error_handling:
@@ -3081,8 +3086,17 @@ try_again:
if (fil_page_is_compressed((byte *)buf)) {
fil_decompress_page(NULL, (byte *)buf, n, NULL);
}
-
return(TRUE);
+ } else if (ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Error in system call pread(). The operating"
+ " system error number is %lu.",(ulint) errno);
+ } else {
+ /* Partial read occured */
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tried to read " ULINTPF " bytes at offset "
+ UINT64PF ". Was only able to read %ld.",
+ n, offset, (lint) ret);
}
#endif /* __WIN__ */
#ifdef __WIN__
@@ -3302,18 +3316,26 @@ retry:
if (!os_has_said_disk_full) {
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: Write to file %s failed"
- " at offset " UINT64PF ".\n"
- "InnoDB: %lu bytes should have been written,"
- " only %ld were written.\n"
- "InnoDB: Operating system error number %lu.\n"
- "InnoDB: Check that your OS and file system"
- " support files of this size.\n"
- "InnoDB: Check also that the disk is not full"
- " or a disk quota exceeded.\n",
- name, offset, n, (lint) ret,
- (ulint) errno);
+ if(ret == -1) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Failure of system call pwrite(). Operating"
+ " system error number is %lu.",
+ (ulint) errno);
+ } else {
+ fprintf(stderr,
+ " InnoDB: Error: Write to file %s failed"
+ " at offset " UINT64PF ".\n"
+ "InnoDB: %lu bytes should have been written,"
+ " only %ld were written.\n"
+ "InnoDB: Operating system error number %lu.\n"
+ "InnoDB: Check that your OS and file system"
+ " support files of this size.\n"
+ "InnoDB: Check also that the disk is not full"
+ " or a disk quota exceeded.\n",
+ name, offset, n, (lint) ret,
+ (ulint) errno);
+ }
+
if (strerror(errno) != NULL) {
fprintf(stderr,
"InnoDB: Error number %d means '%s'.\n",
@@ -3500,8 +3522,9 @@ os_file_get_status(
stat_info->type = OS_FILE_TYPE_LINK;
break;
case S_IFBLK:
- stat_info->type = OS_FILE_TYPE_BLOCK;
- break;
+ /* Handle block device as regular file. */
+ case S_IFCHR:
+ /* Handle character device as regular file. */
case S_IFREG:
stat_info->type = OS_FILE_TYPE_FILE;
break;
@@ -3510,8 +3533,8 @@ os_file_get_status(
}
- if (check_rw_perm && (stat_info->type == OS_FILE_TYPE_FILE
- || stat_info->type == OS_FILE_TYPE_BLOCK)) {
+ if (check_rw_perm && stat_info->type == OS_FILE_TYPE_FILE) {
+
int fh;
int access;
@@ -4977,7 +5000,7 @@ os_aio_func(
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
- mode = OS_AIO_SYNC;);
+ mode = OS_AIO_SYNC; os_has_said_disk_full = FALSE;);
if (mode == OS_AIO_SYNC
#ifdef WIN_ASYNC_IO
@@ -5011,6 +5034,10 @@ os_aio_func(
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
os_has_said_disk_full = FALSE; ret = 0; errno = 28;);
+
+ if (!ret) {
+ os_file_handle_error_cond_exit(name, "os_file_write_func", TRUE, FALSE, __FILE__, __LINE__);
+ }
}
return ret;
}
@@ -5906,18 +5933,20 @@ consecutive_loop:
ret = os_file_write(
aio_slot->name, aio_slot->file, combined_buf,
aio_slot->offset, total_len);
- } else {
- ret = os_file_read(
- aio_slot->file, combined_buf,
- aio_slot->offset, total_len,
- aio_slot->page_compression);
- }
- if (aio_slot->type == OS_FILE_WRITE) {
DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28",
os_has_said_disk_full = FALSE;
ret = 0;
errno = 28;);
+
+ if (!ret) {
+ os_file_handle_error_cond_exit(aio_slot->name, "os_file_write_func", TRUE, FALSE, __FILE__, __LINE__);
+ }
+
+ } else {
+ ret = os_file_read(
+ aio_slot->file, combined_buf,
+ aio_slot->offset, total_len, aio_slot->page_compression);
}
srv_set_io_thread_op_info(global_segment, "file i/o done");
diff --git a/storage/innobase/os/os0sync.cc b/storage/innobase/os/os0sync.cc
index 451ba5285e3..03c53848832 100644
--- a/storage/innobase/os/os0sync.cc
+++ b/storage/innobase/os/os0sync.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, 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
@@ -234,24 +234,6 @@ os_cond_broadcast(
}
/*********************************************************//**
-Wakes one thread waiting for condition variable */
-UNIV_INLINE
-void
-os_cond_signal(
-/*==========*/
- os_cond_t* cond) /*!< in: condition variable. */
-{
- ut_a(cond);
-
-#ifdef __WIN__
- ut_a(wake_condition_variable != NULL);
- wake_condition_variable(cond);
-#else
- ut_a(pthread_cond_signal(cond) == 0);
-#endif
-}
-
-/*********************************************************//**
Destroys condition variable */
UNIV_INLINE
void
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index bd5fb36af8f..cb2381df48c 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
This program is free software; you can redistribute it and/or modify it under
@@ -2811,3 +2811,45 @@ page_find_rec_max_not_deleted(
}
return(prev_rec);
}
+
+/** Issue a warning when the checksum that is stored in the page is valid,
+but different than the global setting innodb_checksum_algorithm.
+@param[in] current_algo current checksum algorithm
+@param[in] page_checksum page valid checksum
+@param[in] space_id tablespace id
+@param[in] page_no page number */
+void
+page_warn_strict_checksum(
+ srv_checksum_algorithm_t curr_algo,
+ srv_checksum_algorithm_t page_checksum,
+ ulint space_id,
+ ulint page_no)
+{
+ srv_checksum_algorithm_t curr_algo_nonstrict;
+ switch (curr_algo) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32;
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_INNODB;
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+ curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_NONE;
+ break;
+ default:
+ ut_error;
+ }
+
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "innodb_checksum_algorithm is set to \"%s\""
+ " but the page [page id: space=" ULINTPF ","
+ " page number=" ULINTPF "] contains a valid checksum \"%s\"."
+ " Accepting the page as valid. Change innodb_checksum_algorithm"
+ " to \"%s\" to silently accept such pages or rewrite all pages"
+ " so that they contain \"%s\" checksum.",
+ buf_checksum_algorithm_name(curr_algo),
+ space_id, page_no,
+ buf_checksum_algorithm_name(page_checksum),
+ buf_checksum_algorithm_name(curr_algo_nonstrict),
+ buf_checksum_algorithm_name(curr_algo_nonstrict));
+}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 677a2ba4f70..68a8bb1532f 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
This program is free software; you can redistribute it and/or modify it under
@@ -47,6 +47,8 @@ using namespace std;
#include "btr0cur.h"
#include "page0types.h"
#include "log0recv.h"
+#else
+#define page_warn_strict_checksum(A,B,C,D)
#endif /* !UNIV_INNOCHECKSUM */
#include "zlib.h"
#ifndef UNIV_HOTBACKUP
@@ -1608,7 +1610,7 @@ page_zip_fields_free(
{
if (index) {
dict_table_t* table = index->table;
- os_fast_mutex_free(&index->zip_pad.mutex);
+ dict_index_zip_pad_mutex_destroy(index);
mem_heap_free(index->heap);
dict_mem_table_free(table);
@@ -4926,6 +4928,10 @@ page_zip_verify_checksum(
stored = static_cast<ib_uint32_t>(mach_read_from_4(
static_cast<const unsigned char*>(data) + FIL_PAGE_SPACE_OR_CHKSUM));
+ ulint page_no = mach_read_from_4(static_cast<const unsigned char*> (data) + FIL_PAGE_OFFSET);
+ ulint space_id = mach_read_from_4(static_cast<const unsigned char*>
+ (data) + FIL_PAGE_SPACE_ID);
+
#if FIL_PAGE_LSN % 8
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
@@ -4951,40 +4957,113 @@ page_zip_verify_checksum(
}
#endif
+ const srv_checksum_algorithm_t curr_algo =
+ static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+
+ if (curr_algo == SRV_CHECKSUM_ALGORITHM_NONE) {
+ return(TRUE);
+ }
+
calc = static_cast<ib_uint32_t>(page_zip_calc_checksum(
- data, size, static_cast<srv_checksum_algorithm_t>(
- srv_checksum_algorithm)));
+ data, size, curr_algo));
if (stored == calc) {
return(TRUE);
}
- switch ((srv_checksum_algorithm_t) srv_checksum_algorithm) {
+ switch (curr_algo) {
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- return(stored == calc);
case SRV_CHECKSUM_ALGORITHM_CRC32:
+
if (stored == BUF_NO_CHECKSUM_MAGIC) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
+
return(TRUE);
}
- crc32 = calc;
+
innodb = static_cast<ib_uint32_t>(page_zip_calc_checksum(
data, size, SRV_CHECKSUM_ALGORITHM_INNODB));
+
+ if (stored == innodb) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_CRC32) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ }
+
+ return(TRUE);
+ }
+
break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
case SRV_CHECKSUM_ALGORITHM_INNODB:
+
if (stored == BUF_NO_CHECKSUM_MAGIC) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_NONE,
+ space_id, page_no);
+ }
+
+ return(TRUE);
+ }
+
+ crc32 = static_cast<ib_uint32_t>(page_zip_calc_checksum(
+ data, size, SRV_CHECKSUM_ALGORITHM_CRC32));
+
+ if (stored == crc32) {
+ if (curr_algo
+ == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+ }
+
return(TRUE);
}
+
+ break;
+ case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
+
crc32 = static_cast<ib_uint32_t>(page_zip_calc_checksum(
data, size, SRV_CHECKSUM_ALGORITHM_CRC32));
- innodb = calc;
+
+ if (stored == crc32) {
+ page_warn_strict_checksum(
+ curr_algo, SRV_CHECKSUM_ALGORITHM_CRC32,
+ space_id, page_no);
+
+ return(TRUE);
+ }
+
+ innodb = static_cast<ib_uint32_t>(page_zip_calc_checksum(
+ data, size, SRV_CHECKSUM_ALGORITHM_INNODB));
+
+ if (stored == innodb) {
+ page_warn_strict_checksum(
+ curr_algo,
+ SRV_CHECKSUM_ALGORITHM_INNODB,
+ space_id, page_no);
+ return(TRUE);
+ }
+
break;
case SRV_CHECKSUM_ALGORITHM_NONE:
- return(TRUE);
+ ut_error;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- return(stored == crc32 || stored == innodb);
+ return(FALSE);
}
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index fb185959d56..957a90e71b3 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, 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
@@ -380,32 +380,6 @@ que_fork_start_command(
return(thr);
}
-/****************************************************************//**
-Tests if all the query threads in the same fork have a given state.
-@return TRUE if all the query threads in the same fork were in the
-given state */
-UNIV_INLINE
-ibool
-que_fork_all_thrs_in_state(
-/*=======================*/
- que_fork_t* fork, /*!< in: query fork */
- ulint state) /*!< in: state */
-{
- que_thr_t* thr_node;
-
- for (thr_node = UT_LIST_GET_FIRST(fork->thrs);
- thr_node != NULL;
- thr_node = UT_LIST_GET_NEXT(thrs, thr_node)) {
-
- if (thr_node->state != state) {
-
- return(FALSE);
- }
- }
-
- return(TRUE);
-}
-
/**********************************************************************//**
Calls que_graph_free_recursive for statements in a statement list. */
static
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index b11a9f0d85a..621a14d27c2 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2010, 2014, 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
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 3c5beb86bc2..018bf44fb8d 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, 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
@@ -1381,6 +1381,27 @@ blob_done:
dfield_set_data(dfield, data, len);
}
+ if (len != UNIV_SQL_NULL && col->mtype == DATA_MYSQL
+ && col->len != len && !dict_table_is_comp(log->table)) {
+
+ ut_ad(col->len >= len);
+ if (dict_table_is_comp(index->table)) {
+ byte* buf = (byte*) mem_heap_alloc(heap,
+ col->len);
+ memcpy(buf, dfield->data, len);
+ memset(buf + len, 0x20, col->len - len);
+
+ dfield_set_data(dfield, buf, col->len);
+ } else {
+ /* field length mismatch should not happen
+ when rebuilding the redundant row format
+ table. */
+ ut_ad(0);
+ *error = DB_CORRUPTION;
+ return(NULL);
+ }
+ }
+
/* See if any columns were changed to NULL or NOT NULL. */
const dict_col_t* new_col
= dict_table_get_nth_col(log->table, col_no);
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index cb219e29d6e..7ebcdefdc3a 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2015, 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
@@ -235,22 +235,86 @@ row_merge_buf_free(
mem_heap_free(buf->heap);
}
-/******************************************************//**
-Insert a data tuple into a sort buffer.
-@return number of rows added, 0 if out of space */
+/** Convert the field data from compact to redundant format.
+@param[in] row_field field to copy from
+@param[out] field field to copy to
+@param[in] len length of the field data
+@param[in] zip_size compressed BLOB page size,
+ zero for uncompressed BLOBs
+@param[in,out] heap memory heap where to allocate data when
+ converting to ROW_FORMAT=REDUNDANT, or NULL
+ when not to invoke
+ row_merge_buf_redundant_convert(). */
+static
+void
+row_merge_buf_redundant_convert(
+ const dfield_t* row_field,
+ dfield_t* field,
+ ulint len,
+ ulint zip_size,
+ mem_heap_t* heap)
+{
+ ut_ad(DATA_MBMINLEN(field->type.mbminmaxlen) == 1);
+ ut_ad(DATA_MBMAXLEN(field->type.mbminmaxlen) > 1);
+
+ byte* buf = (byte*) mem_heap_alloc(heap, len);
+ ulint field_len = row_field->len;
+ ut_ad(field_len <= len);
+
+ if (row_field->ext) {
+ const byte* field_data = static_cast<byte*>(
+ dfield_get_data(row_field));
+ ulint ext_len;
+
+ ut_a(field_len >= BTR_EXTERN_FIELD_REF_SIZE);
+ ut_a(memcmp(field_data + field_len - BTR_EXTERN_FIELD_REF_SIZE,
+ field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
+
+ byte* data = btr_copy_externally_stored_field(
+ &ext_len, field_data, zip_size, field_len, heap, NULL);
+
+ ut_ad(ext_len < len);
+
+ memcpy(buf, data, ext_len);
+ field_len = ext_len;
+ } else {
+ memcpy(buf, row_field->data, field_len);
+ }
+
+ memset(buf + field_len, 0x20, len - field_len);
+
+ dfield_set_data(field, buf, len);
+}
+
+/** Insert a data tuple into a sort buffer.
+@param[in,out] buf sort buffer
+@param[in] fts_index fts index to be created
+@param[in] old_table original table
+@param[in,out] psort_info parallel sort info
+@param[in] row table row
+@param[in] ext cache of externally stored
+ column prefixes, or NULL
+@param[in,out] doc_id Doc ID if we are creating
+ FTS index
+@param[in,out] conv_heap memory heap where to allocate data when
+ converting to ROW_FORMAT=REDUNDANT, or NULL
+ when not to invoke
+ row_merge_buf_redundant_convert()
+@param[in,out] exceed_page set if the record size exceeds the page size
+ when converting to ROW_FORMAT=REDUNDANT
+@return number of rows added, 0 if out of space */
static
ulint
row_merge_buf_add(
-/*==============*/
- row_merge_buf_t* buf, /*!< in/out: sort buffer */
- dict_index_t* fts_index,/*!< in: fts index to be created */
- const dict_table_t* old_table,/*!< in: original table */
- fts_psort_t* psort_info, /*!< in: parallel sort info */
- const dtuple_t* row, /*!< in: table row */
- const row_ext_t* ext, /*!< in: cache of externally stored
- column prefixes, or NULL */
- doc_id_t* doc_id) /*!< in/out: Doc ID if we are
- creating FTS index */
+ row_merge_buf_t* buf,
+ dict_index_t* fts_index,
+ const dict_table_t* old_table,
+ fts_psort_t* psort_info,
+ const dtuple_t* row,
+ const row_ext_t* ext,
+ doc_id_t* doc_id,
+ mem_heap_t* conv_heap,
+ bool* exceed_page)
{
ulint i;
const dict_index_t* index;
@@ -400,6 +464,23 @@ row_merge_buf_add(
n_row_added = 1;
continue;
}
+
+ if (field->len != UNIV_SQL_NULL
+ && col->mtype == DATA_MYSQL
+ && col->len != field->len) {
+
+ if (conv_heap != NULL) {
+ row_merge_buf_redundant_convert(
+ row_field, field, col->len,
+ dict_table_zip_size(old_table),
+ conv_heap);
+ } else {
+ /* Field length mismatch should not
+ happen when rebuilding redundant row
+ format table. */
+ ut_ad(dict_table_is_comp(index->table));
+ }
+ }
}
len = dfield_get_len(field);
@@ -508,6 +589,14 @@ row_merge_buf_add(
of extra_size. */
data_size += (extra_size + 1) + ((extra_size + 1) >= 0x80);
+ /* Record size can exceed page size while converting to
+ redundant row format. But there is assert
+ ut_ad(size < UNIV_PAGE_SIZE) in rec_offs_data_size().
+ It may hit the assert before attempting to insert the row. */
+ if (conv_heap != NULL && data_size > UNIV_PAGE_SIZE) {
+ *exceed_page = true;
+ }
+
ut_ad(data_size < srv_sort_buf_size);
/* Reserve one byte for the end marker of row_merge_block_t. */
@@ -527,6 +616,10 @@ row_merge_buf_add(
dfield_dup(field++, buf->heap);
} while (--n_fields);
+ if (conv_heap != NULL) {
+ mem_heap_empty(conv_heap);
+ }
+
DBUG_RETURN(n_row_added);
}
@@ -1209,6 +1302,7 @@ row_merge_read_clustered_index(
os_event_t fts_parallel_sort_event = NULL;
ibool fts_pll_sort = FALSE;
ib_int64_t sig_count = 0;
+ mem_heap_t* conv_heap = NULL;
DBUG_ENTER("row_merge_read_clustered_index");
ut_ad((old_table == new_table) == !col_map);
@@ -1304,6 +1398,11 @@ row_merge_read_clustered_index(
row_heap = mem_heap_create(sizeof(mrec_buf_t));
+ if (dict_table_is_comp(old_table)
+ && !dict_table_is_comp(new_table)) {
+ conv_heap = mem_heap_create(sizeof(mrec_buf_t));
+ }
+
/* Scan the clustered index. */
for (;;) {
const rec_t* rec;
@@ -1582,16 +1681,24 @@ write_buffers:
row_merge_buf_t* buf = merge_buf[i];
merge_file_t* file = &files[i];
ulint rows_added = 0;
+ bool exceed_page = false;
if (UNIV_LIKELY
(row && (rows_added = row_merge_buf_add(
buf, fts_index, old_table,
- psort_info, row, ext, &doc_id)))) {
+ psort_info, row, ext, &doc_id,
+ conv_heap, &exceed_page)))) {
/* If we are creating FTS index,
a single row can generate more
records for tokenized word */
file->n_rec += rows_added;
+
+ if (exceed_page) {
+ err = DB_TOO_BIG_RECORD;
+ break;
+ }
+
if (doc_id > max_doc_id) {
max_doc_id = doc_id;
}
@@ -1692,12 +1799,18 @@ write_buffers:
(!(rows_added = row_merge_buf_add(
buf, fts_index, old_table,
psort_info, row, ext,
- &doc_id)))) {
+ &doc_id, conv_heap,
+ &exceed_page)))) {
/* An empty buffer should have enough
room for at least one record. */
ut_error;
}
+ if (exceed_page) {
+ err = DB_TOO_BIG_RECORD;
+ break;
+ }
+
file->n_rec += rows_added;
}
}
@@ -1722,6 +1835,10 @@ func_exit:
}
all_done:
+ if (conv_heap != NULL) {
+ mem_heap_free(conv_heap);
+ }
+
#ifdef FTS_INTERNAL_DIAG_PRINT
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Scan Table\n");
#endif
@@ -2100,6 +2217,7 @@ row_merge(
/* Copy the last blocks, if there are any. */
while (foffs0 < ihalf) {
+
if (UNIV_UNLIKELY(trx_is_interrupted(trx))) {
return(DB_INTERRUPTED);
}
@@ -2116,6 +2234,7 @@ row_merge(
ut_ad(foffs0 == ihalf);
while (foffs1 < file->offset) {
+
if (trx_is_interrupted(trx)) {
return(DB_INTERRUPTED);
}
@@ -2175,6 +2294,7 @@ row_merge_sort(
{
const ulint half = file->offset / 2;
ulint num_runs;
+ ulint cur_run = 0;
ulint* run_offset;
dberr_t error = DB_SUCCESS;
DBUG_ENTER("row_merge_sort");
@@ -2198,11 +2318,19 @@ row_merge_sort(
of file marker). Thus, it must be at least one block. */
ut_ad(file->offset > 0);
+ thd_progress_init(trx->mysql_thd, num_runs);
+
/* Merge the runs until we have one big run */
do {
+ cur_run++;
+
error = row_merge(trx, dup, file, block, tmpfd,
&num_runs, run_offset);
+ /* Report progress of merge sort to MySQL for
+ show processlist progress field */
+ thd_progress_report(trx->mysql_thd, cur_run, num_runs);
+
if (error != DB_SUCCESS) {
break;
}
@@ -2212,6 +2340,8 @@ row_merge_sort(
mem_free(run_offset);
+ thd_progress_end(trx->mysql_thd);
+
DBUG_RETURN(error);
}
@@ -3337,9 +3467,13 @@ row_merge_create_index(
for (i = 0; i < n_fields; i++) {
index_field_t* ifield = &index_def->fields[i];
+ const char * col_name = ifield->col_name ?
+ dict_table_get_col_name_for_mysql(table, ifield->col_name) :
+ dict_table_get_col_name(table, ifield->col_no);
dict_mem_index_add_field(
- index, dict_table_get_col_name(table, ifield->col_no),
+ index,
+ col_name,
ifield->prefix_len);
}
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 2717d39b4c0..6184bcddcb5 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2015, 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
@@ -610,6 +610,7 @@ handle_new_error:
case DB_DUPLICATE_KEY:
case DB_FOREIGN_DUPLICATE_KEY:
case DB_TOO_BIG_RECORD:
+ case DB_TOO_BIG_FOR_REDO:
case DB_UNDO_RECORD_TOO_BIG:
case DB_ROW_IS_REFERENCED:
case DB_NO_REFERENCED_ROW:
@@ -1324,18 +1325,14 @@ row_insert_for_mysql(
mem_analyze_corruption(prebuilt);
ut_error;
- } else if (srv_created_new_raw || srv_force_recovery) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ } else if (srv_force_recovery) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that"
- " newraw is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- return(DB_READ_ONLY);
- }
- return(DB_ERROR);
+
+ return(DB_READ_ONLY);
}
trx->op_info = "inserting";
@@ -1460,6 +1457,11 @@ error_exit:
with a latch. */
dict_table_n_rows_inc(table);
+ if (prebuilt->clust_index_was_generated) {
+ /* set row id to prebuilt */
+ ut_memcpy(prebuilt->row_id, node->row_id_buf, DATA_ROW_ID_LEN);
+ }
+
row_update_statistics_if_needed(table);
trx->op_info = "";
@@ -1721,18 +1723,14 @@ row_update_for_mysql(
ut_error;
}
- if (UNIV_UNLIKELY(srv_created_new_raw || srv_force_recovery)) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ if (UNIV_UNLIKELY(srv_force_recovery)) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
- "InnoDB: mysqld and edit my.cnf so that newraw"
- " is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: mysqld and edit my.cnf so that"
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- return(DB_READ_ONLY);
- }
- return(DB_ERROR);
+
+ return(DB_READ_ONLY);
}
DEBUG_SYNC_C("innodb_row_update_for_mysql_begin");
@@ -2231,22 +2229,6 @@ row_create_table_for_mysql(
goto err_exit;
);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-err_exit:
- dict_mem_table_free(table);
-
- if (commit) {
- trx_commit_for_mysql(trx);
- }
-
- return(DB_ERROR);
- }
-
trx->op_info = "creating table";
if (row_mysql_is_system_table(table->name)) {
@@ -2257,7 +2239,19 @@ err_exit:
"InnoDB: MySQL system tables must be"
" of the MyISAM type!\n",
table->name);
- goto err_exit;
+
+#ifndef DBUG_OFF
+err_exit:
+#endif /* !DBUG_OFF */
+ dict_mem_table_free(table);
+
+ if (commit) {
+ trx_commit_for_mysql(trx);
+ }
+
+ trx->op_info = "";
+
+ return(DB_ERROR);
}
trx_start_if_not_started_xa(trx);
@@ -3307,16 +3301,6 @@ row_truncate_table_for_mysql(
ut_ad(table);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-
- return(DB_ERROR);
- }
-
if (dict_table_is_discarded(table)) {
return(DB_TABLESPACE_DELETED);
} else if (table->ibd_file_missing) {
@@ -3438,13 +3422,11 @@ row_truncate_table_for_mysql(
goto funct_exit;
}
- if (table->space && !table->dir_path_of_temp_table) {
+ if (table->space && !DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
/* Discard and create the single-table tablespace. */
ulint space = table->space;
ulint flags = fil_space_get_flags(space);
- ut_a(!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY));
-
dict_get_and_save_data_dir_path(table, true);
if (flags != ULINT_UNDEFINED
@@ -3798,16 +3780,6 @@ row_drop_table_for_mysql(
ut_a(name != NULL);
- if (srv_created_new_raw) {
- fputs("InnoDB: A new raw disk partition was initialized:\n"
- "InnoDB: we do not allow database modifications"
- " by the user.\n"
- "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
- " is replaced with raw.\n", stderr);
-
- DBUG_RETURN(DB_ERROR);
- }
-
/* The table name is prefixed with the database name and a '/'.
Certain table names starting with 'innodb_' have their special
meaning regardless of the database name. Thus, we need to
@@ -4244,8 +4216,9 @@ row_drop_table_for_mysql(
is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY);
/* If there is a temp path then the temp flag is set.
- However, during recovery, we might have a temp flag but
- not know the temp path */
+ However, during recovery or reloading the table object
+ after eviction from data dictionary cache, we might
+ have a temp flag but not know the temp path */
ut_a(table->dir_path_of_temp_table == NULL || is_temp);
if (dict_table_is_discarded(table)
|| table->ibd_file_missing) {
@@ -4373,7 +4346,7 @@ row_drop_table_for_mysql(
case DB_OUT_OF_FILE_SPACE:
err = DB_MUST_GET_MORE_FILE_SPACE;
-
+ trx->error_state = err;
row_mysql_handle_errors(&err, trx, NULL, NULL);
/* raise error */
@@ -4813,24 +4786,22 @@ row_rename_table_for_mysql(
ibool old_is_tmp, new_is_tmp;
pars_info_t* info = NULL;
int retry;
+ bool aux_fts_rename = false;
ut_a(old_name != NULL);
ut_a(new_name != NULL);
ut_ad(trx->state == TRX_STATE_ACTIVE);
- if (srv_created_new_raw || srv_force_recovery) {
- fputs("InnoDB: A new raw disk partition was initialized or\n"
- "InnoDB: innodb_force_recovery is on: we do not allow\n"
+ if (srv_force_recovery) {
+ fputs("InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
- "InnoDB: mysqld and edit my.cnf so that newraw"
- " is replaced\n"
- "InnoDB: with raw, and innodb_force_... is removed.\n",
+ "InnoDB: mysqld and edit my.cnf so that"
+ "InnoDB: innodb_force_... is removed.\n",
stderr);
- if(srv_force_recovery) {
- err = DB_READ_ONLY;
- }
+ err = DB_READ_ONLY;
goto funct_exit;
+
} else if (row_mysql_is_system_table(new_name)) {
fprintf(stderr,
@@ -5099,34 +5070,8 @@ row_rename_table_for_mysql(
if (dict_table_has_fts_index(table)
&& !dict_tables_have_same_db(old_name, new_name)) {
err = fts_rename_aux_tables(table, new_name, trx);
-
- if (err != DB_SUCCESS && (table->space != 0)) {
- char* orig_name = table->name;
- trx_t* trx_bg = trx_allocate_for_background();
-
- /* If the first fts_rename fails, the trx would
- be rolled back and committed, we can't use it any more,
- so we have to start a new background trx here. */
- ut_a(trx_state_eq(trx, TRX_STATE_NOT_STARTED));
- trx_bg->op_info = "Revert the failing rename "
- "for fts aux tables";
- trx_bg->dict_operation_lock_mode = RW_X_LATCH;
- trx_start_for_ddl(trx_bg, TRX_DICT_OP_TABLE);
-
- /* If rename fails and table has its own tablespace,
- we need to call fts_rename_aux_tables again to
- revert the ibd file rename, which is not under the
- control of trx. Also notice the parent table name
- in cache is not changed yet. If the reverting fails,
- the ibd data may be left in the new database, which
- can be fixed only manually. */
- table->name = const_cast<char*>(new_name);
- fts_rename_aux_tables(table, old_name, trx_bg);
- table->name = orig_name;
-
- trx_bg->dict_operation_lock_mode = 0;
- trx_commit_for_mysql(trx_bg);
- trx_free_for_background(trx_bg);
+ if (err != DB_TABLE_NOT_FOUND) {
+ aux_fts_rename = true;
}
}
@@ -5239,6 +5184,37 @@ end:
}
funct_exit:
+ if (aux_fts_rename && err != DB_SUCCESS
+ && table != NULL && (table->space != 0)) {
+
+ char* orig_name = table->name;
+ trx_t* trx_bg = trx_allocate_for_background();
+
+ /* If the first fts_rename fails, the trx would
+ be rolled back and committed, we can't use it any more,
+ so we have to start a new background trx here. */
+ ut_a(trx_state_eq(trx_bg, TRX_STATE_NOT_STARTED));
+ trx_bg->op_info = "Revert the failing rename "
+ "for fts aux tables";
+ trx_bg->dict_operation_lock_mode = RW_X_LATCH;
+ trx_start_for_ddl(trx_bg, TRX_DICT_OP_TABLE);
+
+ /* If rename fails and table has its own tablespace,
+ we need to call fts_rename_aux_tables again to
+ revert the ibd file rename, which is not under the
+ control of trx. Also notice the parent table name
+ in cache is not changed yet. If the reverting fails,
+ the ibd data may be left in the new database, which
+ can be fixed only manually. */
+ table->name = const_cast<char*>(new_name);
+ fts_rename_aux_tables(table, old_name, trx_bg);
+ table->name = orig_name;
+
+ trx_bg->dict_operation_lock_mode = 0;
+ trx_commit_for_mysql(trx_bg);
+ trx_free_for_background(trx_bg);
+ }
+
if (table != NULL) {
dict_table_close(table, dict_locked, FALSE);
}
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc
index 1d67d5a9717..ecd6f47947b 100644
--- a/storage/innobase/row/row0quiesce.cc
+++ b/storage/innobase/row/row0quiesce.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2012, 2014, 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
@@ -680,7 +680,6 @@ row_quiesce_set_state(
switch (state) {
case QUIESCE_START:
- ut_a(table->quiesce == QUIESCE_NONE);
break;
case QUIESCE_COMPLETE:
diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc
index 57409243f5e..5e15dd15db2 100644
--- a/storage/innobase/srv/srv0mon.cc
+++ b/storage/innobase/srv/srv0mon.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2010, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2014, MariaDB Corporation
@@ -1003,7 +1003,8 @@ static monitor_info_t innodb_counter_info[] =
{"adaptive_hash_searches_btree", "adaptive_hash_index",
"Number of searches using B-tree on an index search",
- MONITOR_NONE,
+ static_cast<monitor_type_t>(
+ MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE},
{"adaptive_hash_pages_added", "adaptive_hash_index",
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 4f72ab3f4f2..129b33f0da9 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -2687,7 +2687,9 @@ srv_do_purge(
*n_total_purged += n_pages_purged;
- } while (!srv_purge_should_exit(n_pages_purged) && n_pages_purged > 0);
+ } while (!srv_purge_should_exit(n_pages_purged)
+ && n_pages_purged > 0
+ && purge_sys->state == PURGE_STATE_RUN);
return(rseg_history_len);
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index cdf08b4cde1..f2de5e954ad 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -138,7 +138,7 @@ static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 32 + MTFLUSH_MAX_WOR
void *mtflush_ctx=NULL;
/** Thead handles */
-static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 6 + 32];
+static os_thread_t thread_handles[SRV_MAX_N_IO_THREADS + 6 + 32 + MTFLUSH_MAX_WORKER];
static os_thread_t buf_flush_page_cleaner_thread_handle;
static os_thread_t buf_dump_thread_handle;
static os_thread_t dict_stats_thread_handle;
@@ -239,8 +239,8 @@ srv_file_check_mode(
/* Note: stat.rw_perm is only valid of files */
- if (stat.type == OS_FILE_TYPE_FILE
- || stat.type == OS_FILE_TYPE_BLOCK) {
+ if (stat.type == OS_FILE_TYPE_FILE) {
+
if (!stat.rw_perm) {
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -437,14 +437,16 @@ srv_parse_data_file_paths_and_sizes(
&& *(str + 1) == 'e'
&& *(str + 2) == 'w') {
str += 3;
+ /* Initialize new raw device only during bootstrap */
(srv_data_file_is_raw_partition)[i] = SRV_NEW_RAW;
}
if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') {
str += 3;
+ /* Initialize new raw device only during bootstrap */
if ((srv_data_file_is_raw_partition)[i] == 0) {
- (srv_data_file_is_raw_partition)[i] = SRV_OLD_RAW;
+ (srv_data_file_is_raw_partition)[i] = SRV_NEW_RAW;
}
}
@@ -897,6 +899,24 @@ open_or_create_data_files(
return(DB_ERROR);
}
+
+ const char* check_msg;
+ check_msg = fil_read_first_page(
+ files[i], FALSE, &flags, &space,
+#ifdef UNIV_LOG_ARCHIVE
+ min_arch_log_no, max_arch_log_no,
+#endif /* UNIV_LOG_ARCHIVE */
+ min_flushed_lsn, max_flushed_lsn, ULINT_UNDEFINED);
+
+ /* If first page is valid, don't overwrite DB.
+ It prevents overwriting DB when mysql_install_db
+ starts mysqld multiple times during bootstrap. */
+ if (check_msg == NULL) {
+
+ srv_created_new_raw = FALSE;
+ ret = FALSE;
+ }
+
} else if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
srv_start_raw_disk_in_use = TRUE;
@@ -3121,9 +3141,9 @@ innobase_shutdown_for_mysql(void)
ibuf_close();
log_shutdown();
- lock_sys_close();
trx_sys_file_format_close();
trx_sys_close();
+ lock_sys_close();
/* We don't create these mutexes in RO mode because we don't create
the temp files that the cover. */
diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc
index 10c201e990e..c7163695a3f 100644
--- a/storage/innobase/sync/sync0arr.cc
+++ b/storage/innobase/sync/sync0arr.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -1101,8 +1101,8 @@ sync_array_print_info_low(
os_thread_id_t r = 0;
fprintf(file,
- "OS WAIT ARRAY INFO: reservation count %ld\n",
- (long) arr->res_count);
+ "OS WAIT ARRAY INFO: reservation count " ULINTPF "\n",
+ arr->res_count);
for (i = 0; count < arr->n_reserved; ++i) {
sync_cell_t* cell;
@@ -1197,7 +1197,7 @@ sync_array_print(
}
fprintf(file,
- "OS WAIT ARRAY INFO: signal count %ld\n", (long) sg_count);
+ "OS WAIT ARRAY INFO: signal count " ULINTPF "\n", sg_count);
}
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 4ff330791a0..e77c7a9b396 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -545,6 +545,8 @@ rw_lock_x_lock_low(
const char* file_name,/*!< in: file name where lock requested */
ulint line) /*!< in: line where requested */
{
+ ibool local_recursive= lock->recursive;
+
if (rw_lock_lock_word_decr(lock, X_LOCK_DECR)) {
/* lock->recursive also tells us if the writer_thread
@@ -566,12 +568,12 @@ rw_lock_x_lock_low(
} else {
os_thread_id_t thread_id = os_thread_get_curr_id();
- if (!pass) {
- os_rmb;
- }
-
- /* Decrement failed: relock or failed lock */
- if (!pass && lock->recursive
+ /* Decrement failed: relock or failed lock
+ Note: recursive must be loaded before writer_thread see
+ comment for rw_lock_set_writer_id_and_recursion_flag().
+ To achieve this we load it before rw_lock_lock_word_decr(),
+ which implies full memory barrier in current implementation. */
+ if (!pass && local_recursive
&& os_thread_eq(lock->writer_thread, thread_id)) {
/* Relock */
if (lock->lock_word == 0) {
diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc
index fb559f26bd4..e0f132574c9 100644
--- a/storage/innobase/sync/sync0sync.cc
+++ b/storage/innobase/sync/sync0sync.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -47,6 +47,8 @@ Created 9/5/1995 Heikki Tuuri
#include "ha_prototypes.h"
#include "my_cpu.h"
+#include <vector>
+
/*
REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX
============================================
@@ -224,14 +226,8 @@ UNIV_INTERN ibool sync_order_checks_on = FALSE;
static const ulint SYNC_THREAD_N_LEVELS = 10000;
/** Array for tracking sync levels per thread. */
-struct sync_arr_t {
- ulint in_use; /*!< Number of active cells */
- ulint n_elems; /*!< Number of elements in the array */
- ulint max_elems; /*!< Maximum elements */
- ulint next_free; /*!< ULINT_UNDEFINED or index of next
- free slot */
- sync_level_t* elems; /*!< Array elements */
-};
+typedef std::vector<sync_level_t> sync_arr_t;
+
/** Mutexes or rw-locks held by a thread */
struct sync_thread_t{
@@ -299,9 +295,9 @@ mutex_create_func(
/* NOTE! The very first mutexes are not put to the mutex list */
- if ((mutex == &mutex_list_mutex)
+ if (mutex == &mutex_list_mutex
#ifdef UNIV_SYNC_DEBUG
- || (mutex == &sync_thread_mutex)
+ || mutex == &sync_thread_mutex
#endif /* UNIV_SYNC_DEBUG */
) {
@@ -844,10 +840,10 @@ sync_thread_levels_g(
{
ulint i;
- for (i = 0; i < arr->n_elems; i++) {
+ for (i = 0; i < arr->size(); i++) {
const sync_level_t* slot;
- slot = &arr->elems[i];
+ slot = (const sync_level_t*)&(arr->at(i));
if (slot->latch != NULL && slot->level <= limit) {
if (warn) {
@@ -879,10 +875,10 @@ sync_thread_levels_contain(
{
ulint i;
- for (i = 0; i < arr->n_elems; i++) {
+ for (i = 0; i < arr->size(); i++) {
const sync_level_t* slot;
- slot = &arr->elems[i];
+ slot = (const sync_level_t*)&(arr->at(i));
if (slot->latch != NULL && slot->level == level) {
@@ -926,10 +922,10 @@ sync_thread_levels_contains(
arr = thread_slot->levels;
- for (i = 0; i < arr->n_elems; i++) {
+ for (i = 0; i < arr->size(); i++) {
sync_level_t* slot;
- slot = &arr->elems[i];
+ slot = (sync_level_t*)&(arr->at(i));
if (slot->latch != NULL && slot->level == level) {
@@ -975,10 +971,10 @@ sync_thread_levels_nonempty_gen(
arr = thread_slot->levels;
- for (i = 0; i < arr->n_elems; ++i) {
+ for (i = 0; i < arr->size(); ++i) {
const sync_level_t* slot;
- slot = &arr->elems[i];
+ slot = (const sync_level_t*)&(arr->at(i));
if (slot->latch != NULL
&& (!dict_mutex_allowed
@@ -1035,10 +1031,10 @@ sync_thread_levels_nonempty_trx(
arr = thread_slot->levels;
- for (i = 0; i < arr->n_elems; ++i) {
+ for (i = 0; i < arr->size(); ++i) {
const sync_level_t* slot;
- slot = &arr->elems[i];
+ slot = (const sync_level_t*)&(arr->at(i));
if (slot->latch != NULL
&& (!has_search_latch
@@ -1069,10 +1065,9 @@ sync_thread_add_level(
SYNC_LEVEL_VARYING, nothing is done */
ibool relock) /*!< in: TRUE if re-entering an x-lock */
{
- ulint i;
- sync_level_t* slot;
sync_arr_t* array;
sync_thread_t* thread_slot;
+ sync_level_t sync_level;
if (!sync_order_checks_on) {
@@ -1097,21 +1092,11 @@ sync_thread_add_level(
thread_slot = sync_thread_level_arrays_find_slot();
if (thread_slot == NULL) {
- ulint sz;
-
- sz = sizeof(*array)
- + (sizeof(*array->elems) * SYNC_THREAD_N_LEVELS);
/* We have to allocate the level array for a new thread */
- array = static_cast<sync_arr_t*>(calloc(sz, sizeof(char)));
+ array = new sync_arr_t();
ut_a(array != NULL);
-
- array->next_free = ULINT_UNDEFINED;
- array->max_elems = SYNC_THREAD_N_LEVELS;
- array->elems = (sync_level_t*) &array[1];
-
thread_slot = sync_thread_level_arrays_find_free();
-
thread_slot->levels = array;
thread_slot->id = os_thread_get_curr_id();
}
@@ -1321,26 +1306,10 @@ sync_thread_add_level(
}
levels_ok:
- if (array->next_free == ULINT_UNDEFINED) {
- ut_a(array->n_elems < array->max_elems);
-
- i = array->n_elems++;
- } else {
- i = array->next_free;
- array->next_free = array->elems[i].level;
- }
-
- ut_a(i < array->n_elems);
- ut_a(i != ULINT_UNDEFINED);
-
- ++array->in_use;
- slot = &array->elems[i];
-
- ut_a(slot->latch == NULL);
-
- slot->latch = latch;
- slot->level = level;
+ sync_level.latch = latch;
+ sync_level.level = level;
+ array->push_back(sync_level);
mutex_exit(&sync_thread_mutex);
}
@@ -1358,7 +1327,6 @@ sync_thread_reset_level(
{
sync_arr_t* array;
sync_thread_t* thread_slot;
- ulint i;
if (!sync_order_checks_on) {
@@ -1387,36 +1355,15 @@ sync_thread_reset_level(
array = thread_slot->levels;
- for (i = 0; i < array->n_elems; i++) {
- sync_level_t* slot;
-
- slot = &array->elems[i];
+ for (std::vector<sync_level_t>::iterator it = array->begin(); it != array->end(); ++it) {
+ sync_level_t level = *it;
- if (slot->latch != latch) {
+ if (level.latch != latch) {
continue;
}
- slot->latch = NULL;
-
- /* Update the free slot list. See comment in sync_level_t
- for the level field. */
- slot->level = array->next_free;
- array->next_free = i;
-
- ut_a(array->in_use >= 1);
- --array->in_use;
-
- /* If all cells are idle then reset the free
- list. The assumption is that this will save
- time when we need to scan up to n_elems. */
-
- if (array->in_use == 0) {
- array->n_elems = 0;
- array->next_free = ULINT_UNDEFINED;
- }
-
+ array->erase(it);
mutex_exit(&sync_thread_mutex);
-
return(TRUE);
}
@@ -1502,8 +1449,7 @@ sync_thread_level_arrays_free(void)
/* If this slot was allocated then free the slot memory too. */
if (slot->levels != NULL) {
- free(slot->levels);
- slot->levels = NULL;
+ delete slot->levels;
}
}
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index a64367c4ba7..e2c3c0b949c 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -50,6 +50,9 @@ Created 3/26/1996 Heikki Tuuri
rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
+/** true if trx_rollback_or_clean_all_recovered() thread is active */
+bool trx_rollback_or_clean_is_active;
+
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
static const trx_t* trx_roll_crash_recv_trx = NULL;
@@ -492,7 +495,7 @@ trx_release_savepoint_for_mysql(
{
trx_named_savept_t* savep;
- ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
+ ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || trx_state_eq(trx, TRX_STATE_PREPARED));
ut_ad(trx->in_mysql_trx_list);
savep = trx_savepoint_find(trx, savepoint_name);
@@ -805,6 +808,8 @@ DECLARE_THREAD(trx_rollback_or_clean_all_recovered)(
trx_rollback_or_clean_recovered(TRUE);
+ trx_rollback_or_clean_is_active = false;
+
/* 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. */
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 52830a77b12..5eb3cef46c1 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -1187,8 +1187,6 @@ trx_sys_close(void)
/* Free the double write data structures. */
buf_dblwr_free();
- mutex_enter(&trx_sys->mutex);
-
ut_a(UT_LIST_GET_LEN(trx_sys->ro_trx_list) == 0);
/* Only prepared transactions may be left in the system. Free them. */
@@ -1228,8 +1226,6 @@ trx_sys_close(void)
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == 0);
ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
- mutex_exit(&trx_sys->mutex);
-
mutex_free(&trx_sys->mutex);
mem_free(trx_sys);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 405d4ef958f..f072cc6e9c4 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2015, 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
@@ -307,11 +307,10 @@ trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
{
- ut_ad(mutex_own(&trx_sys->mutex));
-
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_a(trx->magic_n == TRX_MAGIC_N);
+ lock_trx_release_locks(trx);
trx_undo_free_prepared(trx);
assert_trx_in_rw_list(trx);
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index b273b5a117e..68446cc85ef 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2014, 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
@@ -822,6 +822,8 @@ ut_strerr(
return("Temp file write failure");
case DB_FTS_TOO_MANY_WORDS_IN_PHRASE:
return("Too many words in a FTS phrase or proximity search");
+ case DB_TOO_BIG_FOR_REDO:
+ return("BLOB record length is greater than 10%% of redo log");
/* do not add default: in order to produce a warning if new code
is added to the enum but not added here */