diff options
Diffstat (limited to 'storage/innobase')
29 files changed, 248 insertions, 179 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 8fec8a8a824..81a04701da1 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -5451,7 +5451,6 @@ btr_cur_optimistic_delete_func( mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; - ibool no_compress_needed; rec_offs_init(offsets_); ut_ad(flags == 0 || flags == BTR_CREATE_FLAG); @@ -5472,6 +5471,20 @@ btr_cur_optimistic_delete_func( rec = btr_cur_get_rec(cursor); + offsets = rec_get_offsets(rec, cursor->index, offsets, true, + ULINT_UNDEFINED, &heap); + + const ibool no_compress_needed = !rec_offs_any_extern(offsets) + && btr_cur_can_delete_without_compress( + cursor, rec_offs_size(offsets), mtr); + + if (!no_compress_needed) { + /* prefetch siblings of the leaf for the pessimistic + operation. */ + btr_cur_prefetch_siblings(block); + goto func_exit; + } + if (UNIV_UNLIKELY(block->page.id().page_no() == cursor->index->page && page_get_n_recs(block->frame) == 1 + (cursor->index->is_instant() @@ -5509,19 +5522,11 @@ btr_cur_optimistic_delete_func( } page_cur_set_after_last(block, btr_cur_get_page_cur(cursor)); - return true; + goto func_exit; } } - offsets = rec_get_offsets(rec, cursor->index, offsets, true, - ULINT_UNDEFINED, &heap); - - no_compress_needed = !rec_offs_any_extern(offsets) - && btr_cur_can_delete_without_compress( - cursor, rec_offs_size(offsets), mtr); - - if (no_compress_needed) { - + { page_t* page = buf_block_get_frame(block); page_zip_des_t* page_zip= buf_block_get_page_zip(block); @@ -5581,10 +5586,6 @@ btr_cur_optimistic_delete_func( ibuf_update_free_bits_low(block, max_ins, mtr); } } - } else { - /* prefetch siblings of the leaf for the pessimistic - operation. */ - btr_cur_prefetch_siblings(block); } func_exit: diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 238551783db..68d946aa79d 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1981,8 +1981,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) n_bytes, index->id); } - btr_search_sys_t::partition* const part - = btr_search_sys.get_part(*index); + /* We must not look up "part" before acquiring ahi_latch. */ + btr_search_sys_t::partition* part= nullptr; bool locked = false; if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, *index)) { @@ -1999,6 +1999,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) goto function_exit; } + part = btr_search_sys.get_part(*index); ha_insert_for_fold(&part->table, part->heap, ins_fold, block, ins_rec); MONITOR_INC(MONITOR_ADAPTIVE_HASH_ROW_ADDED); @@ -2016,6 +2017,8 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch) if (!btr_search_enabled || !block->index) { goto function_exit; } + + part = btr_search_sys.get_part(*index); } if (!left_side) { @@ -2039,6 +2042,8 @@ check_next_rec: if (!btr_search_enabled || !block->index) { goto function_exit; } + + part = btr_search_sys.get_part(*index); } ha_insert_for_fold(&part->table, part->heap, @@ -2057,6 +2062,8 @@ check_next_rec: if (!btr_search_enabled || !block->index) { goto function_exit; } + + part = btr_search_sys.get_part(*index); } if (!left_side) { diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index b8ed7bb3f36..f822adc3389 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -319,7 +319,7 @@ static buf_buddy_free_t* buf_buddy_alloc_zip(ulint i) if (buf) { buf_buddy_free_t* buddy = reinterpret_cast<buf_buddy_free_t*>( - buf->stamp.bytes + reinterpret_cast<byte*>(buf) + (BUF_BUDDY_LOW << i)); ut_ad(!buf_pool.contains_zip(buddy)); buf_buddy_add_to_free(buddy, i); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index d9338af1327..52b77fd93a5 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2353,7 +2353,6 @@ dict_index_add_col( if (col->is_virtual()) { dict_v_col_t* v_col = reinterpret_cast<dict_v_col_t*>(col); /* Register the index with the virtual column index list */ - v_col->n_v_indexes++; v_col->v_indexes.push_front(dict_v_idx_t(index, index->n_def)); col_name = dict_table_get_v_col_name_mysql( table, dict_col_get_no(col)); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 5b79406fb18..c27ea57e68d 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -440,7 +440,6 @@ dict_mem_table_add_v_col( /* Initialize the index list for virtual columns */ ut_ad(v_col->v_indexes.empty()); - v_col->n_v_indexes = 0; return(v_col); } @@ -1211,6 +1210,24 @@ operator<< (std::ostream& out, const dict_foreign_set& fk_set) return(out); } +/** Check whether fulltext index gets affected by foreign +key constraint. */ +bool dict_foreign_t::affects_fulltext() const +{ + if (foreign_table == referenced_table || !foreign_table->fts) + return false; + + for (ulint i= 0; i < n_fields; i++) + { + const dict_col_t *col= dict_index_get_nth_col(foreign_index, i); + if (dict_table_is_fts_column(foreign_table->fts->indexes, col->ind, + col->is_virtual()) != ULINT_UNDEFINED) + return true; + } + + return false; +} + /** Reconstruct the clustered index fields. */ inline void dict_index_t::reconstruct_fields() { diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 56476edbfa0..021f2f15e3b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -412,6 +412,14 @@ static bool fil_node_open_file(fil_node_t* node) const bool first_time_open = node->size == 0; + bool o_direct_possible = !FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags); + if (const ulint ssize = FSP_FLAGS_GET_ZIP_SSIZE(space->flags)) { + compile_time_assert(((UNIV_ZIP_SIZE_MIN >> 1) << 3) == 4096); + if (ssize < 3) { + o_direct_possible = false; + } + } + if (first_time_open || (space->purpose == FIL_TYPE_TABLESPACE && node == UT_LIST_GET_FIRST(space->chain) @@ -429,7 +437,12 @@ retry: node->is_raw_disk ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, - OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); + OS_FILE_AIO, + o_direct_possible + ? OS_DATA_FILE + : OS_DATA_FILE_NO_O_DIRECT, + read_only_mode, + &success); if (!success) { /* The following call prints an error message */ @@ -462,7 +475,12 @@ fail: node->is_raw_disk ? OS_FILE_OPEN_RAW | OS_FILE_ON_ERROR_NO_EXIT : OS_FILE_OPEN | OS_FILE_ON_ERROR_NO_EXIT, - OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); + OS_FILE_AIO, + o_direct_possible + ? OS_DATA_FILE + : OS_DATA_FILE_NO_O_DIRECT, + read_only_mode, + &success); } ut_a(success); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 552832200e7..a5945fea791 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -5266,7 +5266,6 @@ fts_t::fts_t( mem_heap_t* heap) : added_synced(0), dict_locked(0), - bg_threads(0), add_wq(NULL), cache(NULL), doc_col(ULINT_UNDEFINED), in_queue(false), sync_message(false), @@ -5274,8 +5273,6 @@ fts_t::fts_t( { ut_a(table->fts == NULL); - mutex_create(LATCH_ID_FTS_BG_THREADS, &bg_threads_mutex); - ib_alloc_t* heap_alloc = ib_heap_allocator_create(fts_heap); indexes = ib_vector_create(heap_alloc, sizeof(dict_index_t*), 4); @@ -5286,8 +5283,6 @@ fts_t::fts_t( /** fts_t destructor. */ fts_t::~fts_t() { - mutex_free(&bg_threads_mutex); - ut_ad(add_wq == NULL); if (cache != NULL) { diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 01c35ba280c..20ba44a8d73 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -2590,6 +2590,11 @@ fts_optimize_remove_table( if (fts_opt_start_shutdown) { ib::info() << "Try to remove table " << table->name << " after FTS optimize thread exiting."; + /* If the table can't be removed then wait till + fts optimize thread shuts down */ + while (fts_optimize_wq) { + os_thread_sleep(10000); + } return; } diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 4baba419ff7..dd74aad4de7 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2020, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -144,6 +144,8 @@ struct fts_query_t { ib_rbt_t* wildcard_words; /*!< words with wildcard */ bool multi_exist; /*!< multiple FTS_EXIST oper */ + byte visiting_sub_exp; /*!< count of nested + fts_ast_visit_sub_exp() */ st_mysql_ftparser* parser; /*!< fts plugin parser */ }; @@ -2964,6 +2966,8 @@ fts_query_get_token( return(new_ptr); } +static dberr_t fts_ast_visit_sub_exp(fts_ast_node_t*, fts_ast_callback, void*); + /*****************************************************************//** Visit every node of the AST. */ static @@ -3088,6 +3092,14 @@ fts_ast_visit_sub_exp( ut_a(node->type == FTS_AST_SUBEXP_LIST); + /* To avoid stack overflow, we limit the mutual recursion + depth between fts_ast_visit(), fts_query_visitor() and + fts_ast_visit_sub_exp(). */ + if (query->visiting_sub_exp++ > 31) { + query->error = DB_OUT_OF_MEMORY; + DBUG_RETURN(query->error); + } + cur_oper = query->oper; /* Save current result set */ @@ -3110,6 +3122,7 @@ fts_ast_visit_sub_exp( /* Reinstate parent node state */ query->multi_exist = multi_exist; query->oper = cur_oper; + query->visiting_sub_exp--; /* Merge the sub-expression result with the parent result set. */ subexpr_doc_ids = query->doc_ids; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 546957f8800..d6f28192893 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -514,7 +514,6 @@ static PSI_mutex_info all_innodb_mutexes[] = { PSI_KEY(recalc_pool_mutex), PSI_KEY(fil_system_mutex), PSI_KEY(flush_list_mutex), - PSI_KEY(fts_bg_threads_mutex), PSI_KEY(fts_delete_mutex), PSI_KEY(fts_doc_id_mutex), PSI_KEY(log_flush_order_mutex), @@ -2275,6 +2274,12 @@ innobase_trx_init( DBUG_ENTER("innobase_trx_init"); DBUG_ASSERT(thd == trx->mysql_thd); + /* Ensure that thd_lock_wait_timeout(), which may be called + while holding lock_sys.mutex, by lock_rec_enqueue_waiting(), + will not end up acquiring LOCK_global_system_variables in + intern_sys_var_ptr(). */ + THDVAR(thd, lock_wait_timeout); + trx->check_foreigns = !thd_test_options( thd, OPTION_NO_FOREIGN_KEY_CHECKS); @@ -3407,12 +3412,30 @@ static int innodb_init_params() DBUG_RETURN(HA_ERR_INITIALIZATION); } + if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS) { + ib::warn() << "The parameter innodb_lock_schedule_algorithm" + " is deprecated, and the setting" + " innodb_lock_schedule_algorithm=vats" + " may cause corruption. The parameter may be removed" + " in future releases."; + #ifdef WITH_WSREP - /* Currently, Galera does not support VATS lock schedule algorithm. */ - if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS - && global_system_variables.wsrep_on) { - ib::info() << "For Galera, using innodb_lock_schedule_algorithm=fcfs"; - innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS; + /* Currently, Galera does not support VATS lock schedule algorithm. */ + if (global_system_variables.wsrep_on) { + ib::info() << "For Galera, using innodb_lock_schedule_algorithm=fcfs"; + innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS; + } +#endif /* WITH_WSREP */ + } + +#ifdef WITH_WSREP + /* Print deprecation info if xtrabackup is used for SST method */ + if (global_system_variables.wsrep_on + && wsrep_sst_method + && (!strcmp(wsrep_sst_method, "xtrabackup") + || !strcmp(wsrep_sst_method, "xtrabackup-v2"))) { + ib::info() << "Galera SST method xtrabackup is deprecated and the " + " support for it may be removed in future releases."; } #endif /* WITH_WSREP */ @@ -15961,8 +15984,7 @@ struct ShowStatus { /** Collect the latch metrics. Ignore entries where the spins and waits are zero. @param[in] count The latch metrics */ - void operator()(Count* count) - UNIV_NOTHROW + void operator()(Count* count) const UNIV_NOTHROW { if (count->m_spins > 0 || count->m_waits > 0) { @@ -15990,13 +16012,8 @@ struct ShowStatus { bool operator()(latch_meta_t& latch_meta) UNIV_NOTHROW { - latch_meta_t::CounterType* counter; - - counter = latch_meta.get_counter(); - - GetCount get_count(latch_meta.get_name(), &m_values); - - counter->iterate(get_count); + latch_meta.get_counter()->iterate( + GetCount(latch_meta.get_name(), &m_values)); return(true); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index d5486567e44..9343ca7fe45 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -553,8 +553,10 @@ inline bool dict_table_t::instant_column(const dict_table_t& table, mem_heap_dup(heap, table.v_col_names, ulint(end - table.v_col_names))); v_cols = static_cast<dict_v_col_t*>( - mem_heap_dup(heap, table.v_cols, - table.n_v_cols * sizeof *v_cols)); + mem_heap_alloc(heap, table.n_v_cols * sizeof(*v_cols))); + for (ulint i = table.n_v_cols; i--; ) { + new (&v_cols[i]) dict_v_col_t(table.v_cols[i]); + } } else { ut_ad(table.n_v_cols == 0); v_col_names = NULL; @@ -570,7 +572,6 @@ inline bool dict_table_t::instant_column(const dict_table_t& table, for (unsigned i = 0; i < n_v_def; i++) { dict_v_col_t& v = v_cols[i]; DBUG_ASSERT(v.v_indexes.empty()); - v.n_v_indexes = 0; v.base_col = static_cast<dict_col_t**>( mem_heap_dup(heap, v.base_col, v.num_base * sizeof *v.base_col)); @@ -680,7 +681,6 @@ dup_dropped: <dict_v_col_t*>(f.col); v_col->v_indexes.push_front( dict_v_idx_t(index, i)); - v_col->n_v_indexes++; } } } @@ -4963,7 +4963,6 @@ prepare_inplace_add_virtual( - ctx->num_to_drop_vcol + j) & dict_index_t::MAX_N_FIELDS; - ctx->add_vcol[j].n_v_indexes = 0; /* MDEV-17468: Do this on ctx->instant_table later */ innodb_base_col_setup(ctx->old_table, field, &ctx->add_vcol[j]); j++; @@ -10805,11 +10804,11 @@ ha_innobase::commit_inplace_alter_table( /* Exclusively lock the table, to ensure that no other transaction is holding locks on the table while we - change the table definition. The meta-data lock (MDL) + change the table definition. The MySQL meta-data lock should normally guarantee that no conflicting locks exist. However, FOREIGN KEY constraints checks and any transactions collected during crash recovery could be - holding InnoDB locks only, not MDL. */ + holding InnoDB locks only, not MySQL locks. */ dberr_t error = row_merge_lock_table( m_prebuilt->trx, ctx->old_table, LOCK_X); @@ -11163,7 +11162,7 @@ foreign_fail: } dict_sys.remove(m_prebuilt->table); m_prebuilt->table = dict_table_open_on_name( - tb_name, TRUE, TRUE, DICT_ERR_IGNORE_NONE); + tb_name, TRUE, TRUE, DICT_ERR_IGNORE_FK_NOKEY); /* Drop outdated table stats. */ char errstr[1024]; diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 0c42c5ffe6f..1ae52dfbf5d 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -766,9 +766,6 @@ struct dict_v_col_t{ /** column pos in table */ unsigned v_pos:10; - /** number of indexes */ - unsigned n_v_indexes:12; - /** Virtual index list, and column position in the index */ std::forward_list<dict_v_idx_t, ut_allocator<dict_v_idx_t> > v_indexes; @@ -777,21 +774,17 @@ struct dict_v_col_t{ @param index index to be detached from */ void detach(const dict_index_t &index) { - if (!n_v_indexes) return; + if (v_indexes.empty()) return; auto i= v_indexes.before_begin(); - ut_d(unsigned n= 0); do { auto prev = i++; if (i == v_indexes.end()) { - ut_ad(n == n_v_indexes); return; } - ut_ad(++n <= n_v_indexes); if (i->index == &index) { v_indexes.erase_after(prev); - n_v_indexes--; return; } } @@ -1450,6 +1443,10 @@ struct dict_foreign_t{ dict_vcol_set* v_cols; /*!< set of virtual columns affected by foreign key constraint. */ + + /** Check whether the fulltext index gets affected by + foreign key constraint */ + bool affects_fulltext() const; }; std::ostream& diff --git a/storage/innobase/include/fts0ast.h b/storage/innobase/include/fts0ast.h index 3dca92235c7..15bf30bc5d5 100644 --- a/storage/innobase/include/fts0ast.h +++ b/storage/innobase/include/fts0ast.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h index 5c35e5dac4f..5e0381ccd56 100644 --- a/storage/innobase/include/fts0fts.h +++ b/storage/innobase/include/fts0fts.h @@ -316,19 +316,11 @@ public: /** fts_t destructor. */ ~fts_t(); - /** Mutex protecting bg_threads* and fts_add_wq. */ - ib_mutex_t bg_threads_mutex; - - /** Whether the ADDED table record sync-ed after - crash recovery; protected by bg_threads_mutex */ + /** Whether the ADDED table record sync-ed after crash recovery */ unsigned added_synced:1; - /** Whether the table holds dict_sys.mutex; - protected by bg_threads_mutex */ + /** Whether the table holds dict_sys.mutex */ unsigned dict_locked:1; - /** Number of background threads accessing this table. */ - ulint bg_threads; - /** Work queue for scheduling jobs for the FTS 'Add' thread, or NULL if the thread has not yet been created. Each work item is a fts_trx_doc_ids_t*. */ diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 4be5e5341ba..def091c9771 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -160,6 +160,7 @@ static const ulint OS_FILE_NORMAL = 62; static const ulint OS_DATA_FILE = 100; static const ulint OS_LOG_FILE = 101; static const ulint OS_DATA_TEMP_FILE = 102; +static const ulint OS_DATA_FILE_NO_O_DIRECT = 103; /* @} */ /** Error codes from os_file_get_last_error @{ */ diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index 651fcb1aa36..af282b378ca 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -35,9 +35,6 @@ Created 5/27/1996 Heikki Tuuri #include "row0types.h" #include "pars0types.h" -/** Mutex protecting the query threads. */ -extern ib_mutex_t que_thr_mutex; - /***********************************************************************//** Creates a query graph fork node. @return own: fork node */ diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 72f2d8ffb74..be8ad78de82 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -52,7 +52,6 @@ extern mysql_pfs_key_t dict_foreign_err_mutex_key; extern mysql_pfs_key_t dict_sys_mutex_key; extern mysql_pfs_key_t fil_system_mutex_key; extern mysql_pfs_key_t flush_list_mutex_key; -extern mysql_pfs_key_t fts_bg_threads_mutex_key; extern mysql_pfs_key_t fts_delete_mutex_key; extern mysql_pfs_key_t fts_doc_id_mutex_key; extern mysql_pfs_key_t fts_pll_tokenize_mutex_key; diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index a6d0bd8a86c..f0168bd1c27 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -197,14 +197,12 @@ enum latch_level_t { SYNC_FTS_TOKENIZE, SYNC_FTS_OPTIMIZE, - SYNC_FTS_BG_THREADS, SYNC_FTS_CACHE_INIT, SYNC_RECV, SYNC_LOG_FLUSH_ORDER, SYNC_LOG, SYNC_PURGE_QUEUE, SYNC_TRX_SYS_HEADER, - SYNC_REC_LOCK, SYNC_TRX, SYNC_RW_TRX_HASH_ELEMENT, SYNC_READ_VIEW, @@ -267,7 +265,6 @@ enum latch_id_t { LATCH_ID_DICT_FOREIGN_ERR, LATCH_ID_DICT_SYS, LATCH_ID_FIL_SYSTEM, - LATCH_ID_FTS_BG_THREADS, LATCH_ID_FTS_DELETE, LATCH_ID_FTS_DOC_ID, LATCH_ID_FTS_PLL_TOKENIZE, @@ -600,10 +597,10 @@ public: } /** Iterate over the counters */ - template <typename Callback> - void iterate(Callback& callback) const - UNIV_NOTHROW + template<typename C> void iterate(const C& callback) UNIV_NOTHROW { + m_mutex.enter(); + Counters::const_iterator end = m_counters.end(); for (Counters::const_iterator it = m_counters.begin(); @@ -612,6 +609,8 @@ public: callback(*it); } + + m_mutex.exit(); } /** Disable the monitoring */ diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index 04ec10cc379..294304e672a 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -131,16 +131,10 @@ public: /* Some of the slots will be null in non-debug mode */ - if (*it == NULL) { - continue; - } - - latch_meta_t* latch_meta = *it; - - bool ret = callback(*latch_meta); - - if (!ret) { - return(ret); + if (latch_meta_t* l= *it) { + if (!callback(*l)) { + return false; + } } } diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index df206af34c7..71077e3f9fb 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2082,12 +2082,12 @@ static void lock_grant_and_move_on_page(ulint rec_fold, const page_id_t id) lock = previous->hash; } - ut_ad(!lock->trx->is_wsrep()); ut_ad(previous->hash == lock || previous == lock); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ while (lock) { /* If the lock is a wait lock on this page, and it does not need to wait. */ + ut_ad(!lock->trx->is_wsrep()); if (lock_get_wait(lock) && lock->un_member.rec_lock.page_id == id && !lock_rec_has_to_wait_in_queue(lock)) { @@ -3964,11 +3964,10 @@ lock_grant_and_move_on_rec( } lock = previous->hash; } - ut_ad(!lock->trx->is_wsrep()); /* Grant locks if there are no conflicting locks ahead. Move granted locks to the head of the list. */ - for (;lock != NULL;) { - + while (lock) { + ut_ad(!lock->trx->is_wsrep()); /* If the lock is a wait lock on this page, and it does not need to wait. */ if (lock->un_member.rec_lock.page_id == page_id && lock_rec_get_nth_bit(lock, heap_no) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 7e24ff7ab5e..bfe18fd2519 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1384,7 +1384,8 @@ os_file_create_func( ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE - || type == OS_DATA_TEMP_FILE); + || type == OS_DATA_TEMP_FILE + || type == OS_DATA_FILE_NO_O_DIRECT); ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL); @@ -1430,7 +1431,8 @@ os_file_create_func( /* We disable OS caching (O_DIRECT) only on data files */ if (!read_only && *success - && (type != OS_LOG_FILE && type != OS_DATA_TEMP_FILE) + && type != OS_LOG_FILE && type != OS_DATA_TEMP_FILE + && type != OS_DATA_FILE_NO_O_DIRECT && (srv_file_flush_method == SRV_O_DIRECT || srv_file_flush_method == SRV_O_DIRECT_NO_FSYNC)) { diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 649051da305..5e41d037b6c 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -460,7 +460,7 @@ row_ins_cascade_calc_update_vec( n_fields_updated = 0; - bool affects_fulltext = false; + bool affects_fulltext = foreign->affects_fulltext(); if (table->fts) { doc_id_pos = dict_table_get_nth_col_pos( @@ -583,17 +583,6 @@ row_ins_cascade_calc_update_vec( padded_data, min_size); } - /* Check whether the current column has - FTS index on it */ - if (table->fts - && dict_table_is_fts_column( - table->fts->indexes, - dict_col_get_no(col), - col->is_virtual()) - != ULINT_UNDEFINED) { - affects_fulltext = true; - } - /* If Doc ID is updated, check whether the Doc ID is valid */ if (table->fts @@ -1223,8 +1212,6 @@ row_ins_foreign_check_on_constraint( MEM_UNDEFINED(update->fields, update->n_fields * sizeof *update->fields); - bool affects_fulltext = false; - for (ulint i = 0; i < foreign->n_fields; i++) { upd_field_t* ufield = &update->fields[i]; ulint col_no = dict_index_get_nth_col_no( @@ -1241,19 +1228,9 @@ row_ins_foreign_check_on_constraint( ufield->orig_len = 0; ufield->exp = NULL; dfield_set_null(&ufield->new_val); - - if (!affects_fulltext - && table->fts && dict_table_is_fts_column( - table->fts->indexes, - dict_index_get_nth_col(index, i)->ind, - dict_index_get_nth_col(index, i) - ->is_virtual()) - != ULINT_UNDEFINED) { - affects_fulltext = true; - } } - if (affects_fulltext) { + if (foreign->affects_fulltext()) { fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); } @@ -1267,24 +1244,10 @@ row_ins_foreign_check_on_constraint( goto nonstandard_exit_func; } } - } else if (table->fts && cascade->is_delete == PLAIN_DELETE) { + } else if (table->fts && cascade->is_delete == PLAIN_DELETE + && foreign->affects_fulltext()) { /* DICT_FOREIGN_ON_DELETE_CASCADE case */ - bool affects_fulltext = false; - - for (ulint i = 0; i < foreign->n_fields; i++) { - if (dict_table_is_fts_column( - table->fts->indexes, - dict_index_get_nth_col(index, i)->ind, - dict_index_get_nth_col(index, i)->is_virtual()) - != ULINT_UNDEFINED) { - affects_fulltext = true; - break; - } - } - - if (affects_fulltext) { - fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); - } + fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); } if (!node->is_delete diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 401a655517f..d7a0490db3d 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -3906,7 +3906,7 @@ exhausted: /*********************************************************************//** Check a pushed-down index condition. -@return CHECK_NEG, CHECK_POS, or CHECK_OUT_OF_RANGE */ +@return CHECK_ABORTED_BY_USER, CHECK_NEG, CHECK_POS, or CHECK_OUT_OF_RANGE */ static check_result_t row_search_idx_cond_check( @@ -3992,7 +3992,7 @@ row_search_idx_cond_check( case CHECK_POS: break; default: - ut_error; + return(result); } } /* Convert the remaining fields to MySQL format. @@ -4453,15 +4453,21 @@ early_not_found: switch (row_search_idx_cond_check( buf, prebuilt, rec, offsets)) { + case CHECK_ABORTED_BY_USER: + goto aborted; case CHECK_NEG: case CHECK_OUT_OF_RANGE: - case CHECK_ABORTED_BY_USER: case CHECK_ERROR: err = DB_RECORD_NOT_FOUND; goto shortcut_done; case CHECK_POS: goto shortcut_done; } + + ut_ad("incorrect code" == 0); +aborted: + err = DB_INTERRUPTED; + goto shortcut_done; } if (!row_sel_store_mysql_rec( @@ -4495,6 +4501,9 @@ early_not_found: trx->op_info = ""; ut_ad(!sync_check_iterate(sync_check())); ut_ad(!did_semi_consistent_read); + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } DBUG_RETURN(err); case SEL_RETRY: @@ -5191,9 +5200,11 @@ no_gap_lock: buf, prebuilt, rec, offsets)) { case CHECK_NEG: goto next_rec; - case CHECK_OUT_OF_RANGE: case CHECK_ABORTED_BY_USER: - case CHECK_ERROR: + err = DB_INTERRUPTED; + goto idx_cond_failed; + case CHECK_OUT_OF_RANGE: + case CHECK_ERROR: err = DB_RECORD_NOT_FOUND; goto idx_cond_failed; case CHECK_POS: @@ -5251,8 +5262,10 @@ locks_ok_del_marked: row_unlock_for_mysql(prebuilt, TRUE); } goto next_rec; - case CHECK_OUT_OF_RANGE: case CHECK_ABORTED_BY_USER: + err = DB_INTERRUPTED; + goto idx_cond_failed; + case CHECK_OUT_OF_RANGE: case CHECK_ERROR: err = DB_RECORD_NOT_FOUND; goto idx_cond_failed; @@ -5752,7 +5765,7 @@ normal_return: func_exit: trx->op_info = ""; - if (heap != NULL) { + if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc index 68856d47b5e..987c5b60f21 100644 --- a/storage/innobase/row/row0uins.cc +++ b/storage/innobase/row/row0uins.cc @@ -88,7 +88,8 @@ row_undo_ins_remove_clust_rec( online = dict_index_is_online_ddl(index); if (online) { ut_ad(node->rec_type == TRX_UNDO_INSERT_REC); - ut_ad(!node->trx->dict_operation_lock_mode); + ut_ad(node->trx->dict_operation_lock_mode + != RW_X_LATCH); ut_ad(node->table->id != DICT_INDEXES_ID); ut_ad(node->table->id != DICT_COLUMNS_ID); mtr_s_lock_index(index, &mtr); @@ -529,9 +530,6 @@ row_undo_ins( return DB_SUCCESS; } - ut_ad(node->table->is_temporary() - || lock_table_has_locks(node->table)); - /* Iterate over all the indexes and undo the insert.*/ node->index = dict_table_get_first_index(node->table); diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index d32c6cd2510..af35dc1af7f 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -244,7 +244,10 @@ row_undo_mod_clust( bool online; ut_ad(thr_get_trx(thr) == node->trx); + ut_ad(node->trx->dict_operation_lock_mode); ut_ad(node->trx->in_rollback); + ut_ad(rw_lock_own_flagged(&dict_sys.latch, + RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); log_free_check(); pcur = &node->pcur; @@ -261,7 +264,7 @@ row_undo_mod_clust( online = dict_index_is_online_ddl(index); if (online) { - ut_ad(!node->trx->dict_operation_lock_mode); + ut_ad(node->trx->dict_operation_lock_mode != RW_X_LATCH); mtr_s_lock_index(index, &mtr); } @@ -300,7 +303,17 @@ row_undo_mod_clust( ut_ad(err == DB_SUCCESS || err == DB_OUT_OF_FILE_SPACE); } - if (err == DB_SUCCESS && online && dict_index_is_online_ddl(index)) { + /* Online rebuild cannot be initiated while we are holding + dict_sys.latch and index->lock. (It can be aborted.) */ + ut_ad(online || !dict_index_is_online_ddl(index)); + + if (err == DB_SUCCESS && online) { + + ut_ad(rw_lock_own_flagged( + &index->lock, + RW_LOCK_FLAG_S | RW_LOCK_FLAG_X + | RW_LOCK_FLAG_SX)); + switch (node->rec_type) { case TRX_UNDO_DEL_MARK_REC: row_log_table_insert( @@ -875,6 +888,37 @@ func_exit_no_pcur: } /***********************************************************//** +Flags a secondary index corrupted. */ +static MY_ATTRIBUTE((nonnull)) +void +row_undo_mod_sec_flag_corrupted( +/*============================*/ + trx_t* trx, /*!< in/out: transaction */ + dict_index_t* index) /*!< in: secondary index */ +{ + ut_ad(!dict_index_is_clust(index)); + + switch (trx->dict_operation_lock_mode) { + case RW_S_LATCH: + /* Because row_undo() is holding an S-latch + on the data dictionary during normal rollback, + we can only mark the index corrupted in the + data dictionary cache. TODO: fix this somehow.*/ + mutex_enter(&dict_sys.mutex); + dict_set_corrupted_index_cache_only(index); + mutex_exit(&dict_sys.mutex); + break; + default: + ut_ad(0); + /* fall through */ + case RW_X_LATCH: + /* This should be the rollback of a data dictionary + transaction. */ + dict_set_corrupted(index, trx, "rollback"); + } +} + +/***********************************************************//** Undoes a modify in secondary indexes when undo record type is UPD_DEL. @return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -987,7 +1031,8 @@ row_undo_mod_del_mark_sec( } if (err == DB_DUPLICATE_KEY) { - index->type |= DICT_CORRUPT; + row_undo_mod_sec_flag_corrupted( + thr_get_trx(thr), index); err = DB_SUCCESS; /* Do not return any error to the caller. The duplicate will be reported by ALTER TABLE or @@ -1132,7 +1177,8 @@ row_undo_mod_upd_exist_sec( } if (err == DB_DUPLICATE_KEY) { - index->type |= DICT_CORRUPT; + row_undo_mod_sec_flag_corrupted( + thr_get_trx(thr), index); err = DB_SUCCESS; } else if (err != DB_SUCCESS) { break; @@ -1295,8 +1341,6 @@ row_undo_mod( return DB_SUCCESS; } - ut_ad(node->table->is_temporary() - || lock_table_has_locks(node->table)); node->index = dict_table_get_first_index(node->table); ut_ad(dict_index_is_clust(node->index)); diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 82c999d8b53..375de331255 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -418,8 +418,7 @@ row_undo( for online operation. (A table lock would only be acquired when committing the ALTER TABLE operation.) */ trx_t* trx = node->trx; - const bool locked_data_dict = UNIV_UNLIKELY(trx->is_recovered) - && !trx->dict_operation_lock_mode; + const bool locked_data_dict = !trx->dict_operation_lock_mode; if (UNIV_UNLIKELY(locked_data_dict)) { row_mysql_freeze_data_dictionary(trx); @@ -441,7 +440,8 @@ row_undo( err = DB_CORRUPTION; } - if (UNIV_UNLIKELY(locked_data_dict)) { + if (locked_data_dict) { + row_mysql_unfreeze_data_dictionary(trx); } diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index 11038c6020d..b809e5cb42a 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -459,14 +459,12 @@ LatchDebug::LatchDebug() LEVEL_MAP_INSERT(SYNC_WORK_QUEUE); LEVEL_MAP_INSERT(SYNC_FTS_TOKENIZE); LEVEL_MAP_INSERT(SYNC_FTS_OPTIMIZE); - LEVEL_MAP_INSERT(SYNC_FTS_BG_THREADS); LEVEL_MAP_INSERT(SYNC_FTS_CACHE_INIT); LEVEL_MAP_INSERT(SYNC_RECV); LEVEL_MAP_INSERT(SYNC_LOG_FLUSH_ORDER); LEVEL_MAP_INSERT(SYNC_LOG); LEVEL_MAP_INSERT(SYNC_PURGE_QUEUE); LEVEL_MAP_INSERT(SYNC_TRX_SYS_HEADER); - LEVEL_MAP_INSERT(SYNC_REC_LOCK); LEVEL_MAP_INSERT(SYNC_TRX); LEVEL_MAP_INSERT(SYNC_RW_TRX_HASH_ELEMENT); LEVEL_MAP_INSERT(SYNC_READ_VIEW); @@ -731,7 +729,6 @@ LatchDebug::check_order( /* Fall through */ case SYNC_RECV: - case SYNC_FTS_BG_THREADS: case SYNC_WORK_QUEUE: case SYNC_FTS_TOKENIZE: case SYNC_FTS_OPTIMIZE: @@ -796,15 +793,6 @@ LatchDebug::check_order( } break; - case SYNC_REC_LOCK: - - if (find(latches, SYNC_LOCK_SYS) != 0) { - basic_check(latches, level, SYNC_REC_LOCK - 1); - } else { - basic_check(latches, level, SYNC_REC_LOCK); - } - break; - case SYNC_IBUF_BITMAP: /* Either the thread must own the master mutex to all @@ -1234,9 +1222,6 @@ sync_latch_meta_init() LATCH_ADD_MUTEX(FIL_SYSTEM, SYNC_ANY_LATCH, fil_system_mutex_key); - LATCH_ADD_MUTEX(FTS_BG_THREADS, SYNC_FTS_BG_THREADS, - fts_bg_threads_mutex_key); - LATCH_ADD_MUTEX(FTS_DELETE, SYNC_FTS_OPTIMIZE, fts_delete_mutex_key); LATCH_ADD_MUTEX(FTS_DOC_ID, SYNC_FTS_OPTIMIZE, fts_doc_id_mutex_key); diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index f88a3945773..dd78aa9ae14 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -41,7 +41,6 @@ mysql_pfs_key_t dict_foreign_err_mutex_key; mysql_pfs_key_t dict_sys_mutex_key; mysql_pfs_key_t fil_system_mutex_key; mysql_pfs_key_t flush_list_mutex_key; -mysql_pfs_key_t fts_bg_threads_mutex_key; mysql_pfs_key_t fts_delete_mutex_key; mysql_pfs_key_t fts_doc_id_mutex_key; mysql_pfs_key_t fts_pll_tokenize_mutex_key; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index ba006f37bb5..6b0395cef07 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -129,20 +129,35 @@ trx_undo_log_v_idx( { ut_ad(pos < table->n_v_def); dict_v_col_t* vcol = dict_table_get_nth_v_col(table, pos); - ulint n_idx = vcol->n_v_indexes; byte* old_ptr; - ut_ad(n_idx > 0); + ut_ad(!vcol->v_indexes.empty()); /* Size to reserve, max 5 bytes for each index id and position, plus 5 bytes for num of indexes, 2 bytes for write total length. 1 byte for undo log record format version marker */ - ulint size = n_idx * (5 + 5) + 5 + 2 + (first_v_col ? 1 : 0); + ulint size = 5 + 2 + (first_v_col ? 1 : 0); + const ulint avail = trx_undo_left(undo_block, ptr); - if (trx_undo_left(undo_block, ptr) < size) { + if (avail < size) { return(NULL); } + size = 0; + ulint n_idx = 0; + for (const auto& v_index : vcol->v_indexes) { + n_idx++; + /* FIXME: index->id is 64 bits! */ + size += mach_get_compressed_size(uint32_t(v_index.index->id)); + size += mach_get_compressed_size(v_index.nth_field); + } + size += 2 + mach_get_compressed_size(n_idx); + + if (avail < size) { + return(NULL); + } + + if (first_v_col) { /* write the version marker */ mach_write_to_1(ptr, VIRTUAL_COL_UNDO_FORMAT_1); @@ -158,7 +173,8 @@ trx_undo_log_v_idx( for (const auto& v_index : vcol->v_indexes) { ptr += mach_write_compressed( - ptr, static_cast<ulint>(v_index.index->id)); + /* FIXME: index->id is 64 bits! */ + ptr, uint32_t(v_index.index->id)); ptr += mach_write_compressed(ptr, v_index.nth_field); } |