diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-10-09 18:16:27 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-10-09 18:16:27 +0200 |
commit | 01be663c503f180b47f477fb8cc7a2b55a7b79ff (patch) | |
tree | 2c97076b3a28dd4f0f523a344863726074b2bd02 | |
parent | 77c44a3470885e37489f85c90f6146e3309df030 (diff) | |
parent | 6a821d78a6a33aaf81909ab2858d13f95dbe2708 (diff) | |
download | mariadb-git-01be663c503f180b47f477fb8cc7a2b55a7b79ff.tar.gz |
Merge branch 'merge-xtradb-5.6' into 10.0
-rw-r--r-- | storage/xtradb/api/api0api.cc | 12 | ||||
-rw-r--r-- | storage/xtradb/btr/btr0cur.cc | 8 | ||||
-rw-r--r-- | storage/xtradb/buf/buf0flu.cc | 19 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0dict.cc | 65 | ||||
-rw-r--r-- | storage/xtradb/dict/dict0stats_bg.cc | 8 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0fil.cc | 9 | ||||
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 69 | ||||
-rw-r--r-- | storage/xtradb/handler/handler0alter.cc | 166 | ||||
-rw-r--r-- | storage/xtradb/ibuf/ibuf0ibuf.cc | 4 | ||||
-rw-r--r-- | storage/xtradb/include/dict0dict.h | 27 | ||||
-rw-r--r-- | storage/xtradb/include/dict0dict.ic | 2 | ||||
-rw-r--r-- | storage/xtradb/include/fts0fts.h | 2 | ||||
-rw-r--r-- | storage/xtradb/include/row0purge.h | 12 | ||||
-rw-r--r-- | storage/xtradb/include/univ.i | 4 | ||||
-rw-r--r-- | storage/xtradb/log/log0log.cc | 3 | ||||
-rw-r--r-- | storage/xtradb/os/os0file.cc | 18 | ||||
-rw-r--r-- | storage/xtradb/row/row0import.cc | 107 | ||||
-rw-r--r-- | storage/xtradb/row/row0ins.cc | 71 | ||||
-rw-r--r-- | storage/xtradb/row/row0purge.cc | 79 | ||||
-rw-r--r-- | storage/xtradb/row/row0sel.cc | 2 | ||||
-rw-r--r-- | storage/xtradb/srv/srv0srv.cc | 3 | ||||
-rw-r--r-- | storage/xtradb/srv/srv0start.cc | 27 |
22 files changed, 418 insertions, 299 deletions
diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc index 0fe21423232..739ea9f7572 100644 --- a/storage/xtradb/api/api0api.cc +++ b/storage/xtradb/api/api0api.cc @@ -245,7 +245,7 @@ ib_open_table_by_id( dict_mutex_enter_for_mysql(); } - table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL); + table = dict_table_open_on_id(table_id, TRUE, DICT_TABLE_OP_NORMAL); if (table != NULL && table->ibd_file_missing) { table = NULL; @@ -2116,6 +2116,10 @@ ib_cursor_moveto( n_fields = dict_index_get_n_ordering_defined_by_user(prebuilt->index); + if (n_fields > dtuple_get_n_fields(tuple->ptr)) { + n_fields = dtuple_get_n_fields(tuple->ptr); + } + dtuple_set_n_fields(search_tuple, n_fields); dtuple_set_n_fields_cmp(search_tuple, n_fields); @@ -3753,14 +3757,14 @@ ib_table_truncate( if (trunc_err == DB_SUCCESS) { ut_a(ib_trx_state(ib_trx) == static_cast<ib_trx_state_t>( TRX_STATE_NOT_STARTED)); - - err = ib_trx_release(ib_trx); - ut_a(err == DB_SUCCESS); } else { err = ib_trx_rollback(ib_trx); ut_a(err == DB_SUCCESS); } + err = ib_trx_release(ib_trx); + ut_a(err == DB_SUCCESS); + /* Set the memcached_sync_count back. */ if (table != NULL && memcached_sync != 0) { dict_mutex_enter_for_mysql(); diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index 4186c9ab33f..04e5797602c 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -4175,6 +4175,14 @@ btr_estimate_number_of_different_key_vals( page = btr_cur_get_page(&cursor); SRV_CORRUPT_TABLE_CHECK(page, goto exit_loop;); + DBUG_EXECUTE_IF("ib_corrupt_page_while_stats_calc", + page = NULL;); + + SRV_CORRUPT_TABLE_CHECK(page, + { + mtr_commit(&mtr); + goto exit_loop; + }); rec = page_rec_get_next(page_get_infimum_rec(page)); diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc index 278f47fc327..c0686cf844f 100644 --- a/storage/xtradb/buf/buf0flu.cc +++ b/storage/xtradb/buf/buf0flu.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, 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 @@ -931,12 +931,12 @@ buf_flush_write_block_low( break; case BUF_BLOCK_ZIP_DIRTY: frame = bpage->zip.data; - mach_write_to_8(frame + FIL_PAGE_LSN, bpage->newest_modification); - memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8); ut_a(page_zip_verify_checksum(frame, zip_size)); + + memset(frame + FIL_PAGE_FILE_FLUSH_LSN, 0, 8); break; case BUF_BLOCK_FILE_PAGE: frame = bpage->zip.data; @@ -2847,8 +2847,6 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( while (srv_shutdown_state == SRV_SHUTDOWN_NONE || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP) { - ulint n_flushed_lru; - srv_current_thread_priority = srv_cleaner_thread_priority; page_cleaner_sleep_if_needed(next_loop_time); @@ -2857,16 +2855,7 @@ DECLARE_THREAD(buf_flush_lru_manager_thread)( next_loop_time = ut_time_ms() + lru_sleep_time; - n_flushed_lru = buf_flush_LRU_tail(); - - if (n_flushed_lru) { - - MONITOR_INC_VALUE_CUMULATIVE( - MONITOR_FLUSH_BACKGROUND_TOTAL_PAGE, - MONITOR_FLUSH_BACKGROUND_COUNT, - MONITOR_FLUSH_BACKGROUND_PAGES, - n_flushed_lru); - } + buf_flush_LRU_tail(); } buf_lru_manager_is_active = false; diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 7b6166b15fb..01c5453f351 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -3280,71 +3280,6 @@ dict_table_is_referenced_by_foreign_key( return(!table->referenced_set.empty()); } -/*********************************************************************//** -Check if the index is referenced by a foreign key, if TRUE return foreign -else return NULL -@return pointer to foreign key struct if index is defined for foreign -key, otherwise NULL */ -UNIV_INTERN -dict_foreign_t* -dict_table_get_referenced_constraint( -/*=================================*/ - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index) /*!< in: InnoDB index */ -{ - dict_foreign_t* foreign; - - ut_ad(index != NULL); - ut_ad(table != NULL); - - for (dict_foreign_set::iterator it = table->referenced_set.begin(); - it != table->referenced_set.end(); - ++it) { - - foreign = *it; - - if (foreign->referenced_index == index) { - - return(foreign); - } - } - - return(NULL); -} - -/*********************************************************************//** -Checks if a index is defined for a foreign key constraint. Index is a part -of a foreign key constraint if the index is referenced by foreign key -or index is a foreign key index. -@return pointer to foreign key struct if index is defined for foreign -key, otherwise NULL */ -UNIV_INTERN -dict_foreign_t* -dict_table_get_foreign_constraint( -/*==============================*/ - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index) /*!< in: InnoDB index */ -{ - dict_foreign_t* foreign; - - ut_ad(index != NULL); - ut_ad(table != NULL); - - for (dict_foreign_set::iterator it = table->foreign_set.begin(); - it != table->foreign_set.end(); - ++it) { - - foreign = *it; - - if (foreign->foreign_index == index) { - - return(foreign); - } - } - - return(NULL); -} - /**********************************************************************//** Removes a foreign constraint struct from the dictionary cache. */ UNIV_INTERN diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc index 9e1f75a13a9..a5e0e2cf044 100644 --- a/storage/xtradb/dict/dict0stats_bg.cc +++ b/storage/xtradb/dict/dict0stats_bg.cc @@ -352,6 +352,14 @@ DECLARE_THREAD(dict_stats_thread)( break; } +#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG + if (srv_ibuf_disable_background_merge) { + usleep(100000); + os_event_reset(dict_stats_event); + continue; + } +#endif + dict_stats_process_entry_from_recalc_pool(); os_event_reset(dict_stats_event); diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 337716fd027..b05fc603c24 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1995, 2015, 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 @@ -5477,9 +5477,10 @@ _fil_io( space = fil_space_get_by_id(space_id); - /* If we are deleting a tablespace we don't allow any read - operations on that. However, we do allow write operations. */ - if (space == 0 || (type == OS_FILE_READ && space->stop_new_ops)) { + /* If we are deleting a tablespace we don't allow async read operations + on that. However, we do allow write and sync read operations */ + if (space == 0 + || (type == OS_FILE_READ && !sync && space->stop_new_ops)) { mutex_exit(&fil_system->mutex); ib_logf(IB_LOG_LEVEL_ERROR, diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 439b9aaac27..4ad637d57d3 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1173,6 +1173,17 @@ innobase_end( handlerton* hton, /* in: Innodb handlerton */ ha_panic_function type); +#if NOT_USED +/*****************************************************************//** +Stores the current binlog coordinates in the trx system header. */ +static +int +innobase_store_binlog_info( +/*=======================*/ + handlerton* hton, /*!< in: InnoDB handlerton */ + THD* thd); /*!< in: MySQL thread handle */ +#endif + /*****************************************************************//** Creates an InnoDB transaction struct for the thd if it does not yet have one. Starts a new InnoDB transaction if a transaction is not yet started. And @@ -3268,6 +3279,9 @@ innobase_init( innobase_hton->start_consistent_snapshot = innobase_start_trx_and_assign_read_view; + /*innobase_hton->store_binlog_info = + innobase_store_binlog_info;*/ + innobase_hton->flush_logs = innobase_flush_logs; innobase_hton->show_status = innobase_show_status; innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | @@ -3978,6 +3992,38 @@ innobase_commit_low( } } +#if NOT_USED +/*****************************************************************//** +Stores the current binlog coordinates in the trx system header. */ +static +int +innobase_store_binlog_info( +/*=======================*/ + handlerton* hton, /*!< in: InnoDB handlerton */ + THD* thd) /*!< in: MySQL thread handle */ + +{ + const char* file_name; + unsigned long long pos; + mtr_t mtr; + + DBUG_ENTER("innobase_store_binlog_info"); + + thd_binlog_pos(thd, &file_name, &pos); + + mtr_start(&mtr); + + trx_sys_update_mysql_binlog_offset(file_name, pos, + TRX_SYS_MYSQL_LOG_INFO, &mtr); + + mtr_commit(&mtr); + + innobase_flush_logs(hton); + + DBUG_RETURN(0); +} +#endif + /*****************************************************************//** Creates an InnoDB transaction struct for the thd if it does not yet have one. Starts a new InnoDB transaction if a transaction is not yet started. And @@ -9571,7 +9617,8 @@ create_table_def( /* MySQL does the name length check. But we do additional check on the name length here */ - if (strlen(table_name) > MAX_FULL_NAME_LEN) { + const size_t table_name_len = strlen(table_name); + if (table_name_len > MAX_FULL_NAME_LEN) { push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, ER_TABLE_NAME, @@ -9580,6 +9627,15 @@ create_table_def( DBUG_RETURN(ER_TABLE_NAME); } + if (table_name[table_name_len - 1] == '/') { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + ER_TABLE_NAME, + "InnoDB: Table name is empty"); + + DBUG_RETURN(ER_WRONG_TABLE_NAME); + } + n_cols = form->s->fields; s_cols = form->s->stored_fields; @@ -10894,6 +10950,10 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(HA_ERR_TABLE_READONLY); } + if (UNIV_UNLIKELY(prebuilt->trx->fake_changes)) { + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } + dict_table = prebuilt->table; if (dict_table->space == TRX_SYS_SPACE) { @@ -12590,8 +12650,8 @@ ha_innobase::check( my_error(ER_QUERY_INTERRUPTED, MYF(0)); } - if (UNIV_UNLIKELY(share->ib_table->is_corrupt)) { - return(HA_ADMIN_CORRUPT); + if (UNIV_UNLIKELY(prebuilt->table && prebuilt->table->corrupted)) { + DBUG_RETURN(HA_ADMIN_CORRUPT); } DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); @@ -15083,6 +15143,9 @@ innodb_log_archive_update( void* var_ptr, const void* save) { + if (srv_read_only_mode) + return; + my_bool in_val = *static_cast<const my_bool*>(save); if (in_val) { diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index d8cadfb6891..c3df05aafbb 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2015, 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 @@ -29,6 +29,7 @@ Smart ALTER TABLE #include <innodb_priv.h> #include <sql_alter.h> #include <sql_class.h> +#include <sql_table.h> #include "dict0crea.h" #include "dict0dict.h" @@ -529,12 +530,9 @@ ha_innobase::check_if_supported_inplace_alter( } else if (((ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) || innobase_need_rebuild(ha_alter_info)) - && (innobase_fulltext_exist(altered_table) - || (prebuilt->table->flags2 - & DICT_TF2_FTS_HAS_DOC_ID))) { + && (innobase_fulltext_exist(altered_table))) { /* Refuse to rebuild the table online, if - fulltext indexes are to survive the rebuild, - or if the table contains a hidden FTS_DOC_ID column. */ + fulltext indexes are to survive the rebuild. */ online = false; /* If the table already contains fulltext indexes, refuse to rebuild the table natively altogether. */ @@ -892,10 +890,8 @@ innobase_get_foreign_key_info( char* tbl_namep = NULL; ulint db_name_len = 0; ulint tbl_name_len = 0; -#ifdef __WIN__ char db_name[MAX_DATABASE_NAME_LEN]; char tbl_name[MAX_TABLE_NAME_LEN]; -#endif fk_key = static_cast<Foreign_key*>(key); @@ -948,24 +944,29 @@ innobase_get_foreign_key_info( add_fk[num_fk] = dict_mem_foreign_create(); #ifndef __WIN__ - tbl_namep = fk_key->ref_table.str; - tbl_name_len = fk_key->ref_table.length; - db_namep = fk_key->ref_db.str; - db_name_len = fk_key->ref_db.length; + if(fk_key->ref_db.str) { + tablename_to_filename(fk_key->ref_db.str, db_name, + MAX_DATABASE_NAME_LEN); + db_namep = db_name; + db_name_len = strlen(db_name); + } + if (fk_key->ref_table.str) { + tablename_to_filename(fk_key->ref_table.str, tbl_name, + MAX_TABLE_NAME_LEN); + tbl_namep = tbl_name; + tbl_name_len = strlen(tbl_name); + } #else ut_ad(fk_key->ref_table.str); - - memcpy(tbl_name, fk_key->ref_table.str, - fk_key->ref_table.length); - tbl_name[fk_key->ref_table.length] = 0; + tablename_to_filename(fk_key->ref_table.str, tbl_name, + MAX_TABLE_NAME_LEN); innobase_casedn_str(tbl_name); tbl_name_len = strlen(tbl_name); tbl_namep = &tbl_name[0]; if (fk_key->ref_db.str != NULL) { - memcpy(db_name, fk_key->ref_db.str, - fk_key->ref_db.length); - db_name[fk_key->ref_db.length] = 0; + tablename_to_filename(fk_key->ref_db.str, db_name, + MAX_DATABASE_NAME_LEN); innobase_casedn_str(db_name); db_name_len = strlen(db_name); db_namep = &db_name[0]; @@ -3316,58 +3317,74 @@ innobase_check_foreign_key_index( ulint n_drop_fk) /*!< in: Number of foreign keys to drop */ { - dict_foreign_t* foreign; + ut_ad(index != NULL); + ut_ad(indexed_table != NULL); - /* Check if the index is referenced. */ - foreign = dict_table_get_referenced_constraint(indexed_table, index); - - ut_ad(!foreign || indexed_table - == foreign->referenced_table); - - if (foreign - && !dict_foreign_find_index( - indexed_table, col_names, - foreign->referenced_col_names, - foreign->n_fields, index, - /*check_charsets=*/TRUE, - /*check_null=*/FALSE, NULL, NULL, NULL) - && !innobase_find_equiv_index( - foreign->referenced_col_names, - foreign->n_fields, - ha_alter_info->key_info_buffer, - ha_alter_info->index_add_buffer, - ha_alter_info->index_add_count) - ) { - trx->error_info = index; - return(true); + const dict_foreign_set* fks = &indexed_table->referenced_set; + + /* Check for all FK references from other tables to the index. */ + for (dict_foreign_set::const_iterator it = fks->begin(); + it != fks->end(); ++it) { + + dict_foreign_t* foreign = *it; + if (foreign->referenced_index != index) { + continue; + } + ut_ad(indexed_table == foreign->referenced_table); + + if (NULL == dict_foreign_find_index( + indexed_table, col_names, + foreign->referenced_col_names, + foreign->n_fields, index, + /*check_charsets=*/TRUE, + /*check_null=*/FALSE, + 0,0,0) + && NULL == innobase_find_equiv_index( + foreign->referenced_col_names, + foreign->n_fields, + ha_alter_info->key_info_buffer, + ha_alter_info->index_add_buffer, + ha_alter_info->index_add_count)) { + + /* Index cannot be dropped. */ + trx->error_info = index; + return(true); + } } - /* Check if this index references some - other table */ - foreign = dict_table_get_foreign_constraint( - indexed_table, index); - - ut_ad(!foreign || indexed_table - == foreign->foreign_table); - - if (foreign - && !innobase_dropping_foreign( - foreign, drop_fk, n_drop_fk) - && !dict_foreign_find_index( - indexed_table, col_names, - foreign->foreign_col_names, - foreign->n_fields, index, - /*check_charsets=*/TRUE, - /*check_null=*/FALSE, NULL,NULL, NULL) - && !innobase_find_equiv_index( - foreign->foreign_col_names, - foreign->n_fields, - ha_alter_info->key_info_buffer, - ha_alter_info->index_add_buffer, - ha_alter_info->index_add_count) - ) { - trx->error_info = index; - return(true); + fks = &indexed_table->foreign_set; + + /* Check for all FK references in current table using the index. */ + for (dict_foreign_set::const_iterator it = fks->begin(); + it != fks->end(); ++it) { + + dict_foreign_t* foreign = *it; + if (foreign->foreign_index != index) { + continue; + } + + ut_ad(indexed_table == foreign->foreign_table); + + if (!innobase_dropping_foreign( + foreign, drop_fk, n_drop_fk) + && NULL == dict_foreign_find_index( + indexed_table, col_names, + foreign->foreign_col_names, + foreign->n_fields, index, + /*check_charsets=*/TRUE, + /*check_null=*/FALSE, + 0, 0, 0) + && NULL == innobase_find_equiv_index( + foreign->foreign_col_names, + foreign->n_fields, + ha_alter_info->key_info_buffer, + ha_alter_info->index_add_buffer, + ha_alter_info->index_add_count)) { + + /* Index cannot be dropped. */ + trx->error_info = index; + return(true); + } } return(false); @@ -3590,6 +3607,19 @@ check_if_ok_to_rename: if (index->type & DICT_FTS) { DBUG_ASSERT(index->type == DICT_FTS || (index->type & DICT_CORRUPT)); + + /* We need to drop any corrupted fts indexes + before we add a new fts index. */ + if (add_fts_idx && index->type & DICT_CORRUPT) { + ib_errf(user_thd, IB_LOG_LEVEL_ERROR, + ER_INNODB_INDEX_CORRUPT, + "Fulltext index '%s' is corrupt. " + "you should drop this index first.", + index->name); + + goto err_exit_no_heap; + } + continue; } diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index 972208c51bd..19521d362ed 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -2734,7 +2734,9 @@ ibuf_merge_space( &pages[0], &spaces[0], &versions[0], n_pages, &mtr); - ++sum_sizes; + if (*n_pages > 0) { + ++sum_sizes; + } } ibuf_mtr_commit(&mtr); diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index ce70e936e6e..5643892bffc 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -433,18 +433,6 @@ dict_foreign_add_to_cache( /*!< in: error to be ignored */ __attribute__((nonnull(1), warn_unused_result)); /*********************************************************************//** -Check if the index is referenced by a foreign key, if TRUE return the -matching instance NULL otherwise. -@return pointer to foreign key struct if index is defined for foreign -key, otherwise NULL */ -UNIV_INTERN -dict_foreign_t* -dict_table_get_referenced_constraint( -/*=================================*/ - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index) /*!< in: InnoDB index */ - __attribute__((nonnull, warn_unused_result)); -/*********************************************************************//** Checks if a table is referenced by foreign keys. @return TRUE if table is referenced by a foreign key */ UNIV_INTERN @@ -479,19 +467,6 @@ dict_str_starts_with_keyword( const char* keyword) /*!< in: keyword to look for */ __attribute__((nonnull, warn_unused_result)); /*********************************************************************//** -Checks if a index is defined for a foreign key constraint. Index is a part -of a foreign key constraint if the index is referenced by foreign key -or index is a foreign key index -@return pointer to foreign key struct if index is defined for foreign -key, otherwise NULL */ -UNIV_INTERN -dict_foreign_t* -dict_table_get_foreign_constraint( -/*==============================*/ - dict_table_t* table, /*!< in: InnoDB table */ - dict_index_t* index) /*!< in: InnoDB index */ - __attribute__((nonnull, warn_unused_result)); -/*********************************************************************//** Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after the indexes for a table have been created. diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index 6bfd7f6cdae..753f10aba86 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, 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 diff --git a/storage/xtradb/include/fts0fts.h b/storage/xtradb/include/fts0fts.h index a2996ecacc8..d54ed281d9a 100644 --- a/storage/xtradb/include/fts0fts.h +++ b/storage/xtradb/include/fts0fts.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2015, 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 diff --git a/storage/xtradb/include/row0purge.h b/storage/xtradb/include/row0purge.h index 93dcf9cf49b..888289a6c79 100644 --- a/storage/xtradb/include/row0purge.h +++ b/storage/xtradb/include/row0purge.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2015, 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 @@ -119,6 +119,16 @@ struct purge_node_t{ clustered index record */ ibool done; /* Debug flag */ +#ifdef UNIV_DEBUG + /***********************************************************//** + Validate the persisent cursor. The purge node has two references + to the clustered index record - one via the ref member, and the + other via the persistent cursor. These two references must match + each other if the found_clust flag is set. + @return true if the persistent cursor is consistent with + the ref member.*/ + bool validate_pcur(); +#endif }; #ifndef UNIV_NONINL diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 1db6bd85edd..c9394647fef 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -44,10 +44,10 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 25 +#define INNODB_VERSION_BUGFIX 26 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 73.1 +#define PERCONA_INNODB_VERSION 74.0 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index 1ff00dbcb8c..73551fd72f2 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -3343,6 +3343,7 @@ ulint log_archive_noarchivelog(void) /*==========================*/ { + ut_ad(!srv_read_only_mode); loop: mutex_enter(&(log_sys->mutex)); @@ -3375,6 +3376,8 @@ ulint log_archive_archivelog(void) /*========================*/ { + ut_ad(!srv_read_only_mode); + mutex_enter(&(log_sys->mutex)); if (log_sys->archiving_state == LOG_ARCH_OFF) { diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 41cbe3f119f..ea10c6f2b75 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -1485,6 +1485,7 @@ os_file_create_simple_no_error_handling_func( *success = (file != INVALID_HANDLE_VALUE); #else /* __WIN__ */ int create_flag; + const char* mode_str = NULL; ut_a(name); @@ -1493,6 +1494,8 @@ os_file_create_simple_no_error_handling_func( if (create_mode == OS_FILE_OPEN) { + mode_str = "OPEN"; + if (access_type == OS_FILE_READ_ONLY) { create_flag = O_RDONLY; @@ -1511,10 +1514,14 @@ os_file_create_simple_no_error_handling_func( } else if (srv_read_only_mode) { + mode_str = "OPEN"; + create_flag = O_RDONLY; } else if (create_mode == OS_FILE_CREATE) { + mode_str = "CREATE"; + create_flag = O_RDWR | O_CREAT | O_EXCL; } else { @@ -1529,6 +1536,17 @@ os_file_create_simple_no_error_handling_func( *success = file == -1 ? FALSE : TRUE; + /* This function is always called for data files, we should disable + OS caching (O_DIRECT) here as we do in os_file_create_func(), so + we open the same file in the same mode, see man page of open(2). */ + if (!srv_read_only_mode + && *success + && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT + || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) { + + os_file_set_nocache(file, name, mode_str); + } + #ifdef USE_FILE_LOCK if (!srv_read_only_mode && *success diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index c513320afc1..fc1a72b5695 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2015, 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 @@ -139,14 +139,6 @@ struct row_import { ulint find_col(const char* name) const UNIV_NOTHROW; /** - Find the index field entry in in the cfg indexes fields. - @name - of the index to look for - @return instance if found else 0. */ - const dict_field_t* find_field( - const row_index_t* cfg_index, - const char* name) const UNIV_NOTHROW; - - /** Get the number of rows for which purge failed during the convert phase. @param name - index name @return number of rows for which purge failed. */ @@ -1141,30 +1133,6 @@ row_import::find_col( } /** -Find the index field entry in in the cfg indexes fields. -@name - of the index to look for -@return instance if found else 0. */ -const dict_field_t* -row_import::find_field( - const row_index_t* cfg_index, - const char* name) const UNIV_NOTHROW -{ - const dict_field_t* field = cfg_index->m_fields; - - for (ulint i = 0; i < cfg_index->m_n_fields; ++i, ++field) { - const char* field_name; - - field_name = reinterpret_cast<const char*>(field->name); - - if (strcmp(field_name, name) == 0) { - return(field); - } - } - - return(0); -} - -/** Check if the index schema that was read from the .cfg file matches the in memory index definition. @return DB_SUCCESS or error code. */ @@ -1187,51 +1155,60 @@ row_import::match_index_columns( return(DB_ERROR); } - cfg_index->m_srv_index = index; + if (cfg_index->m_n_fields != index->n_fields) { - const dict_field_t* field = index->fields; + ib_errf(thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Index field count %lu doesn't match" + " tablespace metadata file value %lu", + (ulong) index->n_fields, + (ulong) cfg_index->m_n_fields); - for (ulint i = 0; i < index->n_fields; ++i, ++field) { + return(DB_ERROR); + } - const dict_field_t* cfg_field; + cfg_index->m_srv_index = index; - cfg_field = find_field(cfg_index, field->name); + const dict_field_t* field = index->fields; + const dict_field_t* cfg_field = cfg_index->m_fields; - if (cfg_field == 0) { + for (ulint i = 0; i < index->n_fields; ++i, ++field, ++cfg_field) { + + if (strcmp(field->name, cfg_field->name) != 0) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s not found in tablespace " - "meta-data file.", - index->name, field->name); + "Index field name %s doesn't match" + " tablespace metadata field name %s" + " for field position %lu", + field->name, cfg_field->name, (ulong) i); err = DB_ERROR; - } else { + } - if (cfg_field->prefix_len != field->prefix_len) { - ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s prefix len %lu " - "doesn't match meta-data file value " - "%lu", - index->name, field->name, - (ulong) field->prefix_len, - (ulong) cfg_field->prefix_len); + if (cfg_field->prefix_len != field->prefix_len) { + ib_errf(thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s prefix len %lu" + " doesn't match metadata file value" + " %lu", + index->name, field->name, + (ulong) field->prefix_len, + (ulong) cfg_field->prefix_len); - err = DB_ERROR; - } + err = DB_ERROR; + } - if (cfg_field->fixed_len != field->fixed_len) { - ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Index %s field %s fixed len %lu " - "doesn't match meta-data file value " - "%lu", - index->name, field->name, - (ulong) field->fixed_len, - (ulong) cfg_field->fixed_len); + if (cfg_field->fixed_len != field->fixed_len) { + ib_errf(thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Index %s field %s fixed len %lu" + " doesn't match metadata file value" + " %lu", + index->name, field->name, + (ulong) field->fixed_len, + (ulong) cfg_field->fixed_len); - err = DB_ERROR; - } + err = DB_ERROR; } } diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index 6fa71c50d96..75ef74bda35 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2015, 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 @@ -2327,24 +2327,34 @@ row_ins_clust_index_entry_low( big_rec_t* big_rec = NULL; mtr_t mtr; mem_heap_t* offsets_heap = NULL; + ulint search_mode; ut_ad(dict_index_is_clust(index)); ut_ad(!dict_index_is_unique(index) || n_uniq == dict_index_get_n_unique(index)); ut_ad(!n_uniq || n_uniq == dict_index_get_n_unique(index)); + /* If running with fake_changes mode on then switch from modify to + search so that code takes only s-latch and not x-latch. + For dry-run (fake-changes) s-latch is acceptable. Taking x-latch will + make it more restrictive and will block real changes/workflow. */ + if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) { + search_mode = (mode & BTR_MODIFY_TREE) + ? BTR_SEARCH_TREE : BTR_SEARCH_LEAF; + } else { + search_mode = mode; + } + mtr_start_trx(&mtr, thr_get_trx(thr)); if (mode == BTR_MODIFY_LEAF && dict_index_is_online_ddl(index)) { - if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) { - mode = BTR_SEARCH_LEAF | BTR_ALREADY_S_LATCHED; - } else { - mode = BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED; - } + + /* We really don't need to OR mode but will leave it for + code consistency. */ + mode |= BTR_ALREADY_S_LATCHED; + search_mode |= BTR_ALREADY_S_LATCHED; + mtr_s_lock(dict_index_get_lock(index), &mtr); - } else if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) { - mode = (mode & BTR_MODIFY_TREE) - ? BTR_SEARCH_TREE : BTR_SEARCH_LEAF; } cursor.thr = thr; @@ -2353,7 +2363,7 @@ row_ins_clust_index_entry_low( the function will return in both low_match and up_match of the cursor sensible values */ - btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, mode, + btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, search_mode, &cursor, 0, __FILE__, __LINE__, &mtr); #ifdef UNIV_DEBUG @@ -2625,7 +2635,7 @@ row_ins_sec_index_entry_low( que_thr_t* thr) /*!< in: query thread */ { btr_cur_t cursor; - ulint search_mode = mode | BTR_INSERT; + ulint search_mode; dberr_t err = DB_SUCCESS; ulint n_unique; mtr_t mtr; @@ -2639,6 +2649,18 @@ row_ins_sec_index_entry_low( ut_ad(thr_get_trx(thr)->id); mtr_start_trx(&mtr, trx); + /* If running with fake_changes mode on then avoid using insert buffer + and also switch from modify to search so that code takes only s-latch + and not x-latch. For dry-run (fake-changes) s-latch is acceptable. + Taking x-latch will make it more restrictive and will block real + changes/workflow. */ + if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) { + search_mode = (mode & BTR_MODIFY_TREE) + ? BTR_SEARCH_TREE : BTR_SEARCH_LEAF; + } else { + search_mode = mode | BTR_INSERT; + } + /* Ensure that we acquire index->lock when inserting into an index with index->online_status == ONLINE_INDEX_COMPLETE, but could still be subject to rollback_inplace_alter_table(). @@ -2646,11 +2668,24 @@ row_ins_sec_index_entry_low( The memory object cannot be freed as long as we have an open reference to the table, or index->table->n_ref_count > 0. */ const bool check = *index->name == TEMP_INDEX_PREFIX; + if (check) { + DEBUG_SYNC_C("row_ins_sec_index_enter"); - if (mode == BTR_MODIFY_LEAF) { + + /* mode = MODIFY_LEAF is synonymous to search_mode = SEARCH_LEAF + search_mode = SEARCH_TREE suggest operation in fake_change mode + so continue to s-latch in this mode too. */ + + if (mode == BTR_MODIFY_LEAF || search_mode == BTR_SEARCH_TREE) { + + ut_ad((search_mode == BTR_SEARCH_TREE + && thr_get_trx(thr)->fake_changes) + || mode == BTR_MODIFY_LEAF); + search_mode |= BTR_ALREADY_S_LATCHED; mtr_s_lock(dict_index_get_lock(index), &mtr); + } else { mtr_x_lock(dict_index_get_lock(index), &mtr); } @@ -2661,14 +2696,13 @@ row_ins_sec_index_entry_low( } } - /* Note that we use PAGE_CUR_LE as the search mode, because then - the function will return in both low_match and up_match of the - cursor sensible values */ - if (!thr_get_trx(thr)->check_unique_secondary) { search_mode |= BTR_IGNORE_SEC_UNIQUE; } + /* Note that we use PAGE_CUR_LE as the search mode, because then + the function will return in both low_match and up_match of the + cursor sensible values */ btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE, search_mode, &cursor, 0, __FILE__, __LINE__, &mtr); @@ -2748,10 +2782,7 @@ row_ins_sec_index_entry_low( btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_LE, - UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes) - ? BTR_SEARCH_LEAF - : (btr_latch_mode) - (search_mode & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)), + search_mode & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE), &cursor, 0, __FILE__, __LINE__, &mtr); } diff --git a/storage/xtradb/row/row0purge.cc b/storage/xtradb/row/row0purge.cc index 8212a7b43e0..b26ba971a95 100644 --- a/storage/xtradb/row/row0purge.cc +++ b/storage/xtradb/row/row0purge.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2015, 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 @@ -84,7 +84,7 @@ row_purge_node_create( /***********************************************************//** Repositions the pcur in the purge node on the clustered index record, -if found. +if found. If the record is not found, close pcur. @return TRUE if the record was found */ static ibool @@ -95,11 +95,10 @@ row_purge_reposition_pcur( mtr_t* mtr) /*!< in: mtr */ { if (node->found_clust) { - ibool found; + ut_ad(node->validate_pcur()); - found = btr_pcur_restore_position(mode, &node->pcur, mtr); + node->found_clust = btr_pcur_restore_position(mode, &node->pcur, mtr); - return(found); } else { node->found_clust = row_search_on_row_ref( &node->pcur, mode, node->table, node->ref, mtr); @@ -109,6 +108,11 @@ row_purge_reposition_pcur( } } + /* Close the current cursor if we fail to position it correctly. */ + if (!node->found_clust) { + btr_pcur_close(&node->pcur); + } + return(node->found_clust); } @@ -182,7 +186,12 @@ func_exit: mem_heap_free(heap); } - btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + /* Persistent cursor is closed if reposition fails. */ + if (node->found_clust) { + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + } else { + mtr_commit(&mtr); + } return(success); } @@ -251,7 +260,12 @@ row_purge_poss_sec( btr_pcur_get_rec(&node->pcur), &mtr, index, entry); - btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + /* Persistent cursor is closed if reposition fails. */ + if (node->found_clust) { + btr_pcur_commit_specify_mtr(&node->pcur, &mtr); + } else { + mtr_commit(&mtr); + } return(can_delete); } @@ -831,6 +845,8 @@ row_purge_record_func( dict_index_t* clust_index; bool purged = true; + ut_ad(!node->found_clust); + clust_index = dict_table_get_first_index(node->table); node->index = dict_table_get_next_index(clust_index); @@ -986,3 +1002,52 @@ row_purge_step( return(thr); } + +#ifdef UNIV_DEBUG +/***********************************************************//** +Validate the persisent cursor. The purge node has two references +to the clustered index record - one via the ref member, and the +other via the persistent cursor. These two references must match +each other if the found_clust flag is set. +@return true if the stored copy of persistent cursor is consistent +with the ref member.*/ +bool +purge_node_t::validate_pcur() +{ + if (!found_clust) { + return(true); + } + + if (index == NULL) { + return(true); + } + + if (index->type == DICT_FTS) { + return(true); + } + + if (pcur.old_stored != BTR_PCUR_OLD_STORED) { + return(true); + } + + dict_index_t* clust_index = pcur.btr_cur.index; + + ulint* offsets = rec_get_offsets( + pcur.old_rec, clust_index, NULL, pcur.old_n_fields, &heap); + + /* Here we are comparing the purge ref record and the stored initial + part in persistent cursor. Both cases we store n_uniq fields of the + cluster index and so it is fine to do the comparison. We note this + dependency here as pcur and ref belong to different modules. */ + int st = cmp_dtuple_rec(ref, pcur.old_rec, offsets); + + if (st != 0) { + fprintf(stderr, "Purge node pcur validation failed\n"); + dtuple_print(stderr, ref); + rec_print(stderr, pcur.old_rec, clust_index); + return(false); + } + + return(true); +} +#endif /* UNIV_DEBUG */ diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 6c7796e3ee6..457e8361331 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 303985cdae2..e679e180d45 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -2209,8 +2209,7 @@ rescan_idle: mutex_enter(&trx_sys->mutex); trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list); while (trx) { - if (!trx_state_eq(trx, TRX_STATE_NOT_STARTED) - && trx_state_eq(trx, TRX_STATE_ACTIVE) + if (trx->state == TRX_STATE_ACTIVE && trx->mysql_thd && innobase_thd_is_idle(trx->mysql_thd)) { ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd); diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 1dd09b9e294..f28e578111b 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -2706,24 +2706,25 @@ files_checked: } #ifdef UNIV_LOG_ARCHIVE - /* Archiving is always off under MySQL */ - if (!srv_log_archive_on) { - ut_a(DB_SUCCESS == log_archive_noarchivelog()); - } else { - bool start_archive; + if (!srv_read_only_mode) { + if (!srv_log_archive_on) { + ut_a(DB_SUCCESS == log_archive_noarchivelog()); + } else { + bool start_archive; - mutex_enter(&(log_sys->mutex)); + mutex_enter(&(log_sys->mutex)); - start_archive = FALSE; + start_archive = false; - if (log_sys->archiving_state == LOG_ARCH_OFF) { - start_archive = TRUE; - } + if (log_sys->archiving_state == LOG_ARCH_OFF) { + start_archive = true; + } - mutex_exit(&(log_sys->mutex)); + mutex_exit(&(log_sys->mutex)); - if (start_archive) { - ut_a(DB_SUCCESS == log_archive_archivelog()); + if (start_archive) { + ut_a(DB_SUCCESS == log_archive_archivelog()); + } } } #endif /* UNIV_LOG_ARCHIVE */ |