diff options
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/buf/buf0dump.cc | 4 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 2 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 436 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 43 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 6 | ||||
-rw-r--r-- | storage/innobase/include/log0recv.h | 9 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 4 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 13 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 26 | ||||
-rw-r--r-- | storage/innobase/page/page0cur.cc | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 11 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0vers.cc | 1 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 25 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 17 |
16 files changed, 146 insertions, 459 deletions
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 7ede67fd0e4..088741e8ce8 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -391,7 +391,7 @@ buf_dump( /* leave tmp_filename to exist */ return; } - if ( (j % 1024) == 0) { + if (SHUTTING_DOWN() && !(j % 1024)) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "Dumping buffer pool " ULINTPF "/" ULINTPF ", " diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 51190ff2ef6..3fba1679cdf 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -6110,7 +6110,7 @@ dict_table_get_index_on_name( while (index != NULL) { if (index->is_committed() == committed - && innobase_strcasecmp(index->name, name) == 0) { + && strcmp(index->name, name) == 0) { return(index); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 52d4c815dc3..bfb7abd7ab3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -169,8 +169,6 @@ static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); #endif /* WITH_WSREP */ -/** to protect innobase_open_files */ -static mysql_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ static ulong commit_threads = 0; static mysql_cond_t commit_cond; @@ -461,8 +459,6 @@ operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */ #define INNOBASE_WAKE_INTERVAL 32 static ulong innobase_active_counter = 0; -static hash_table_t* innobase_open_tables; - /** Allowed values of innodb_change_buffering */ static const char* innodb_change_buffering_names[] = { "none", /* IBUF_USE_NONE */ @@ -571,7 +567,6 @@ const struct _ft_vft_ext ft_vft_ext_result = {innobase_fts_get_version, /* Keys to register pthread mutexes/cond in the current file with performance schema */ -static mysql_pfs_key_t innobase_share_mutex_key; static mysql_pfs_key_t commit_cond_mutex_key; static mysql_pfs_key_t commit_cond_key; static mysql_pfs_key_t pending_checkpoint_mutex_key; @@ -580,7 +575,6 @@ static mysql_pfs_key_t thd_destructor_thread_key; static PSI_mutex_info all_pthread_mutexes[] = { PSI_KEY(commit_cond_mutex), PSI_KEY(pending_checkpoint_mutex), - PSI_KEY(innobase_share_mutex) }; static PSI_cond_info all_innodb_conds[] = { @@ -1197,23 +1191,6 @@ static SHOW_VAR innodb_status_variables[]= { {NullS, NullS, SHOW_LONG} }; -/************************************************************************//** -Handling the shared INNOBASE_SHARE structure that is needed to provide table -locking. Register the table name if it doesn't exist in the hash table. */ -static -INNOBASE_SHARE* -get_share( -/*======*/ - const char* table_name); /*!< in: table to lookup */ - -/************************************************************************//** -Free the shared object that was registered with get_share(). */ -static -void -free_share( -/*=======*/ - INNOBASE_SHARE* share); /*!< in/own: share to free */ - /*****************************************************************//** Frees a possible InnoDB trx object associated with the current THD. @return 0 or error number */ @@ -4291,10 +4268,6 @@ static int innodb_init(void* p) ibuf_max_size_update(srv_change_buffer_max_size); - innobase_open_tables = hash_create(200); - mysql_mutex_init(innobase_share_mutex_key, - &innobase_share_mutex, - MY_MUTEX_INIT_FAST); mysql_mutex_init(commit_cond_mutex_key, &commit_cond_m, MY_MUTEX_INIT_FAST); mysql_cond_init(commit_cond_key, &commit_cond, 0); @@ -4363,9 +4336,6 @@ innobase_end(handlerton*, ha_panic_function) } } - hash_table_free(innobase_open_tables); - innobase_open_tables = NULL; - st_my_thread_var* running = reinterpret_cast<st_my_thread_var*>( my_atomic_loadptr_explicit( reinterpret_cast<void**>(&srv_running), @@ -4383,7 +4353,6 @@ innobase_end(handlerton*, ha_panic_function) innodb_shutdown(); innobase_space_shutdown(); - mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_cond_m); mysql_cond_destroy(&commit_cond); mysql_mutex_destroy(&pending_checkpoint_mutex); @@ -5619,6 +5588,7 @@ is consistent between KEY info from mysql and that from innodb index. @param[in] key_info Index info from mysql @param[in] index_info Index info from InnoDB @return true if all column types match. */ +static bool innobase_match_index_columns( const KEY* key_info, @@ -5908,90 +5878,33 @@ innobase_build_v_templ( s_templ->tb_name = table->s->table_name.str; } -/*******************************************************************//** -This function builds a translation table in INNOBASE_SHARE -structure for fast index location with mysql array number from its -table->key_info structure. This also provides the necessary translation -between the key order in mysql key_info and InnoDB ib_table->indexes if -they are not fully matched with each other. -Note we do not have any mutex protecting the translation table -building based on the assumption that there is no concurrent -index creation/drop and DMLs that requires index lookup. All table -handle will be closed before the index creation/drop. -@return true if index translation table built successfully */ -static -bool -innobase_build_index_translation( -/*=============================*/ - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - dict_table_t* ib_table,/*!< in: table in InnoDB data - dictionary */ - INNOBASE_SHARE* share) /*!< in/out: share structure - where index translation table - will be constructed in. */ +/** Check consistency between .frm indexes and InnoDB indexes. +@param[in] table table object formed from .frm +@param[in] ib_table InnoDB table definition +@retval true if not errors were found */ +static bool +check_index_consistency(const TABLE* table, const dict_table_t* ib_table) { - DBUG_ENTER("innobase_build_index_translation"); - - bool ret = true; - - mutex_enter(&dict_sys->mutex); - - ulint mysql_num_index = table->s->keys; - ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); - dict_index_t** index_mapping = share->idx_trans_tbl.index_mapping; + ulint mysql_num_index = table->s->keys; + ulint ib_num_index = UT_LIST_GET_LEN(ib_table->indexes); + bool ret = true; /* If there exists inconsistency between MySQL and InnoDB dictionary (metadata) information, the number of index defined in MySQL - could exceed that in InnoDB, do not build index translation - table in such case */ + could exceed that in InnoDB, return error */ if (ib_num_index < mysql_num_index) { ret = false; goto func_exit; } - /* If index entry count is non-zero, nothing has - changed since last update, directly return TRUE */ - if (share->idx_trans_tbl.index_count) { - /* Index entry count should still match mysql_num_index */ - ut_a(share->idx_trans_tbl.index_count == mysql_num_index); - goto func_exit; - } - - /* The number of index increased, rebuild the mapping table */ - if (mysql_num_index > share->idx_trans_tbl.array_size) { - - index_mapping = reinterpret_cast<dict_index_t**>( - ut_realloc(index_mapping, - mysql_num_index * sizeof(*index_mapping))); - - if (index_mapping == NULL) { - /* Report an error if index_mapping continues to be - NULL and mysql_num_index is a non-zero value */ - sql_print_error("InnoDB: fail to allocate memory for " - "index translation table. Number of " - "Index: " ULINTPF - ", array size:" ULINTPF, - mysql_num_index, - share->idx_trans_tbl.array_size); - ret = false; - goto func_exit; - } - - share->idx_trans_tbl.array_size = mysql_num_index; - } - /* For each index in the mysql key_info array, fetch its corresponding InnoDB index pointer into index_mapping array. */ for (ulint count = 0; count < mysql_num_index; count++) { - - /* Fetch index pointers into index_mapping according to mysql - index sequence */ - index_mapping[count] = dict_table_get_index_on_name( + const dict_index_t* index = dict_table_get_index_on_name( ib_table, table->key_info[count].name.str); - if (index_mapping[count] == 0) { + if (index == NULL) { sql_print_error("Cannot find index %s in InnoDB" " index dictionary.", table->key_info[count].name.str); @@ -6002,7 +5915,7 @@ innobase_build_index_translation( /* Double check fetched index has the same column info as those in mysql key_info. */ if (!innobase_match_index_columns(&table->key_info[count], - index_mapping[count])) { + index)) { sql_print_error("Found index %s whose column info" " does not match that of MariaDB.", table->key_info[count].name.str); @@ -6011,51 +5924,10 @@ innobase_build_index_translation( } } - /* Successfully built the translation table */ - share->idx_trans_tbl.index_count = mysql_num_index; - func_exit: - if (!ret) { - /* Build translation table failed. */ - ut_free(index_mapping); - - share->idx_trans_tbl.array_size = 0; - share->idx_trans_tbl.index_count = 0; - index_mapping = NULL; - } - - share->idx_trans_tbl.index_mapping = index_mapping; - - mutex_exit(&dict_sys->mutex); - - DBUG_RETURN(ret); + return ret; } -/*******************************************************************//** -This function uses index translation table to quickly locate the -requested index structure. -Note we do not have mutex protection for the index translatoin table -access, it is based on the assumption that there is no concurrent -translation table rebuild (fter create/drop index) and DMLs that -require index lookup. -@return dict_index_t structure for requested index. NULL if -fail to locate the index structure. */ -static -dict_index_t* -innobase_index_lookup( -/*==================*/ - INNOBASE_SHARE* share, /*!< in: share structure for index - translation table. */ - uint keynr) /*!< in: index number for the requested - index */ -{ - if (share->idx_trans_tbl.index_mapping == NULL - || keynr >= share->idx_trans_tbl.index_count) { - return(NULL); - } - - return(share->idx_trans_tbl.index_mapping[keynr]); -} /********************************************************************//** Get the upper limit of the MySQL integral and floating-point type. @return maximum allowed value for the field */ @@ -6185,11 +6057,6 @@ ha_innobase::open(const char* name, int, uint) m_user_thd = NULL; - if (!(m_share = get_share(name))) { - - DBUG_RETURN(1); - } - /* Will be allocated if it is needed in ::update_row() */ m_upd_buf = NULL; m_upd_buf_size = 0; @@ -6213,7 +6080,6 @@ ha_innobase::open(const char* name, int, uint) norm_name); } no_such_table: - free_share(m_share); set_my_errno(ENOENT); DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); @@ -6271,7 +6137,6 @@ no_such_table: } if (!thd_tablespace_op(thd)) { - free_share(m_share); set_my_errno(ENOENT); int ret_err = HA_ERR_NO_SUCH_TABLE; @@ -6328,9 +6193,10 @@ no_such_table: mutex_exit(&dict_sys->mutex); } - if (!innobase_build_index_translation(table, ib_table, m_share)) { - sql_print_error("Build InnoDB index translation table for" - " Table %s failed", name); + if (!check_index_consistency(table, ib_table)) { + sql_print_error("InnoDB indexes are inconsistent with what " + "defined in .frm for table %s", + name); } /* Allocate a buffer for a 'row reference'. A row reference is @@ -6426,9 +6292,6 @@ no_such_table: /* Index block size in InnoDB: used by MySQL in query optimization */ stats.block_size = srv_page_size; - /* Init table lock structure */ - thr_lock_data_init(&m_share->lock, &lock, NULL); - if (m_prebuilt->table == NULL || m_prebuilt->table->is_temporary() || m_prebuilt->table->persistent_autoinc @@ -6621,8 +6484,6 @@ ha_innobase::close() m_upd_buf_size = 0; } - free_share(m_share); - MONITOR_INC(MONITOR_TABLE_CLOSE); /* Tell InnoDB server that there might be work for @@ -8186,7 +8047,7 @@ ha_innobase::write_row( /* We need the upper limit of the col type to check for whether we update the table autoinc counter or not. */ - col_max_value = innobase_get_int_col_max_value(table->next_number_field); + col_max_value = table->next_number_field->get_max_int_value(); /* Get the value that MySQL attempted to store in the table.*/ auto_inc = table->next_number_field->val_uint(); @@ -8261,14 +8122,30 @@ set_max_autoinc: /* This should filter out the negative values set explicitly by the user. */ if (auto_inc <= col_max_value) { - ut_a(m_prebuilt->autoinc_increment > 0); - ulonglong offset; ulonglong increment; dberr_t err; - offset = m_prebuilt->autoinc_offset; - increment = m_prebuilt->autoinc_increment; +#ifdef WITH_WSREP + /* Applier threads which are + processing ROW events and don't go + through server level autoinc + processing, therefore m_prebuilt + autoinc values don't get + properly assigned. Fetch values from + server side. */ + if (wsrep_on(m_user_thd) && + wsrep_thd_exec_mode(m_user_thd) == REPL_RECV) { + wsrep_thd_auto_increment_variables(m_user_thd, &offset, &increment); + } else { +#endif /* WITH_WSREP */ + ut_a(m_prebuilt->autoinc_increment > 0); + + offset = m_prebuilt->autoinc_offset; + increment = m_prebuilt->autoinc_increment; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ auto_inc = innobase_next_autoinc( auto_inc, @@ -8966,12 +8843,27 @@ ha_innobase::update_row( /* A value for an AUTO_INCREMENT column was specified in the UPDATE statement. */ + ulonglong offset, increment; +#ifdef WITH_WSREP + /* Applier threads which are processing ROW events and + don't go through server level autoinc processing, + therefore m_prebuilt autoinc values don't get properly + assigned. Fetch values from server side. */ + if (wsrep_on(m_user_thd) + && wsrep_thd_exec_mode(m_user_thd) == REPL_RECV) { + wsrep_thd_auto_increment_variables( + m_user_thd, &offset, &increment); + } else { +#endif /* WITH_WSREP */ + offset = m_prebuilt->autoinc_offset; + increment = m_prebuilt->autoinc_increment; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ + autoinc = innobase_next_autoinc( - autoinc, 1, - m_prebuilt->autoinc_increment, - m_prebuilt->autoinc_offset, - innobase_get_int_col_max_value( - table->found_next_number_field)); + autoinc, 1, increment, offset, + table->found_next_number_field->get_max_int_value()); error = innobase_set_max_autoinc(autoinc); @@ -9489,60 +9381,18 @@ ha_innobase::innobase_get_index( clustered index, even if it was internally generated by InnoDB */ { - KEY* key; + KEY* key = NULL; + dict_table_t* ib_table = m_prebuilt->table; dict_index_t* index; DBUG_ENTER("innobase_get_index"); if (keynr != MAX_KEY && table->s->keys > 0) { - - key = table->key_info + keynr; - - index = innobase_index_lookup(m_share, keynr); - - if (index != NULL) { - if (!key || ut_strcmp(index->name, key->name.str) != 0) { - ib::error() << " Index for key no " << keynr - << " mysql name " << (key ? key->name.str : "NULL") - << " InnoDB name " << index->name() - << " for table " << m_prebuilt->table->name.m_name; - - for(uint i=0; i < table->s->keys; i++) { - index = innobase_index_lookup(m_share, i); - key = table->key_info + keynr; - - if (index) { - ib::info() << " Index for key no " << keynr - << " mysql name " << (key ? key->name.str : "NULL") - << " InnoDB name " << index->name() - << " for table " << m_prebuilt->table->name.m_name; - } - } - - } - - ut_a(ut_strcmp(index->name, key->name.str) == 0); - } else { - /* Can't find index with keynr in the translation - table. Only print message if the index translation - table exists */ - if (m_share->idx_trans_tbl.index_mapping != NULL) { - sql_print_warning("InnoDB could not find" - " index %s key no %u for" - " table %s through its" - " index translation table", - key ? key->name.str : "NULL", - keynr, - m_prebuilt->table->name - .m_name); - } - - index = dict_table_get_index_on_name( - m_prebuilt->table, key->name.str); - } + key = &table->key_info[keynr]; + index = dict_table_get_index_on_name(ib_table, key->name.str); + ut_ad(index); } else { - key = 0; - index = dict_table_get_first_index(m_prebuilt->table); + index = dict_table_get_first_index(ib_table); } if (index == NULL) { @@ -9550,7 +9400,7 @@ ha_innobase::innobase_get_index( "InnoDB could not find key no %u with name %s" " from dict cache for table %s", keynr, key ? key->name.str : "NULL", - m_prebuilt->table->name.m_name); + ib_table->name.m_name); } DBUG_RETURN(index); @@ -13703,20 +13553,12 @@ innodb_set_buf_pool_size(ulonglong buf_pool_size) } /*********************************************************************//** -Calculates the key number used inside MySQL for an Innobase index. We will -first check the "index translation table" for a match of the index to get -the index number. If there does not exist an "index translation table", -or not able to find the index in the translation table, then we will fall back -to the traditional way of looping through dict_index_t list to find a -match. In this case, we have to take into account if we generated a -default clustered index for the table +Calculates the key number used inside MySQL for an Innobase index. @return the key number used inside MySQL */ static unsigned innobase_get_mysql_key_number_for_index( /*====================================*/ - INNOBASE_SHARE* share, /*!< in: share structure for index - translation table. */ const TABLE* table, /*!< in: table in MySQL data dictionary */ dict_table_t* ib_table,/*!< in: table in InnoDB data @@ -13746,27 +13588,8 @@ innobase_get_mysql_key_number_for_index( return(i); } - /* If index translation table exists, we will first check - the index through index translation table for a match. */ - if (share->idx_trans_tbl.index_mapping != NULL) { - for (i = 0; i < share->idx_trans_tbl.index_count; i++) { - if (share->idx_trans_tbl.index_mapping[i] == index) { - return(i); - } - } - - /* Print an error message if we cannot find the index - in the "index translation table". */ - if (index->is_committed()) { - sql_print_error("Cannot find index %s in InnoDB index" - " translation table.", index->name()); - } - } - - /* If we do not have an "index translation table", or not able - to find the index in the translation table, we'll directly find - matching index with information from mysql TABLE structure and - InnoDB dict_index_t list */ + /* Directly find matching index with information from mysql TABLE + structure and InnoDB dict_index_t list */ for (i = 0; i < table->s->keys; i++) { ind = dict_table_get_index_on_name( ib_table, table->key_info[i].name.str); @@ -14123,11 +13946,6 @@ ha_innobase::info_low( for (i = 0; i < table->s->keys; i++) { ulong j; - /* We could get index quickly through internal - index mapping with the index translation table. - The identity of index (match up index name with - that of table->key_info[i]) is already verified in - innobase_get_index(). */ dict_index_t* index = innobase_get_index(i); if (index == NULL) { @@ -14235,7 +14053,7 @@ ha_innobase::info_low( if (err_index) { errkey = innobase_get_mysql_key_number_for_index( - m_share, table, ib_table, err_index); + table, ib_table, err_index); } else { errkey = (unsigned int) ( (m_prebuilt->trx->error_key_num @@ -16240,104 +16058,6 @@ innobase_show_status( /* Success */ return(false); } - -/************************************************************************//** -Handling the shared INNOBASE_SHARE structure that is needed to provide table -locking. Register the table name if it doesn't exist in the hash table. */ -static -INNOBASE_SHARE* -get_share( -/*======*/ - const char* table_name) -{ - INNOBASE_SHARE* share; - - mysql_mutex_lock(&innobase_share_mutex); - - ulint fold = ut_fold_string(table_name); - - HASH_SEARCH(table_name_hash, innobase_open_tables, fold, - INNOBASE_SHARE*, share, - ut_ad(share->use_count > 0), - !strcmp(share->table_name, table_name)); - - if (share == NULL) { - - uint length = (uint) strlen(table_name); - - /* TODO: invoke HASH_MIGRATE if innobase_open_tables - grows too big */ - - share = reinterpret_cast<INNOBASE_SHARE*>( - my_malloc(//PSI_INSTRUMENT_ME, - sizeof(*share) + length + 1, - MYF(MY_FAE | MY_ZEROFILL))); - - share->table_name = reinterpret_cast<char*>( - memcpy(share + 1, table_name, length + 1)); - - HASH_INSERT(INNOBASE_SHARE, table_name_hash, - innobase_open_tables, fold, share); - - thr_lock_init(&share->lock); - - /* Index translation table initialization */ - share->idx_trans_tbl.index_mapping = NULL; - share->idx_trans_tbl.index_count = 0; - share->idx_trans_tbl.array_size = 0; - } - - ++share->use_count; - - mysql_mutex_unlock(&innobase_share_mutex); - - return(share); -} - -/************************************************************************//** -Free the shared object that was registered with get_share(). */ -static -void -free_share( -/*=======*/ - INNOBASE_SHARE* share) /*!< in/own: table share to free */ -{ - mysql_mutex_lock(&innobase_share_mutex); - -#ifdef UNIV_DEBUG - INNOBASE_SHARE* share2; - ulint fold = ut_fold_string(share->table_name); - - HASH_SEARCH(table_name_hash, innobase_open_tables, fold, - INNOBASE_SHARE*, share2, - ut_ad(share->use_count > 0), - !strcmp(share->table_name, share2->table_name)); - - ut_a(share2 == share); -#endif /* UNIV_DEBUG */ - - --share->use_count; - - if (share->use_count == 0) { - ulint fold = ut_fold_string(share->table_name); - - HASH_DELETE(INNOBASE_SHARE, table_name_hash, - innobase_open_tables, fold, share); - - thr_lock_delete(&share->lock); - - /* Free any memory from index translation table */ - ut_free(share->idx_trans_tbl.index_mapping); - - my_free(share); - - /* TODO: invoke HASH_MIGRATE if innobase_open_tables - shrinks too much */ - } - - mysql_mutex_unlock(&innobase_share_mutex); -} - /*********************************************************************//** Returns number of THR_LOCK locks used for one instance of InnoDB table. InnoDB no longer relies on THR_LOCK locks so 0 value is returned. @@ -16789,16 +16509,16 @@ ha_innobase::get_auto_increment( "THD: %ld, current: %llu, autoinc: %llu", m_prebuilt->autoinc_increment, increment, - thd_get_thread_id(ha_thd()), + thd_get_thread_id(m_user_thd), current, autoinc); - if (!wsrep_on(ha_thd())) { - current = autoinc - m_prebuilt->autoinc_increment; + if (!wsrep_on(m_user_thd)) { + current = innobase_next_autoinc( + autoinc + - m_prebuilt->autoinc_increment, + 1, increment, offset, col_max_value); } - current = innobase_next_autoinc( - current, 1, increment, offset, col_max_value); - dict_table_autoinc_initialize( m_prebuilt->table, current); @@ -20722,6 +20442,7 @@ static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table) if (!table_name_parse(table->name, db_buf, tbl_buf, db_buf_len, tbl_buf_len)) { + table->release(); return NULL; } @@ -20804,6 +20525,7 @@ static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table) if (!table_name_parse(table->name, db_buf, tbl_buf, db_buf_len, tbl_buf_len)) { + ut_ad(!"invalid table name"); return NULL; } diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index f2bb8aa5ef2..c98779f6823 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -23,35 +23,6 @@ this program; if not, write to the Free Software Foundation, Inc., system clustered index when there is no primary key. */ extern const char innobase_index_reserve_name[]; -/* Structure defines translation table between mysql index and InnoDB -index structures */ -struct innodb_idx_translate_t { - - ulint index_count; /*!< number of valid index entries - in the index_mapping array */ - - ulint array_size; /*!< array size of index_mapping */ - - dict_index_t** index_mapping; /*!< index pointer array directly - maps to index in InnoDB from MySQL - array index */ -}; - -/** InnoDB table share */ -typedef struct st_innobase_share { - THR_LOCK lock; - const char* table_name; /*!< InnoDB table name */ - uint use_count; /*!< reference count, - incremented in get_share() - and decremented in - free_share() */ - void* table_name_hash; - /*!< hash table chain node */ - innodb_idx_translate_t - idx_trans_tbl; /*!< index translation table between - MySQL and InnoDB */ -} INNOBASE_SHARE; - /** Prebuilt structures in an InnoDB table handle used within MySQL */ struct row_prebuilt_t; @@ -496,9 +467,6 @@ protected: THR_LOCK_DATA lock; - /** information for MySQL table locking */ - INNOBASE_SHARE* m_share; - /** buffer used in updates */ uchar* m_upd_buf; @@ -635,17 +603,6 @@ trx_t* innobase_trx_allocate( MYSQL_THD thd); /*!< in: user thread handle */ -/** Match index columns between MySQL and InnoDB. -This function checks whether the index column information -is consistent between KEY info from mysql and that from innodb index. -@param[in] key_info Index info from mysql -@param[in] index_info Index info from InnoDB -@return true if all column types match. */ -bool -innobase_match_index_columns( - const KEY* key_info, - const dict_index_t* index_info); - /*********************************************************************//** This function checks each index name for a table against reserved system default primary index name 'GEN_CLUST_INDEX'. If a name diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 3f31f253b3f..f9fca700179 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -9775,12 +9775,6 @@ foreign_fail: log_append_on_checkpoint(NULL); - /* Invalidate the index translation table. In partitioned - tables, there is no share. */ - if (m_share) { - m_share->idx_trans_tbl.index_count = 0; - } - /* Tell the InnoDB server that there might be work for utility threads: */ diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index eda991661c1..8065ff2c96c 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -139,10 +139,15 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply); /** Moves the parsing buffer data left to the buffer start. */ void recv_sys_justify_left_parsing_buf(); -/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +/** Report optimized DDL operation (without redo log), +corresponding to MLOG_INDEX_LOAD. @param[in] space_id tablespace identifier */ -extern void(*log_optimized_ddl_op)(ulint space_id); +extern void (*log_optimized_ddl_op)(ulint space_id); + +/** Report backup-unfriendly TRUNCATE operation (with separate log file), +corresponding to MLOG_TRUNCATE. */ +extern void (*log_truncate)(); /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 07ae85ced5a..b7c4f8d37cd 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -3528,7 +3528,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock) { + if (c_lock && wsrep_on_trx(trx)) { if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); @@ -3758,7 +3758,7 @@ lock_table_enqueue_waiting( } #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim) { + if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { return(DB_DEADLOCK); } #endif /* WITH_WSREP */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 09ed2f16d7d..c871acb5389 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -959,12 +959,6 @@ log_write_up_to( return; } - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { - service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, - "log write up to: " LSN_PF, - lsn); - } - loop: ut_ad(++loop_count < 128); @@ -1092,6 +1086,13 @@ loop: } } + if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE)) { + service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, + "InnoDB log write: " + LSN_PF "," LSN_PF, + log_sys.write_lsn, lsn); + } + if (log_sys.is_encrypted()) { log_crypt(write_buf + area_start, log_sys.write_lsn, area_end - area_start); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 3d240dc58fe..f5c3f1ecb23 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -169,11 +169,16 @@ typedef std::map< static recv_spaces_t recv_spaces; -/** Report optimized DDL operation (without redo log), corresponding to MLOG_INDEX_LOAD. +/** Report optimized DDL operation (without redo log), +corresponding to MLOG_INDEX_LOAD. @param[in] space_id tablespace identifier */ void (*log_optimized_ddl_op)(ulint space_id); +/** Report backup-unfriendly TRUNCATE operation (with separate log file), +corresponding to MLOG_TRUNCATE. */ +void (*log_truncate)(); + /** Report an operation to create, delete, or rename a file during backup. @param[in] space_id tablespace identifier @param[in] flags tablespace flags (NULL if not create) @@ -189,11 +194,9 @@ void (*log_file_op)(ulint space_id, const byte* flags, @param[in,out] name file name @param[in] len length of the file name @param[in] space_id the tablespace ID -@param[in] deleted whether this is a MLOG_FILE_DELETE record -@retval true if able to process file successfully. -@retval false if unable to process the file */ +@param[in] deleted whether this is a MLOG_FILE_DELETE record */ static -bool +void fil_name_process( char* name, ulint len, @@ -201,15 +204,13 @@ fil_name_process( bool deleted) { if (srv_operation == SRV_OPERATION_BACKUP) { - return true; + return; } ut_ad(srv_operation == SRV_OPERATION_NORMAL || srv_operation == SRV_OPERATION_RESTORE || srv_operation == SRV_OPERATION_RESTORE_EXPORT); - bool processed = true; - /* We will also insert space=NULL into the map, so that further checks can ensure that a MLOG_FILE_NAME record was scanned before applying any page records for the space_id. */ @@ -256,7 +257,6 @@ fil_name_process( << f.name << "' and '" << name << "'." " You must delete one of them."; recv_sys->found_corrupt_fs = true; - processed = false; } break; @@ -309,7 +309,6 @@ fil_name_process( " remove the .ibd file, you can set" " --innodb_force_recovery."; recv_sys->found_corrupt_fs = true; - processed = false; break; } @@ -320,7 +319,6 @@ fil_name_process( break; } } - return(processed); } /** Parse or process a MLOG_FILE_* record. @@ -1093,6 +1091,12 @@ recv_parse_or_apply_log_rec_body( } return(ptr + 8); case MLOG_TRUNCATE: + if (log_truncate) { + ut_ad(srv_operation != SRV_OPERATION_NORMAL); + log_truncate(); + recv_sys->found_corrupt_fs = true; + return NULL; + } return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id)); default: diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 36b9a135b10..fb8f62f5fe3 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -846,7 +846,8 @@ page_cur_insert_rec_write_log( ulint i; if (index->table->is_temporary()) { - ut_ad(!mlog_open(mtr, 0)); + mtr->set_modified(); + ut_ad(mtr->get_log_mode() == MTR_LOG_NO_REDO); return; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index aab445cb197..8758db3c346 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3915,7 +3915,7 @@ row_import_for_mysql( DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure", err = DB_TOO_MANY_CONCURRENT_TRXS;); - +#ifdef BTR_CUR_HASH_ADAPT /* On DISCARD TABLESPACE, we did not drop any adaptive hash index entries. If we replaced the discarded tablespace with a smaller one here, there could still be some adaptive hash @@ -3932,6 +3932,7 @@ row_import_for_mysql( break; } } +#endif /* BTR_CUR_HASH_ADAPT */ if (err != DB_SUCCESS) { char table_name[MAX_FULL_NAME_LEN + 1]; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index ba8a7044baa..000da4b0562 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -3934,17 +3934,6 @@ row_merge_drop_indexes( ut_ad(prev); ut_a(table->fts); fts_drop_index(table, index, trx); - /* Since - INNOBASE_SHARE::idx_trans_tbl - is shared between all open - ha_innobase handles to this - table, no thread should be - accessing this dict_index_t - object. Also, we should be - holding LOCK=SHARED MDL on the - table even after the MDL - upgrade timeout. */ - /* We can remove a DICT_FTS index from the cache, because we do not allow ADD FULLTEXT INDEX diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index a3c3d0eaaa6..7c68bf6f7c2 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3536,6 +3536,7 @@ row_drop_table_for_mysql( if (!table->no_rollback()) { if (table->space != fil_system.sys_space) { +#ifdef BTR_CUR_HASH_ADAPT /* On DISCARD TABLESPACE, we would not drop the adaptive hash index entries. If the tablespace is missing here, delete-marking the record in SYS_INDEXES @@ -3557,6 +3558,7 @@ row_drop_table_for_mysql( goto funct_exit; } } +#endif /* BTR_CUR_HASH_ADAPT */ /* Delete the link file if used. */ if (DICT_TF_HAS_DATA_DIR(table->flags)) { diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 187fa2a0929..fac01fe26cc 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -452,6 +452,7 @@ row_vers_build_clust_v_col( byte* record= 0; ut_ad(dict_index_has_virtual(index)); + ut_ad(index->table == clust_index->table); if (vcol_info != NULL) { vcol_info->set_used(); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 44cb3276561..ae4922af235 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2417,7 +2417,22 @@ static bool srv_purge_should_exit() return(true); } /* Slow shutdown was requested. */ - return !trx_sys.any_active_transactions() && !trx_sys.history_size(); + if (ulint history_size = trx_sys.history_size()) { +#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY + static ib_time_t progress_time; + ib_time_t time = ut_time(); + if (time - progress_time >= 15) { + progress_time = time; + service_manager_extend_timeout( + INNODB_EXTEND_TIMEOUT_INTERVAL, + "InnoDB: to purge " ULINTPF " transactions", + history_size); + } +#endif + return false; + } + + return !trx_sys.any_active_transactions(); } /*********************************************************************//** @@ -2583,14 +2598,6 @@ srv_do_purge(ulint* n_total_purged) (++count % rseg_truncate_frequency) == 0); *n_total_purged += n_pages_purged; - - if (n_pages_purged) { - service_manager_extend_timeout( - INNODB_EXTEND_TIMEOUT_INTERVAL, - "InnoDB " ULINTPF " pages purged", n_pages_purged); - /* The previous round still did some work. */ - continue; - } } while (n_pages_purged > 0 && !purge_sys.paused() && !srv_purge_should_exit()); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 32e050e9b91..8f6e585f66b 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -258,7 +258,12 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) trx_sys.get_max_trx_id(), mtr); } - /* Before any transaction-generating background threads or the + /* After the purge thread has been given permission to exit, + we may roll back transactions (trx->undo_no==0) + in THD::cleanup() invoked from unlink_thd() in fast shutdown, + or in trx_rollback_resurrected() in slow shutdown. + + Before any transaction-generating background threads or the purge have been started, recv_recovery_rollback_active() can start transactions in row_merge_drop_temp_indexes() and fts_drop_orphaned_tables(), and roll back recovered transactions. @@ -268,17 +273,15 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr) innodb_force_recovery=2 or innodb_force_recovery=3. DROP TABLE may be executed at any innodb_force_recovery level. - After the purge thread has been given permission to exit, - in fast shutdown, we may roll back transactions (trx->undo_no==0) - in THD::cleanup() invoked from unlink_thd(), and we may also - continue to execute user transactions. */ + During fast shutdown, we may also continue to execute + user transactions. */ ut_ad(srv_undo_sources + || trx->undo_no == 0 || (!purge_sys.enabled() && (srv_startup_is_before_trx_rollback_phase || trx_rollback_is_active || srv_force_recovery >= SRV_FORCE_NO_BACKGROUND)) - || ((trx->undo_no == 0 || trx->mysql_thd - || trx->internal) + || ((trx->mysql_thd || trx->internal) && srv_fast_shutdown)); #ifdef WITH_WSREP |