summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2015-01-21 14:33:39 +0100
committerSergei Golubchik <sergii@pisem.net>2015-01-21 14:33:39 +0100
commit476a8660e6472d68ea3faa221733e0f5f7fcdd64 (patch)
tree23a2ac20dfcea78d0b223dbdd10da21a5a439366
parentff55d900fbeb1d426e7737caef6748c3f13bf4e6 (diff)
parent06ae6c6dfe6e1e3225815ab0de070db3475eefa1 (diff)
downloadmariadb-git-476a8660e6472d68ea3faa221733e0f5f7fcdd64.tar.gz
InnoDB 5.6.22
-rw-r--r--mysql-test/suite/innodb/r/strict_mode.result2
-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
22 files changed, 745 insertions, 248 deletions
diff --git a/mysql-test/suite/innodb/r/strict_mode.result b/mysql-test/suite/innodb/r/strict_mode.result
index 6d11847cb19..d6a621212c3 100644
--- a/mysql-test/suite/innodb/r/strict_mode.result
+++ b/mysql-test/suite/innodb/r/strict_mode.result
@@ -234,6 +234,8 @@ col226 text,
col227 text,
col228 text
) ENGINE=InnoDB;
+Warnings:
+Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
set innodb_strict_mode = 1;
alter table t1 engine=InnoDB;
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
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);