diff options
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 65 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 7 | ||||
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 34 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 29 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 26 | ||||
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 650 | ||||
-rw-r--r-- | storage/innobase/fts/fts0opt.cc | 18 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 53 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 9 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.cc | 4 | ||||
-rw-r--r-- | storage/innobase/include/btr0cur.ic | 4 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 4 | ||||
-rw-r--r-- | storage/innobase/include/fts0priv.ic | 26 | ||||
-rw-r--r-- | storage/innobase/include/univ.i | 2 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 27 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 6 | ||||
-rw-r--r-- | storage/innobase/os/os0thread.cc | 3 | ||||
-rw-r--r-- | storage/innobase/page/page0zip.cc | 13 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 8 | ||||
-rw-r--r-- | storage/innobase/sync/sync0rw.cc | 1 |
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); |