summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/btr/btr0cur.cc65
-rw-r--r--storage/innobase/buf/buf0buf.cc7
-rw-r--r--storage/innobase/buf/buf0flu.cc34
-rw-r--r--storage/innobase/dict/dict0dict.cc29
-rw-r--r--storage/innobase/fil/fil0fil.cc26
-rw-r--r--storage/innobase/fts/fts0fts.cc650
-rw-r--r--storage/innobase/fts/fts0opt.cc18
-rw-r--r--storage/innobase/handler/ha_innodb.cc53
-rw-r--r--storage/innobase/handler/handler0alter.cc9
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc4
-rw-r--r--storage/innobase/include/btr0cur.ic4
-rw-r--r--storage/innobase/include/dict0dict.h2
-rw-r--r--storage/innobase/include/fil0fil.h4
-rw-r--r--storage/innobase/include/fts0priv.ic26
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/lock/lock0lock.cc27
-rw-r--r--storage/innobase/log/log0log.cc6
-rw-r--r--storage/innobase/os/os0thread.cc3
-rw-r--r--storage/innobase/page/page0zip.cc13
-rw-r--r--storage/innobase/row/row0mysql.cc8
-rw-r--r--storage/innobase/sync/sync0rw.cc1
21 files changed, 743 insertions, 248 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index acc3a4d1c98..2defcb89eb0 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -2365,6 +2365,38 @@ 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. */
+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;
+ dberr_t err = DB_SUCCESS;
+
+ /* Calculate the total number of bytes for blob data */
+ for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
+ total_blob_len += big_rec_vec->fields[i].len;
+ }
+
+ if (total_blob_len > redo_10p) {
+ ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
+ " length (" ULINTPF ") 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;
+ }
+
+ return(err);
+}
+
+/*************************************************************//**
Performs an update of a record on a page of a tree. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. If the
update is made on the leaf level, to avoid deadlocks, mtr must also
@@ -2579,26 +2611,14 @@ make_external:
}
if (big_rec_vec) {
- const ulint redo_10p = srv_log_file_size * UNIV_PAGE_SIZE / 10;
- ulint total_blob_len = 0;
- /* Calculate the total number of bytes for blob data */
- for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
- total_blob_len += big_rec_vec->fields[i].len;
- }
+ err = btr_check_blob_limit(big_rec_vec);
- if (total_blob_len > redo_10p) {
- ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
- " length (" ULINTPF ") is greater than"
- " 10%% of the redo log file size (" UINT64PF
- "). Please increase innodb_log_file_size.",
- total_blob_len, srv_log_file_size);
+ if (err != DB_SUCCESS) {
if (n_reserved > 0) {
fil_space_release_free_extents(
index->space, n_reserved);
}
-
- err = DB_TOO_BIG_RECORD;
goto err_exit;
}
}
@@ -4470,7 +4490,6 @@ btr_store_big_rec_extern_fields(
buf_block_t** freed_pages = NULL;
ulint n_freed_pages = 0;
dberr_t error = DB_SUCCESS;
- ulint total_blob_len = 0;
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets));
@@ -4490,21 +4509,11 @@ btr_store_big_rec_extern_fields(
rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
- const ulint redo_10p = (srv_log_file_size * UNIV_PAGE_SIZE / 10);
+ error = btr_check_blob_limit(big_rec_vec);
- /* Calculate the total number of bytes for blob data */
- for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
- total_blob_len += big_rec_vec->fields[i].len;
- }
-
- if (total_blob_len > redo_10p) {
+ if (error != DB_SUCCESS) {
ut_ad(op == BTR_STORE_INSERT);
- ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data length"
- " (" ULINTPF ") is greater than 10%% of the"
- " redo log file size (" UINT64PF "). Please"
- " increase innodb_log_file_size.",
- total_blob_len, srv_log_file_size);
- return(DB_TOO_BIG_RECORD);
+ return(error);
}
if (page_zip) {
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 9fceae0f880..f0b735546f3 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -564,9 +564,14 @@ buf_page_is_corrupted(
checksum_field2 = mach_read_from_4(
read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
+#if FIL_PAGE_LSN % 8
+#error "FIL_PAGE_LSN must be 64 bit aligned"
+#endif
+
/* declare empty pages non-corrupted */
if (checksum_field1 == 0 && checksum_field2 == 0
- && mach_read_from_4(read_buf + FIL_PAGE_LSN) == 0) {
+ && *reinterpret_cast<const ib_uint64_t*>(read_buf +
+ FIL_PAGE_LSN) == 0) {
/* make sure that the page is really empty */
for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) {
if (read_buf[i] != 0) {
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 6b219262207..f5145297b3f 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -837,39 +837,35 @@ buf_flush_init_for_writing(
case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
checksum = buf_calc_page_crc32(page);
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
break;
case SRV_CHECKSUM_ALGORITHM_INNODB:
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
checksum = (ib_uint32_t) buf_calc_page_new_checksum(page);
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
+ checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
break;
case SRV_CHECKSUM_ALGORITHM_NONE:
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
checksum = BUF_NO_CHECKSUM_MAGIC;
+ mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
break;
/* no default so the compiler will emit a warning if new enum
is added and not handled here */
}
- mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
-
- /* We overwrite the first 4 bytes of the end lsn field to store
- the old formula checksum. Since it depends also on the field
- FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the
- new formula checksum. */
-
- if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB
- || srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) {
+ /* With the InnoDB checksum, we overwrite the first 4 bytes of
+ the end lsn field to store the old formula checksum. Since it
+ depends also on the field FIL_PAGE_SPACE_OR_CHKSUM, it has to
+ be calculated after storing the new formula checksum.
- checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
-
- /* In other cases we use the value assigned from above.
- If CRC32 is used then it is faster to use that checksum
- (calculated above) instead of calculating another one.
- We can afford to store something other than
- buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
- this field because the file will not be readable by old
- versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
- }
+ In other cases we write the same value to both fields.
+ If CRC32 is used then it is faster to use that checksum
+ (calculated above) instead of calculating another one.
+ We can afford to store something other than
+ buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
+ this field because the file will not be readable by old
+ versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
checksum);
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 947476e0e02..2268a4a332f 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -39,6 +39,16 @@ UNIV_INTERN dict_index_t* dict_ind_redundant;
/** dummy index for ROW_FORMAT=COMPACT supremum and infimum records */
UNIV_INTERN dict_index_t* dict_ind_compact;
+#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
+/** Flag to control insert buffer debugging. */
+extern UNIV_INTERN uint ibuf_debug;
+#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
+
+/**********************************************************************
+Issue a warning that the row is too big. */
+void
+ib_warn_row_too_big(const dict_table_t* table);
+
#ifndef UNIV_HOTBACKUP
#include "buf0buf.h"
#include "data0type.h"
@@ -2410,11 +2420,18 @@ dict_index_add_to_cache(
new_index->n_fields = new_index->n_def;
new_index->trx_id = index->trx_id;
- if (strict && dict_index_too_big_for_tree(table, new_index)) {
+ if (dict_index_too_big_for_tree(table, new_index)) {
+
+ if (strict) {
too_big:
- dict_mem_index_free(new_index);
- dict_mem_index_free(index);
- return(DB_TOO_BIG_RECORD);
+ dict_mem_index_free(new_index);
+ dict_mem_index_free(index);
+ return(DB_TOO_BIG_RECORD);
+ } else {
+
+ ib_warn_row_too_big(table);
+
+ }
}
if (dict_index_is_univ(index)) {
@@ -5721,11 +5738,11 @@ dict_set_corrupted(
dict_index_copy_types(tuple, sys_index, 2);
- btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
+ btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr);
- if (cursor.up_match == dtuple_get_n_fields(tuple)) {
+ if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type
WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
ulint len;
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index ba0476b1772..a77893b7ab7 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1941,7 +1941,8 @@ UNIV_INTERN
ibool
fil_inc_pending_ops(
/*================*/
- ulint id) /*!< in: space id */
+ ulint id, /*!< in: space id */
+ ibool print_err) /*!< in: need to print error or not */
{
fil_space_t* space;
@@ -1950,10 +1951,12 @@ fil_inc_pending_ops(
space = fil_space_get_by_id(id);
if (space == NULL) {
- fprintf(stderr,
- "InnoDB: Error: trying to do an operation on a"
- " dropped tablespace %lu\n",
- (ulong) id);
+ if (print_err) {
+ fprintf(stderr,
+ "InnoDB: Error: trying to do an operation on a"
+ " dropped tablespace %lu\n",
+ (ulong) id);
+ }
}
if (space == NULL || space->stop_new_ops) {
@@ -4109,7 +4112,18 @@ fil_load_single_table_tablespace(
/* Build up the tablename in the standard form database/table. */
tablename = static_cast<char*>(
mem_alloc(dbname_len + filename_len + 2));
- sprintf(tablename, "%s/%s", dbname, filename);
+
+ /* When lower_case_table_names = 2 it is possible that the
+ dbname is in upper case ,but while storing it in fil_space_t
+ we must convert it into lower case */
+ sprintf(tablename, "%s" , dbname);
+ tablename[dbname_len] = '\0';
+
+ if (lower_case_file_system) {
+ dict_casedn_str(tablename);
+ }
+
+ sprintf(tablename+dbname_len,"/%s",filename);
tablename_len = strlen(tablename) - strlen(".ibd");
tablename[tablename_len] = '\0';
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ae61b77c6de..e1b9c95c26e 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -36,6 +36,7 @@ Full Text Search interface
#include "dict0priv.h"
#include "dict0stats.h"
#include "btr0pcur.h"
+#include <vector>
#include "ha_prototypes.h"
@@ -899,12 +900,14 @@ fts_drop_index(
index_cache = fts_find_index_cache(cache, index);
- if (index_cache->words) {
- fts_words_free(index_cache->words);
- rbt_free(index_cache->words);
- }
+ if (index_cache != NULL) {
+ if (index_cache->words) {
+ fts_words_free(index_cache->words);
+ rbt_free(index_cache->words);
+ }
- ib_vector_remove(cache->indexes, *(void**) index_cache);
+ ib_vector_remove(cache->indexes, *(void**) index_cache);
+ }
if (cache->get_docs) {
fts_reset_get_doc(cache);
@@ -1255,7 +1258,8 @@ fts_tokenizer_word_get(
#endif
/* If it is a stopword, do not index it */
- if (rbt_search(cache->stopword_info.cached_stopword,
+ if (cache->stopword_info.cached_stopword != NULL
+ && rbt_search(cache->stopword_info.cached_stopword,
&parent, text) == 0) {
return(NULL);
@@ -3558,6 +3562,12 @@ fts_add_doc_by_id(
rw_lock_x_lock(&table->fts->cache->lock);
+ if (table->fts->cache->stopword_info.status
+ & STOPWORD_NOT_INIT) {
+ fts_load_stopword(table, NULL, NULL,
+ NULL, TRUE, TRUE);
+ }
+
fts_cache_add_doc(
table->fts->cache,
get_doc->index_cache,
@@ -6072,8 +6082,6 @@ fts_update_hex_format_flag(
return (err);
}
-#ifdef _WIN32
-
/*********************************************************************//**
Rename an aux table to HEX format. It's called when "%016llu" is used
to format an object id in table name, which only happens in Windows. */
@@ -6170,8 +6178,8 @@ This function should make sure that either all the parent table and aux tables
are set DICT_TF2_FTS_AUX_HEX_NAME with flags2 or none of them are set */
static __attribute__((nonnull, warn_unused_result))
dberr_t
-fts_rename_aux_tables_to_hex_format(
-/*================================*/
+fts_rename_aux_tables_to_hex_format_low(
+/*====================================*/
trx_t* trx, /*!< in: transaction */
dict_table_t* parent_table, /*!< in: parent table */
ib_vector_t* tables) /*!< in: aux tables to rename. */
@@ -6295,12 +6303,14 @@ fts_rename_aux_tables_to_hex_format(
"table %s. Please revert manually.",
table->name);
fts_sql_rollback(trx_bg);
+ trx_free_for_background(trx_bg);
/* Continue to clear aux tables' flags2 */
not_rename = true;
continue;
}
fts_sql_commit(trx_bg);
+ trx_free_for_background(trx_bg);
}
DICT_TF2_FLAG_UNSET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME);
@@ -6324,7 +6334,11 @@ fts_fake_hex_to_dec(
ret = sprintf(tmp_id, UINT64PFx, id);
ut_ad(ret == 16);
+#ifdef _WIN32
ret = sscanf(tmp_id, "%016llu", &dec_id);
+#else
+ ret = sscanf(tmp_id, "%016"PRIu64, &dec_id);
+#endif /* _WIN32 */
ut_ad(ret == 1);
return dec_id;
@@ -6346,7 +6360,293 @@ fts_check_aux_table_parent_id_cmp(
return static_cast<int>(fa1->parent_id - fa2->parent_id);
}
-#endif /* _WIN32 */
+/** Mark all the fts index associated with the parent table as corrupted.
+@param[in] trx transaction
+@param[in, out] parent_table fts index associated with this parent table
+ will be marked as corrupted. */
+static
+void
+fts_parent_all_index_set_corrupt(
+ trx_t* trx,
+ dict_table_t* parent_table)
+{
+ fts_t* fts = parent_table->fts;
+
+ if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) {
+ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+ }
+
+ for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) {
+ dict_index_t* index = static_cast<dict_index_t*>(
+ ib_vector_getp_const(fts->indexes, j));
+ dict_set_corrupted(index,
+ trx, "DROP ORPHANED TABLE");
+ }
+}
+
+/** Mark the fts index which index id matches the id as corrupted.
+@param[in] trx transaction
+@param[in] id index id to search
+@param[in, out] parent_table parent table to check with all
+ the index. */
+static
+void
+fts_set_index_corrupt(
+ trx_t* trx,
+ index_id_t id,
+ dict_table_t* table)
+{
+ fts_t* fts = table->fts;
+
+ if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) {
+ trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
+ }
+
+ for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) {
+ dict_index_t* index = static_cast<dict_index_t*>(
+ ib_vector_getp_const(fts->indexes, j));
+ if (index->id == id) {
+ dict_set_corrupted(index, trx,
+ "DROP ORPHANED TABLE");
+ break;
+ }
+ }
+}
+
+/** Check the index for the aux table is corrupted.
+@param[in] aux_table auxiliary table
+@retval nonzero if index is corrupted, zero for valid index */
+static
+ulint
+fts_check_corrupt_index(
+ fts_aux_table_t* aux_table)
+{
+ dict_table_t* table;
+ dict_index_t* index;
+ table = dict_table_open_on_id(
+ aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
+
+ if (table == NULL) {
+ return(0);
+ }
+
+ for (index = UT_LIST_GET_FIRST(table->indexes);
+ index;
+ index = UT_LIST_GET_NEXT(indexes, index)) {
+ if (index->id == aux_table->index_id) {
+ ut_ad(index->type & DICT_FTS);
+ dict_table_close(table, true, false);
+ return(dict_index_is_corrupted(index));
+ }
+ }
+
+ dict_table_close(table, true, false);
+ return(0);
+}
+
+/** Check the validity of the parent table.
+@param[in] aux_table auxiliary table
+@return true if it is a valid table or false if it is not */
+static
+bool
+fts_valid_parent_table(
+ const fts_aux_table_t* aux_table)
+{
+ dict_table_t* parent_table;
+ bool valid = false;
+
+ parent_table = dict_table_open_on_id(
+ aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
+
+ if (parent_table != NULL && parent_table->fts != NULL) {
+ if (aux_table->index_id == 0) {
+ valid = true;
+ } else {
+ index_id_t id = aux_table->index_id;
+ dict_index_t* index;
+
+ /* Search for the FT index in the table's list. */
+ for (index = UT_LIST_GET_FIRST(parent_table->indexes);
+ index;
+ index = UT_LIST_GET_NEXT(indexes, index)) {
+ if (index->id == id) {
+ valid = true;
+ break;
+ }
+
+ }
+ }
+ }
+
+ if (parent_table) {
+ dict_table_close(parent_table, TRUE, FALSE);
+ }
+
+ return(valid);
+}
+
+/** Try to rename all aux tables of the specified parent table.
+@param[in] aux_tables aux_tables to be renamed
+@param[in] parent_table parent table of all aux
+ tables stored in tables. */
+static
+void
+fts_rename_aux_tables_to_hex_format(
+ ib_vector_t* aux_tables,
+ dict_table_t* parent_table)
+{
+ dberr_t err;
+ trx_t* trx_rename = trx_allocate_for_background();
+ trx_rename->op_info = "Rename aux tables to hex format";
+ trx_rename->dict_operation_lock_mode = RW_X_LATCH;
+ trx_start_for_ddl(trx_rename, TRX_DICT_OP_TABLE);
+
+ err = fts_rename_aux_tables_to_hex_format_low(trx_rename,
+ parent_table, aux_tables);
+
+ trx_rename->dict_operation_lock_mode = 0;
+
+ if (err != DB_SUCCESS) {
+
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Rollback operations on all aux tables of table %s. "
+ "All the fts index associated with the table are "
+ "marked as corrupted. Please rebuild the "
+ "index again.", parent_table->name);
+ fts_sql_rollback(trx_rename);
+
+ /* Corrupting the fts index related to parent table. */
+ trx_t* trx_corrupt;
+ trx_corrupt = trx_allocate_for_background();
+ trx_corrupt->dict_operation_lock_mode = RW_X_LATCH;
+ trx_start_for_ddl(trx_corrupt, TRX_DICT_OP_TABLE);
+ fts_parent_all_index_set_corrupt(trx_corrupt, parent_table);
+ trx_corrupt->dict_operation_lock_mode = 0;
+ fts_sql_commit(trx_corrupt);
+ trx_free_for_background(trx_corrupt);
+ } else {
+ fts_sql_commit(trx_rename);
+ }
+
+ trx_free_for_background(trx_rename);
+ ib_vector_reset(aux_tables);
+}
+
+/** Set the hex format flag for the parent table.
+@param[in, out] parent_table parent table
+@param[in] trx transaction */
+static
+void
+fts_set_parent_hex_format_flag(
+ dict_table_t* parent_table,
+ trx_t* trx)
+{
+ if (!DICT_TF2_FLAG_IS_SET(parent_table,
+ DICT_TF2_FTS_AUX_HEX_NAME)) {
+ DBUG_EXECUTE_IF("parent_table_flag_fail",
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Setting parent table %s to hex format "
+ "failed. Please try to restart the server "
+ "again, if it doesn't work, the system "
+ "tables might be corrupted.",
+ parent_table->name);
+ return;);
+
+ dberr_t err = fts_update_hex_format_flag(
+ trx, parent_table->id, true);
+
+ if (err != DB_SUCCESS) {
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Setting parent table %s to hex format "
+ "failed. Please try to restart the server "
+ "again, if it doesn't work, the system "
+ "tables might be corrupted.",
+ parent_table->name);
+ } else {
+ DICT_TF2_FLAG_SET(
+ parent_table, DICT_TF2_FTS_AUX_HEX_NAME);
+ }
+ }
+}
+
+/** Drop the obsolete auxilary table.
+@param[in] tables tables to be dropped. */
+static
+void
+fts_drop_obsolete_aux_table_from_vector(
+ ib_vector_t* tables)
+{
+ dberr_t err;
+
+ for (ulint count = 0; count < ib_vector_size(tables);
+ ++count) {
+
+ fts_aux_table_t* aux_drop_table;
+ aux_drop_table = static_cast<fts_aux_table_t*>(
+ ib_vector_get(tables, count));
+ trx_t* trx_drop = trx_allocate_for_background();
+ trx_drop->op_info = "Drop obsolete aux tables";
+ trx_drop->dict_operation_lock_mode = RW_X_LATCH;
+ trx_start_for_ddl(trx_drop, TRX_DICT_OP_TABLE);
+
+ err = row_drop_table_for_mysql(
+ aux_drop_table->name, trx_drop, false, true);
+
+ trx_drop->dict_operation_lock_mode = 0;
+
+ if (err != DB_SUCCESS) {
+ /* We don't need to worry about the
+ failure, since server would try to
+ drop it on next restart, even if
+ the table was broken. */
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Fail to drop obsolete aux table '%s', which "
+ "is harmless. will try to drop it on next "
+ "restart.", aux_drop_table->name);
+ fts_sql_rollback(trx_drop);
+ } else {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Dropped obsolete aux table '%s'.",
+ aux_drop_table->name);
+
+ fts_sql_commit(trx_drop);
+ }
+
+ trx_free_for_background(trx_drop);
+ }
+}
+
+/** Drop all the auxiliary table present in the vector.
+@param[in] trx transaction
+@param[in] tables tables to be dropped */
+static
+void
+fts_drop_aux_table_from_vector(
+ trx_t* trx,
+ ib_vector_t* tables)
+{
+ for (ulint count = 0; count < ib_vector_size(tables);
+ ++count) {
+ fts_aux_table_t* aux_drop_table;
+ aux_drop_table = static_cast<fts_aux_table_t*>(
+ ib_vector_get(tables, count));
+
+ /* Check for the validity of the parent table */
+ if (!fts_valid_parent_table(aux_drop_table)) {
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Parent table of FTS auxiliary table %s not "
+ "found.", aux_drop_table->name);
+ dberr_t err = fts_drop_table(trx, aux_drop_table->name);
+ if (err == DB_FAIL) {
+ char* path = fil_make_ibd_name(
+ aux_drop_table->name, false);
+ os_file_delete_if_exists(innodb_file_data_key,
+ path);
+ mem_free(path);
+ }
+ }
+ }
+}
/**********************************************************************//**
Check and drop all orphaned FTS auxiliary tables, those that don't have
@@ -6359,9 +6659,12 @@ fts_check_and_drop_orphaned_tables(
trx_t* trx, /*!< in: transaction */
ib_vector_t* tables) /*!< in: tables to check */
{
-#ifdef _WIN32
mem_heap_t* heap;
ib_vector_t* aux_tables_to_rename;
+ ib_vector_t* invalid_aux_tables;
+ ib_vector_t* valid_aux_tables;
+ ib_vector_t* drop_aux_tables;
+ ib_vector_t* obsolete_aux_tables;
ib_alloc_t* heap_alloc;
heap = mem_heap_create(1024);
@@ -6372,38 +6675,99 @@ fts_check_and_drop_orphaned_tables(
aux_tables_to_rename = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128);
+ /* We store all fake auxiliary table and orphaned table here. */
+ invalid_aux_tables = ib_vector_create(heap_alloc,
+ sizeof(fts_aux_table_t), 128);
+
+ /* We store all valid aux tables. We use this to filter the
+ fake auxiliary table from invalid auxiliary tables. */
+ valid_aux_tables = ib_vector_create(heap_alloc,
+ sizeof(fts_aux_table_t), 128);
+
+ /* We store all auxiliary tables to be dropped. */
+ drop_aux_tables = ib_vector_create(heap_alloc,
+ sizeof(fts_aux_table_t), 128);
+
+ /* We store all obsolete auxiliary tables to be dropped. */
+ obsolete_aux_tables = ib_vector_create(heap_alloc,
+ sizeof(fts_aux_table_t), 128);
+
/* Sort by parent_id first, in case rename will fail */
ib_vector_sort(tables, fts_check_aux_table_parent_id_cmp);
-#endif /* _WIN32 */
for (ulint i = 0; i < ib_vector_size(tables); ++i) {
dict_table_t* parent_table;
fts_aux_table_t* aux_table;
bool drop = false;
-#ifdef _WIN32
dict_table_t* table;
fts_aux_table_t* next_aux_table = NULL;
ib_id_t orig_parent_id = 0;
+ ib_id_t orig_index_id = 0;
bool rename = false;
-#endif /* _WIN32 */
aux_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, i));
-#ifdef _WIN32
table = dict_table_open_on_id(
aux_table->id, TRUE, DICT_TABLE_OP_NORMAL);
orig_parent_id = aux_table->parent_id;
+ orig_index_id = aux_table->index_id;
if (table == NULL || strcmp(table->name, aux_table->name)) {
- /* Skip these aux tables, which are common tables
- with wrong table ids */
- if (table) {
+
+ bool fake_aux = false;
+
+ if (table != NULL) {
dict_table_close(table, TRUE, FALSE);
}
- continue;
+ if (i + 1 < ib_vector_size(tables)) {
+ next_aux_table = static_cast<fts_aux_table_t*>(
+ ib_vector_get(tables, i + 1));
+ }
+
+ /* To know whether aux table is fake fts or
+ orphan fts table. */
+ for (ulint count = 0;
+ count < ib_vector_size(valid_aux_tables);
+ count++) {
+ fts_aux_table_t* valid_aux;
+ valid_aux = static_cast<fts_aux_table_t*>(
+ ib_vector_get(valid_aux_tables, count));
+ if (strcmp(valid_aux->name,
+ aux_table->name) == 0) {
+ fake_aux = true;
+ break;
+ }
+ }
+ /* All aux tables of parent table, whose id is
+ last_parent_id, have been checked, try to rename
+ them if necessary. */
+ if ((next_aux_table == NULL
+ || orig_parent_id != next_aux_table->parent_id)
+ && (!ib_vector_is_empty(aux_tables_to_rename))) {
+
+ ulint parent_id = fts_fake_hex_to_dec(
+ aux_table->parent_id);
+
+ parent_table = dict_table_open_on_id(
+ parent_id, TRUE,
+ DICT_TABLE_OP_NORMAL);
+
+ fts_rename_aux_tables_to_hex_format(
+ aux_tables_to_rename, parent_table);
+
+ dict_table_close(parent_table, TRUE,
+ FALSE);
+ }
+
+ /* If the aux table is fake aux table. Skip it. */
+ if (!fake_aux) {
+ ib_vector_push(invalid_aux_tables, aux_table);
+ }
+
+ continue;
} else if (!DICT_TF2_FLAG_IS_SET(table,
DICT_TF2_FTS_AUX_HEX_NAME)) {
@@ -6416,65 +6780,99 @@ fts_check_and_drop_orphaned_tables(
}
ut_ad(aux_table->id > aux_table->parent_id);
- rename = true;
- }
- if (table) {
- dict_table_close(table, TRUE, FALSE);
- }
-#endif /* _WIN32 */
+ /* Check whether parent table id and index id
+ are stored as decimal format. */
+ if (fts_valid_parent_table(aux_table)) {
- parent_table = dict_table_open_on_id(
- aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
+ parent_table = dict_table_open_on_id(
+ aux_table->parent_id, true,
+ DICT_TABLE_OP_NORMAL);
- if (parent_table == NULL || parent_table->fts == NULL) {
+ ut_ad(parent_table != NULL);
+ ut_ad(parent_table->fts != NULL);
- drop = true;
-
- } else if (aux_table->index_id != 0) {
- index_id_t id;
- fts_t* fts;
+ if (!DICT_TF2_FLAG_IS_SET(
+ parent_table,
+ DICT_TF2_FTS_AUX_HEX_NAME)) {
+ rename = true;
+ }
- drop = true;
- fts = parent_table->fts;
- id = aux_table->index_id;
+ dict_table_close(parent_table, TRUE, FALSE);
+ }
- /* Search for the FT index in the table's list. */
- for (ulint j = 0;
- j < ib_vector_size(fts->indexes);
- ++j) {
+ if (!rename) {
+ /* Reassign the original value of
+ aux table if it is not in decimal format */
+ aux_table->parent_id = orig_parent_id;
+ aux_table->index_id = orig_index_id;
+ }
+ }
- const dict_index_t* index;
+ if (table != NULL) {
+ dict_table_close(table, true, false);
+ }
- index = static_cast<const dict_index_t*>(
- ib_vector_getp_const(fts->indexes, j));
+ if (!rename) {
+ /* Check the validity of the parent table. */
+ if (!fts_valid_parent_table(aux_table)) {
+ drop = true;
+ }
+ }
- if (index->id == id) {
- drop = false;
- break;
- }
+ /* Filter out the fake aux table by comparing with the
+ current valid auxiliary table name . */
+ for (ulint count = 0;
+ count < ib_vector_size(invalid_aux_tables); count++) {
+ fts_aux_table_t* invalid_aux;
+ invalid_aux = static_cast<fts_aux_table_t*>(
+ ib_vector_get(invalid_aux_tables, count));
+ if (strcmp(invalid_aux->name, aux_table->name) == 0) {
+ ib_vector_remove(
+ invalid_aux_tables,
+ *reinterpret_cast<void**>(invalid_aux));
+ break;
}
}
- if (drop) {
+ ib_vector_push(valid_aux_tables, aux_table);
- ib_logf(IB_LOG_LEVEL_WARN,
- "Parent table of FTS auxiliary table %s not "
- "found.", aux_table->name);
+ /* If the index associated with aux table is corrupted,
+ skip it. */
+ if (fts_check_corrupt_index(aux_table) > 0) {
- dberr_t err = fts_drop_table(trx, aux_table->name);
+ if (i + 1 < ib_vector_size(tables)) {
+ next_aux_table = static_cast<fts_aux_table_t*>(
+ ib_vector_get(tables, i + 1));
+ }
- if (err == DB_FAIL) {
- char* path;
+ if (next_aux_table == NULL
+ || orig_parent_id != next_aux_table->parent_id) {
- path = fil_make_ibd_name(
- aux_table->name, false);
+ parent_table = dict_table_open_on_id(
+ aux_table->parent_id, TRUE,
+ DICT_TABLE_OP_NORMAL);
- os_file_delete_if_exists(innodb_file_data_key,
- path);
+ if (!ib_vector_is_empty(aux_tables_to_rename)) {
+ fts_rename_aux_tables_to_hex_format(
+ aux_tables_to_rename, parent_table);
- mem_free(path);
+ } else {
+ fts_set_parent_hex_format_flag(
+ parent_table, trx);
+ }
+
+ dict_table_close(parent_table, TRUE, FALSE);
}
+
+ continue;
+ }
+
+ parent_table = dict_table_open_on_id(
+ aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
+
+ if (drop) {
+ ib_vector_push(drop_aux_tables, aux_table);
} else {
if (FTS_IS_OBSOLETE_AUX_TABLE(aux_table->name)) {
@@ -6484,49 +6882,13 @@ fts_check_and_drop_orphaned_tables(
This could happen when we try to upgrade
from older server to later one, which doesn't
contain these obsolete tables. */
- drop = true;
-
- dberr_t err;
- trx_t* trx_drop =
- trx_allocate_for_background();
-
- trx_drop->op_info = "Drop obsolete aux tables";
- trx_drop->dict_operation_lock_mode = RW_X_LATCH;
-
- trx_start_for_ddl(trx_drop, TRX_DICT_OP_TABLE);
-
- err = row_drop_table_for_mysql(
- aux_table->name, trx_drop, false, true);
-
- trx_drop->dict_operation_lock_mode = 0;
-
- if (err != DB_SUCCESS) {
- /* We don't need to worry about the
- failure, since server would try to
- drop it on next restart, even if
- the table was broken. */
-
- ib_logf(IB_LOG_LEVEL_WARN,
- "Fail to drop obsolete aux"
- " table '%s', which is"
- " harmless. will try to drop"
- " it on next restart.",
- aux_table->name);
-
- fts_sql_rollback(trx_drop);
- } else {
- ib_logf(IB_LOG_LEVEL_INFO,
- "Dropped obsolete aux"
- " table '%s'.",
- aux_table->name);
-
- fts_sql_commit(trx_drop);
- }
-
- trx_free_for_background(trx_drop);
+ ib_vector_push(obsolete_aux_tables, aux_table);
+ continue;
}
}
-#ifdef _WIN32
+
+ /* If the aux table is in decimal format, we should
+ rename it, so push it to aux_tables_to_rename */
if (!drop && rename) {
ib_vector_push(aux_tables_to_rename, aux_table);
}
@@ -6544,38 +6906,16 @@ fts_check_and_drop_orphaned_tables(
them if necessary. We had better use a new background
trx to rename rather than the original trx, in case
any failure would cause a complete rollback. */
- dberr_t err;
- trx_t* trx_rename = trx_allocate_for_background();
- trx_rename->op_info = "Rename aux tables to "
- "hex format";
- trx_rename->dict_operation_lock_mode = RW_X_LATCH;
- trx_start_for_ddl(trx_rename, TRX_DICT_OP_TABLE);
+ ut_ad(rename);
+ ut_ad(!DICT_TF2_FLAG_IS_SET(
+ parent_table, DICT_TF2_FTS_AUX_HEX_NAME));
- err = fts_rename_aux_tables_to_hex_format(trx_rename,
- parent_table, aux_tables_to_rename);
-
- trx_rename->dict_operation_lock_mode = 0;
-
- if (err != DB_SUCCESS) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Rollback operations on all "
- "aux tables of table %s. "
- "Please check why renaming aux tables "
- "failed, and restart the server to "
- "upgrade again to "
- "get the table work.",
- parent_table->name);
-
- fts_sql_rollback(trx_rename);
- } else {
- fts_sql_commit(trx_rename);
- }
-
- trx_free_for_background(trx_rename);
- ib_vector_reset(aux_tables_to_rename);
+ fts_rename_aux_tables_to_hex_format(
+ aux_tables_to_rename,parent_table);
}
-#else /* _WIN32 */
- if (!drop) {
+
+ /* The IDs are already in correct hex format. */
+ if (!drop && !rename) {
dict_table_t* table;
table = dict_table_open_on_id(
@@ -6590,6 +6930,16 @@ fts_check_and_drop_orphaned_tables(
&& !DICT_TF2_FLAG_IS_SET(
table,
DICT_TF2_FTS_AUX_HEX_NAME)) {
+
+ DBUG_EXECUTE_IF("aux_table_flag_fail",
+ ib_logf(IB_LOG_LEVEL_WARN,
+ "Setting aux table %s to hex "
+ "format failed.", table->name);
+ fts_set_index_corrupt(
+ trx, aux_table->index_id,
+ parent_table);
+ goto table_exit;);
+
dberr_t err = fts_update_hex_format_flag(
trx, table->id, true);
@@ -6597,49 +6947,44 @@ fts_check_and_drop_orphaned_tables(
ib_logf(IB_LOG_LEVEL_WARN,
"Setting aux table %s to hex "
"format failed.", table->name);
+
+ fts_set_index_corrupt(
+ trx, aux_table->index_id,
+ parent_table);
} else {
DICT_TF2_FLAG_SET(table,
DICT_TF2_FTS_AUX_HEX_NAME);
}
}
+#ifndef DBUG_OFF
+table_exit:
+#endif /* !DBUG_OFF */
if (table != NULL) {
dict_table_close(table, TRUE, FALSE);
}
ut_ad(parent_table != NULL);
- if (!DICT_TF2_FLAG_IS_SET(parent_table,
- DICT_TF2_FTS_AUX_HEX_NAME)) {
- dberr_t err = fts_update_hex_format_flag(
- trx, parent_table->id, true);
- if (err != DB_SUCCESS) {
- ib_logf(IB_LOG_LEVEL_WARN,
- "Setting parent table %s of "
- "FTS auxiliary %s to hex "
- "format failed.",
- parent_table->name,
- aux_table->name);
- } else {
- DICT_TF2_FLAG_SET(parent_table,
- DICT_TF2_FTS_AUX_HEX_NAME);
- }
- }
+ fts_set_parent_hex_format_flag(
+ parent_table, trx);
}
-#endif /* _WIN32 */
-
- if (parent_table) {
+ if (parent_table != NULL) {
dict_table_close(parent_table, TRUE, FALSE);
}
}
-#ifdef _WIN32
+ fts_drop_aux_table_from_vector(trx, invalid_aux_tables);
+ fts_drop_aux_table_from_vector(trx, drop_aux_tables);
+ fts_sql_commit(trx);
+
+ fts_drop_obsolete_aux_table_from_vector(obsolete_aux_tables);
+
/* Free the memory allocated at the beginning */
if (heap != NULL) {
mem_heap_free(heap);
}
-#endif /* _WIN32 */
}
/**********************************************************************//**
@@ -6738,7 +7083,6 @@ fts_drop_orphaned_tables(void)
if (error == DB_SUCCESS) {
fts_check_and_drop_orphaned_tables(trx, tables);
- fts_sql_commit(trx);
break; /* Exit the loop. */
} else {
ib_vector_reset(tables);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 910a00cd521..2e2bd061d07 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -190,6 +190,8 @@ cycle for a table. */
struct fts_slot_t {
dict_table_t* table; /*!< Table to optimize */
+ table_id_t table_id; /*!< Table id */
+
fts_state_t state; /*!< State of this slot */
ulint added; /*!< Number of doc ids added since the
@@ -2575,6 +2577,8 @@ 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);
@@ -2741,6 +2745,7 @@ fts_optimize_new_table(
memset(slot, 0x0, sizeof(*slot));
slot->table = table;
+ slot->table_id = table->id;
slot->state = FTS_STATE_LOADED;
slot->interval_time = FTS_OPTIMIZE_INTERVAL_IN_SECS;
@@ -2865,7 +2870,8 @@ fts_is_sync_needed(
slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i));
- if (slot->table && slot->table->fts) {
+ if (slot->state != FTS_STATE_EMPTY && slot->table
+ && slot->table->fts) {
total_memory += slot->table->fts->cache->total_size;
}
@@ -2948,6 +2954,7 @@ fts_optimize_thread(
ib_wqueue_t* wq = (ib_wqueue_t*) arg;
ut_ad(!srv_read_only_mode);
+ my_thread_init();
heap = mem_heap_create(sizeof(dict_table_t*) * 64);
heap_alloc = ib_heap_allocator_create(heap);
@@ -3076,9 +3083,11 @@ fts_optimize_thread(
if (slot->state != FTS_STATE_EMPTY) {
dict_table_t* table = NULL;
- table = dict_table_open_on_name(
- slot->table->name, FALSE, FALSE,
- DICT_ERR_IGNORE_INDEX_ROOT);
+ /*slot->table may be freed, so we try to open
+ table by slot->table_id.*/
+ table = dict_table_open_on_id(
+ slot->table_id, FALSE,
+ DICT_TABLE_OP_NORMAL);
if (table) {
@@ -3101,6 +3110,7 @@ fts_optimize_thread(
ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
os_event_set(exit_event);
+ my_thread_end();
/* 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/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 3c52a35b2b4..173ec73e934 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2903,7 +2903,8 @@ innobase_init(
innobase_hton->flush_logs = innobase_flush_logs;
innobase_hton->show_status = innobase_show_status;
- innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS;
+ innobase_hton->flags =
+ HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches =
innobase_release_temporary_latches;
@@ -12414,6 +12415,7 @@ ha_innobase::start_stmt(
thr_lock_type lock_type)
{
trx_t* trx;
+ DBUG_ENTER("ha_innobase::start_stmt");
update_thd(thd);
@@ -12437,6 +12439,29 @@ ha_innobase::start_stmt(
prebuilt->hint_need_to_fetch_extra_cols = 0;
reset_template();
+ if (dict_table_is_temporary(prebuilt->table)
+ && prebuilt->mysql_has_locked
+ && prebuilt->select_lock_type == LOCK_NONE) {
+ dberr_t error;
+
+ switch (thd_sql_command(thd)) {
+ case SQLCOM_INSERT:
+ case SQLCOM_UPDATE:
+ case SQLCOM_DELETE:
+ init_table_handle_for_HANDLER();
+ prebuilt->select_lock_type = LOCK_X;
+ prebuilt->stored_select_lock_type = LOCK_X;
+ error = row_lock_table_for_mysql(prebuilt, NULL, 1);
+
+ if (error != DB_SUCCESS) {
+ int st = convert_error_code_to_mysql(
+ error, 0, thd);
+ DBUG_RETURN(st);
+ }
+ break;
+ }
+ }
+
if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock
@@ -12474,7 +12499,7 @@ ha_innobase::start_stmt(
++trx->will_lock;
}
- return(0);
+ DBUG_RETURN(0);
}
/******************************************************************//**
@@ -17559,3 +17584,27 @@ innobase_convert_to_system_charset(
static_cast<uint>(len), errors));
}
+/**********************************************************************
+Issue a warning that the row is too big. */
+void
+ib_warn_row_too_big(const dict_table_t* table)
+{
+ /* If prefix is true then a 768-byte prefix is stored
+ locally for BLOB fields. Refer to dict_table_get_format() */
+ const bool prefix = (dict_tf_get_format(table->flags)
+ == UNIV_FORMAT_A);
+
+ const ulint free_space = page_get_free_space_of_empty(
+ table->flags & DICT_TF_COMPACT) / 2;
+
+ THD* thd = current_thd;
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW,
+ "Row size too large (> %lu). Changing some columns to TEXT"
+ " or BLOB %smay help. In current row format, BLOB prefix of"
+ " %d bytes is stored inline.", free_space
+ , prefix ? "or using ROW_FORMAT=DYNAMIC or"
+ " ROW_FORMAT=COMPRESSED ": ""
+ , prefix ? DICT_MAX_FIXED_COL_LEN : 0);
+}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index a04b34fe027..e48d1189ccd 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -3362,9 +3362,7 @@ ha_innobase::prepare_inplace_alter_table(
ulint fts_doc_col_no = ULINT_UNDEFINED;
bool add_fts_doc_id = false;
bool add_fts_doc_id_idx = false;
-#ifdef _WIN32
bool add_fts_idx = false;
-#endif /* _WIN32 */
DBUG_ENTER("prepare_inplace_alter_table");
DBUG_ASSERT(!ha_alter_info->handler_ctx);
@@ -3509,9 +3507,7 @@ check_if_ok_to_rename:
& ~(HA_FULLTEXT
| HA_PACK_KEY
| HA_BINARY_PACK_KEY)));
-#ifdef _WIN32
add_fts_idx = true;
-#endif /* _WIN32 */
continue;
}
@@ -3522,19 +3518,16 @@ check_if_ok_to_rename:
}
}
-#ifdef _WIN32
/* We won't be allowed to add fts index to a table with
fts indexes already but without AUX_HEX_NAME set.
This means the aux tables of the table failed to
rename to hex format but new created aux tables
- shall be in hex format, which is contradictory.
- It's only for Windows. */
+ shall be in hex format, which is contradictory. */
if (!DICT_TF2_FLAG_IS_SET(indexed_table, DICT_TF2_FTS_AUX_HEX_NAME)
&& indexed_table->fts != NULL && add_fts_idx) {
my_error(ER_INNODB_FT_AUX_NOT_HEX_ID, MYF(0));
goto err_exit_no_heap;
}
-#endif /* _WIN32 */
/* Check existing index definitions for too-long column
prefixes as well, in case max_col_len shrunk. */
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 0bb898dbce5..2082c0d194b 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 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
@@ -4614,7 +4614,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace
from being dropped. */
- tablespace_being_deleted = fil_inc_pending_ops(space);
+ tablespace_being_deleted = fil_inc_pending_ops(space, true);
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space;
diff --git a/storage/innobase/include/btr0cur.ic b/storage/innobase/include/btr0cur.ic
index 080866c7465..43ee3304c0e 100644
--- a/storage/innobase/include/btr0cur.ic
+++ b/storage/innobase/include/btr0cur.ic
@@ -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
@@ -28,7 +28,7 @@ Created 10/16/1994 Heikki Tuuri
#ifdef UNIV_DEBUG
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\
-if (btr_cur_limit_optimistic_insert_debug\
+if (btr_cur_limit_optimistic_insert_debug > 1\
&& (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\
CODE;\
}
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 026187b2000..d2514ea78b6 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -85,7 +85,7 @@ dict_get_referenced_table(
mem_heap_t* heap); /*!< in: heap memory */
/*********************************************************************//**
Frees a foreign key struct. */
-UNIV_INTERN
+
void
dict_foreign_free(
/*==============*/
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 55559bdd999..5d9f96ce364 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -42,6 +42,7 @@ Created 10/25/1995 Heikki Tuuri
#include <list>
+extern my_bool lower_case_file_system;
// Forward declaration
struct trx_t;
struct fil_space_t;
@@ -590,7 +591,8 @@ UNIV_INTERN
ibool
fil_inc_pending_ops(
/*================*/
- ulint id); /*!< in: space id */
+ ulint id, /*!< in: space id */
+ ibool print_err); /*!< in: need to print error or not */
/*******************************************************************//**
Decrements the count of pending operations. */
UNIV_INTERN
diff --git a/storage/innobase/include/fts0priv.ic b/storage/innobase/include/fts0priv.ic
index 8ef877f267e..2d07c60f980 100644
--- a/storage/innobase/include/fts0priv.ic
+++ b/storage/innobase/include/fts0priv.ic
@@ -37,18 +37,38 @@ fts_write_object_id(
/* in: true for fixed hex format,
false for old ambiguous format */
{
+
#ifdef _WIN32
- /* Use this to construct old(5.6.14 and 5.7.3) ambiguous
- aux table names */
+
+ DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name",
+ return(sprintf(str, UINT64PFx, id)););
+
+ /* Use this to construct old(5.6.14 and 5.7.3) windows
+ ambiguous aux table names */
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
return(sprintf(str, "%016llu", id)););
+#else /* _WIN32 */
+
+ /* Use this to construct old(5.6.14 and 5.7.3) windows
+ ambiguous aux table names */
+ DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name",
+ return(sprintf(str, "%016"PRIu64, id)););
+
+ DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
+ return(sprintf(str, UINT64PFx, id)););
+
+#endif /* _WIN32 */
+
/* As above, but this is only for those tables failing to rename. */
if (!hex_format) {
+#ifdef _WIN32
// FIXME: Use ut_snprintf(), so does following one.
return(sprintf(str, "%016llu", id));
- }
+#else /* _WIN32 */
+ return(sprintf(str, "%016"PRIu64, id));
#endif /* _WIN32 */
+ }
return(sprintf(str, UINT64PFx, id));
}
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index cb2e6613171..acfee420352 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 21
+#define INNODB_VERSION_BUGFIX 22
/* 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 eac18a02d16..5ea187bdb3c 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -5497,6 +5497,7 @@ loop:
ulint space = lock->un_member.rec_lock.space;
ulint zip_size= fil_space_get_zip_size(space);
ulint page_no = lock->un_member.rec_lock.page_no;
+ ibool tablespace_being_deleted = FALSE;
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
@@ -5515,12 +5516,28 @@ loop:
lock_mutex_exit();
mutex_exit(&trx_sys->mutex);
- mtr_start(&mtr);
+ DEBUG_SYNC_C("innodb_monitor_before_lock_page_read");
- buf_page_get_with_no_latch(
- space, zip_size, page_no, &mtr);
+ /* Check if the space is exists or not. only when the space
+ is valid, try to get the page. */
+ tablespace_being_deleted = fil_inc_pending_ops(space, false);
- mtr_commit(&mtr);
+ if (!tablespace_being_deleted) {
+ mtr_start(&mtr);
+
+ buf_page_get_gen(space, zip_size, page_no,
+ RW_NO_LATCH, NULL,
+ BUF_GET_POSSIBLY_FREED,
+ __FILE__, __LINE__, &mtr);
+
+ mtr_commit(&mtr);
+
+ fil_decr_pending_ops(space);
+ } else {
+ fprintf(file, "RECORD LOCKS on"
+ " non-existing space %lu\n",
+ (ulong) space);
+ }
load_page_first = FALSE;
@@ -5943,7 +5960,7 @@ lock_rec_block_validate(
/* Make sure that the tablespace is not deleted while we are
trying to access the page. */
- if (!fil_inc_pending_ops(space)) {
+ if (!fil_inc_pending_ops(space, true)) {
mtr_start(&mtr);
block = buf_page_get_gen(
space, fil_space_get_zip_size(space),
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 53794a0d773..d849b1a6329 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -3407,7 +3407,11 @@ loop:
lsn = log_sys->lsn;
- if (lsn != log_sys->last_checkpoint_lsn
+ ut_ad(srv_force_recovery != SRV_FORCE_NO_LOG_REDO
+ || lsn == log_sys->last_checkpoint_lsn + LOG_BLOCK_HDR_SIZE);
+
+ if ((srv_force_recovery != SRV_FORCE_NO_LOG_REDO
+ && lsn != log_sys->last_checkpoint_lsn)
#ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)
diff --git a/storage/innobase/os/os0thread.cc b/storage/innobase/os/os0thread.cc
index c855ac2c3b9..a5b0f7de6ae 100644
--- a/storage/innobase/os/os0thread.cc
+++ b/storage/innobase/os/os0thread.cc
@@ -114,6 +114,9 @@ os_thread_create_func(
os_thread_id_t* thread_id) /*!< out: id of the created
thread, or NULL */
{
+ /* the new thread should look recent changes up here so far. */
+ os_wmb;
+
#ifdef __WIN__
os_thread_t thread;
DWORD win_thread_id;
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 85ee661a746..677a2ba4f70 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -4926,12 +4926,19 @@ 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));
+#if FIL_PAGE_LSN % 8
+#error "FIL_PAGE_LSN must be 64 bit aligned"
+#endif
+
#ifndef UNIV_INNOCHECKSUM
/* innochecksum doesn't compile with ut_d. Since we don't
need to check for empty pages when running innochecksum,
just don't include this code. */
- /* declare empty pages non-corrupted */
- if (stored == 0) {
+ /* Check if page is empty */
+ if (stored == 0
+ && *reinterpret_cast<const ib_uint64_t*>(static_cast<const char*>(
+ data)
+ + FIL_PAGE_LSN) == 0) {
/* make sure that the page is really empty */
ulint i;
for (i = 0; i < size; i++) {
@@ -4939,7 +4946,7 @@ page_zip_verify_checksum(
return(FALSE);
}
}
-
+ /* Empty page */
return(TRUE);
}
#endif
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 1138aa410cc..2717d39b4c0 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -3792,6 +3792,10 @@ row_drop_table_for_mysql(
pars_info_t* info = NULL;
mem_heap_t* heap = NULL;
+ DBUG_ENTER("row_drop_table_for_mysql");
+
+ DBUG_PRINT("row_drop_table_for_mysql", ("table: %s", name));
+
ut_a(name != NULL);
if (srv_created_new_raw) {
@@ -3801,7 +3805,7 @@ row_drop_table_for_mysql(
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr);
- return(DB_ERROR);
+ DBUG_RETURN(DB_ERROR);
}
/* The table name is prefixed with the database name and a '/'.
@@ -4429,7 +4433,7 @@ funct_exit:
srv_wake_master_thread();
- return(err);
+ DBUG_RETURN(err);
}
/*********************************************************************//**
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index 8a211d81af5..4ff330791a0 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -286,6 +286,7 @@ rw_lock_free_func(
ib_mutex_t* mutex;
#endif /* !INNODB_RW_LOCKS_USE_ATOMICS */
+ os_rmb;
ut_ad(rw_lock_validate(lock));
ut_a(lock->lock_word == X_LOCK_DECR);