diff options
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 51 | ||||
-rw-r--r-- | storage/innobase/buf/buf0lru.cc | 8 | ||||
-rw-r--r-- | storage/innobase/fil/fil0crypt.cc | 49 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 54 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 99 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 2 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 2 | ||||
-rw-r--r-- | storage/innobase/include/btr0pcur.h | 10 | ||||
-rw-r--r-- | storage/innobase/include/btr0pcur.ic | 20 | ||||
-rw-r--r-- | storage/innobase/include/buf0lru.h | 6 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 24 | ||||
-rw-r--r-- | storage/innobase/include/log0recv.h | 5 | ||||
-rw-r--r-- | storage/innobase/include/ut0dbg.h | 6 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 26 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 16 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 58 |
16 files changed, 256 insertions, 180 deletions
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index cbbfb181f24..a03c0083320 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -4424,6 +4424,11 @@ loop: return (NULL); } + if (local_err == DB_PAGE_CORRUPTED + && srv_force_recovery) { + return NULL; + } + /* Try to set table as corrupted instead of asserting. */ if (page_id.space() == TRX_SYS_SPACE) { @@ -5790,10 +5795,27 @@ buf_page_monitor( } /** Mark a table corrupted. +Also remove the bpage from LRU list. +@param[in] bpage Corrupted page. */ +static void buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t* space) +{ + /* If block is not encrypted find the table with specified + space id, and mark it corrupted. Encrypted tables + are marked unusable later e.g. in ::open(). */ + if (!bpage->encrypted) { + dict_set_corrupted_by_space(space); + } else { + dict_set_encrypted_by_space(space); + } +} + +/** Mark a table corrupted. +@param[in] bpage Corrupted page +@param[in] space Corrupted page belongs to tablespace Also remove the bpage from LRU list. */ static void -buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t* space) +buf_corrupt_page_release(buf_page_t* bpage, const fil_space_t* space) { buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); const ibool uncompressed = (buf_page_get_state(bpage) @@ -5817,13 +5839,8 @@ buf_mark_space_corrupt(buf_page_t* bpage, const fil_space_t* space) mutex_exit(buf_page_get_mutex(bpage)); - /* If block is not encrypted find the table with specified - space id, and mark it corrupted. Encrypted tables - are marked unusable later e.g. in ::open(). */ - if (!bpage->encrypted) { - dict_set_corrupted_by_space(space); - } else { - dict_set_encrypted_by_space(space); + if (!srv_force_recovery) { + buf_mark_space_corrupt(bpage, space); } /* After this point bpage can't be referenced. */ @@ -6025,7 +6042,7 @@ database_corrupted: "buf_page_import_corrupt_failure", if (!is_predefined_tablespace( bpage->id.space())) { - buf_mark_space_corrupt(bpage, space); + buf_corrupt_page_release(bpage, space); ib::info() << "Simulated IMPORT " "corruption"; space->release_for_io(); @@ -6059,7 +6076,7 @@ database_corrupted: << FORCE_RECOVERY_MSG; } - if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) { + if (!srv_force_recovery) { /* If page space id is larger than TRX_SYS_SPACE (0), we will attempt to mark the corresponding @@ -6069,7 +6086,7 @@ database_corrupted: " a corrupt database page."; } - buf_mark_space_corrupt(bpage, space); + buf_corrupt_page_release(bpage, space); space->release_for_io(); return(err); } @@ -6078,6 +6095,18 @@ database_corrupted: DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", page_not_corrupt: bpage = bpage; ); + if (err == DB_PAGE_CORRUPTED + || err == DB_DECRYPTION_FAILED) { + buf_corrupt_page_release(bpage, space); + + if (recv_recovery_is_on()) { + recv_recover_corrupt_page(bpage); + } + + space->release_for_io(); + return err; + } + if (recv_recovery_is_on()) { recv_recover_page(bpage); } diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index b3114a4cb47..c00dd414aa6 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -2204,8 +2204,8 @@ buf_LRU_old_ratio_update_instance( buf_pool_t* buf_pool,/*!< in: buffer pool instance */ uint old_pct,/*!< in: Reserve this percentage of the buffer pool for "old" blocks. */ - ibool adjust) /*!< in: TRUE=adjust the LRU list; - FALSE=just assign buf_pool->LRU_old_ratio + bool adjust) /*!< in: true=adjust the LRU list; + false=just assign buf_pool->LRU_old_ratio during the initialization of InnoDB */ { uint ratio; @@ -2247,8 +2247,8 @@ buf_LRU_old_ratio_update( /*=====================*/ uint old_pct,/*!< in: Reserve this percentage of the buffer pool for "old" blocks. */ - ibool adjust) /*!< in: TRUE=adjust the LRU list; - FALSE=just assign buf_pool->LRU_old_ratio + bool adjust) /*!< in: true=adjust the LRU list; + false=just assign buf_pool->LRU_old_ratio during the initialization of InnoDB */ { uint new_ratio = 0; diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 606c59301ea..8eb4b0b12a6 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -942,14 +942,10 @@ fil_crypt_read_crypt_data(fil_space_t* space) mtr.commit(); } -/*********************************************************************** -Start encrypting a space +/** Start encrypting a space @param[in,out] space Tablespace -@return true if a recheck is needed */ -static -bool -fil_crypt_start_encrypting_space( - fil_space_t* space) +@return true if a recheck of tablespace is needed by encryption thread. */ +static bool fil_crypt_start_encrypting_space(fil_space_t* space) { bool recheck = false; @@ -1407,14 +1403,12 @@ fil_crypt_return_iops( fil_crypt_update_total_stat(state); } -/*********************************************************************** -Search for a space needing rotation -@param[in,out] key_state Key state -@param[in,out] state Rotation state -@param[in,out] recheck recheck ? */ -static -bool -fil_crypt_find_space_to_rotate( +/** Search for a space needing rotation +@param[in,out] key_state Key state +@param[in,out] state Rotation state +@param[in,out] recheck recheck of the tablespace is needed or + still encryption thread does write page 0 */ +static bool fil_crypt_find_space_to_rotate( key_state_t* key_state, rotate_thread_t* state, bool* recheck) @@ -1444,11 +1438,10 @@ fil_crypt_find_space_to_rotate( /* If key rotation is enabled (default) we iterate all tablespaces. If key rotation is not enabled we iterate only the tablespaces added to keyrotation list. */ - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_space_keyrotate_next(state->space); - } + state->space = srv_fil_crypt_rotate_key_age + ? fil_space_next(state->space) + : fil_system.keyrotate_next(state->space, *recheck, + key_state->key_version); while (!state->should_shutdown() && state->space) { /* If there is no crypt data and we have not yet read @@ -1466,11 +1459,10 @@ fil_crypt_find_space_to_rotate( return true; } - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_space_keyrotate_next(state->space); - } + state->space = srv_fil_crypt_rotate_key_age + ? fil_space_next(state->space) + : fil_system.keyrotate_next(state->space, *recheck, + key_state->key_version); } /* if we didn't find any space return iops */ @@ -2095,13 +2087,8 @@ A thread which monitors global key state and rotates tablespaces accordingly @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(fil_crypt_thread)( -/*=============================*/ - void* arg __attribute__((unused))) /*!< in: a dummy parameter required - * by os_thread_create */ +DECLARE_THREAD(fil_crypt_thread)(void*) { - UT_NOT_USED(arg); - mutex_enter(&fil_crypt_threads_mutex); uint thread_no = srv_n_fil_crypt_threads_started; srv_n_fil_crypt_threads_started++; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 76b325c61fb..9fb9e1a4138 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -5216,25 +5216,29 @@ fil_space_t::acquire() and fil_space_t::release() are invoked here which blocks a concurrent operation from dropping the tablespace. @param[in] prev_space Pointer to the previous fil_space_t. If NULL, use the first fil_space_t on fil_system.space_list. +@param[in] recheck recheck of the tablespace is needed or + still encryption thread does write page0 for it +@param[in] key_version key version of the key state thread @return pointer to the next fil_space_t. -@retval NULL if this was the last*/ +@retval NULL if this was the last */ fil_space_t* -fil_space_keyrotate_next( - fil_space_t* prev_space) +fil_system_t::keyrotate_next( + fil_space_t* prev_space, + bool recheck, + uint key_version) { - fil_space_t* space = prev_space; - fil_space_t* old = NULL; - mutex_enter(&fil_system.mutex); - if (UT_LIST_GET_LEN(fil_system.rotation_list) == 0) { - if (space) { - space->release(); - fil_space_remove_from_keyrotation(space); - } - mutex_exit(&fil_system.mutex); - return(NULL); - } + /* If one of the encryption threads already started the encryption + of the table then don't remove the unencrypted spaces from + rotation list + + If there is a change in innodb_encrypt_tables variables value then + don't remove the last processed tablespace from the rotation list. */ + const bool remove = ((!recheck || prev_space->crypt_data) + && (!key_version == !srv_encrypt_tables)); + + fil_space_t* space = prev_space; if (prev_space == NULL) { space = UT_LIST_GET_FIRST(fil_system.rotation_list); @@ -5245,22 +5249,17 @@ fil_space_keyrotate_next( /* Move on to the next fil_space_t */ space->release(); - old = space; space = UT_LIST_GET_NEXT(rotation_list, space); - fil_space_remove_from_keyrotation(old); - } - - /* Skip spaces that are being created by fil_ibd_create(), - or dropped. Note that rotation_list contains only - space->purpose == FIL_TYPE_TABLESPACE. */ - while (space != NULL - && (UT_LIST_GET_LEN(space->chain) == 0 - || space->is_stopping())) { + while (space != NULL + && (UT_LIST_GET_LEN(space->chain) == 0 + || space->is_stopping())) { + space = UT_LIST_GET_NEXT(rotation_list, space); + } - old = space; - space = UT_LIST_GET_NEXT(rotation_list, space); - fil_space_remove_from_keyrotation(old); + if (remove) { + fil_space_remove_from_keyrotation(prev_space); + } } if (space != NULL) { @@ -5268,7 +5267,6 @@ fil_space_keyrotate_next( } mutex_exit(&fil_system.mutex); - return(space); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 27d867c2d75..9976537be0a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -10853,7 +10853,6 @@ create_table_info_t::create_table_def() ulint binary_type; ulint long_true_varchar; ulint charset_no; - ulint j = 0; ulint doc_id_col = 0; ibool has_doc_id_col = FALSE; mem_heap_t* heap; @@ -10935,7 +10934,7 @@ create_table_info_t::create_table_def() heap = mem_heap_create(1000); - for (ulint i = 0; i < n_cols; i++) { + for (ulint i = 0, j = 0; j < n_cols; i++) { Field* field = m_form->field[i]; ulint vers_row = 0; @@ -11056,10 +11055,16 @@ err_col: dict_mem_table_add_s_col( table, 0); } + + if (is_virtual && omit_virtual) { + continue; + } + + j++; } if (num_v) { - for (ulint i = 0; i < n_cols; i++) { + for (ulint i = 0, j = 0; i < n_cols; i++) { dict_v_col_t* v_col; const Field* field = m_form->field[i]; @@ -12875,8 +12880,7 @@ inline int ha_innobase::delete_table(const char* name, enum_sql_command sqlcom) extension, in contrast to ::create */ normalize_table_name(norm_name, name); - if (srv_read_only_mode - || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) { + if (high_level_read_only) { DBUG_RETURN(HA_ERR_TABLE_READONLY); } @@ -13065,7 +13069,7 @@ innobase_drop_database( DBUG_ASSERT(hton == innodb_hton_ptr); - if (srv_read_only_mode) { + if (high_level_read_only) { return; } @@ -17361,11 +17365,13 @@ void innodb_adaptive_hash_index_update(THD*, st_mysql_sys_var*, void*, const void* save) { + mysql_mutex_unlock(&LOCK_global_system_variables); if (*(my_bool*) save) { btr_search_enable(); } else { btr_search_disable(true); } + mysql_mutex_lock(&LOCK_global_system_variables); } #endif /* BTR_CUR_HASH_ADAPT */ @@ -17379,7 +17385,9 @@ innodb_cmp_per_index_update(THD*, st_mysql_sys_var*, void*, const void* save) /* Reset the stats whenever we enable the table INFORMATION_SCHEMA.innodb_cmp_per_index. */ if (!srv_cmp_per_index_enabled && *(my_bool*) save) { + mysql_mutex_unlock(&LOCK_global_system_variables); page_zip_reset_stat_per_index(); + mysql_mutex_lock(&LOCK_global_system_variables); } srv_cmp_per_index_enabled = !!(*(my_bool*) save); @@ -17392,9 +17400,11 @@ static void innodb_old_blocks_pct_update(THD*, st_mysql_sys_var*, void*, const void* save) { - innobase_old_blocks_pct = static_cast<uint>( - buf_LRU_old_ratio_update( - *static_cast<const uint*>(save), TRUE)); + mysql_mutex_unlock(&LOCK_global_system_variables); + uint ratio = buf_LRU_old_ratio_update(*static_cast<const uint*>(save), + true); + mysql_mutex_lock(&LOCK_global_system_variables); + innobase_old_blocks_pct = ratio; } /****************************************************************//** @@ -17405,9 +17415,10 @@ void innodb_change_buffer_max_size_update(THD*, st_mysql_sys_var*, void*, const void* save) { - srv_change_buffer_max_size = - (*static_cast<const uint*>(save)); + srv_change_buffer_max_size = *static_cast<const uint*>(save); + mysql_mutex_unlock(&LOCK_global_system_variables); ibuf_max_size_update(srv_change_buffer_max_size); + mysql_mutex_lock(&LOCK_global_system_variables); } #ifdef UNIV_DEBUG @@ -17434,15 +17445,19 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save) { mtr_t mtr; ulong space_id = *static_cast<const ulong*>(save); + mysql_mutex_unlock(&LOCK_global_system_variables); fil_space_t* space = fil_space_acquire_silent(space_id); if (space == NULL) { +func_exit_no_space: + mysql_mutex_lock(&LOCK_global_system_variables); return; } if (srv_saved_page_number_debug >= space->size) { +func_exit: space->release(); - return; + goto func_exit_no_space; } mtr.start(); @@ -17463,7 +17478,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save) MLOG_2BYTES, &mtr); } mtr.commit(); - space->release(); + goto func_exit; } #endif // UNIV_DEBUG /*************************************************************//** @@ -17999,8 +18014,11 @@ innodb_buffer_pool_evict_update(THD*, st_mysql_sys_var*, void*, { if (const char* op = *static_cast<const char*const*>(save)) { if (!strcmp(op, "uncompressed")) { + mysql_mutex_unlock(&LOCK_global_system_variables); for (uint tries = 0; tries < 10000; tries++) { if (innodb_buffer_pool_evict_uncompressed()) { + mysql_mutex_lock( + &LOCK_global_system_variables); return; } @@ -18274,6 +18292,8 @@ void checkpoint_now_set(THD*, st_mysql_sys_var*, void*, const void* save) { if (*(my_bool*) save) { + mysql_mutex_unlock(&LOCK_global_system_variables); + while (log_sys.last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT + (log_sys.append_on_checkpoint != NULL @@ -18288,6 +18308,8 @@ checkpoint_now_set(THD*, st_mysql_sys_var*, void*, const void* save) if (err != DB_SUCCESS) { ib::warn() << "Checkpoint set failed " << err; } + + mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18298,7 +18320,9 @@ void buf_flush_list_now_set(THD*, st_mysql_sys_var*, void*, const void* save) { if (*(my_bool*) save) { + mysql_mutex_unlock(&LOCK_global_system_variables); buf_flush_sync_all_buf_pools(); + mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18377,7 +18401,9 @@ buffer_pool_dump_now( check function */ { if (*(my_bool*) save && !srv_read_only_mode) { + mysql_mutex_unlock(&LOCK_global_system_variables); buf_dump_start(); + mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18400,7 +18426,9 @@ buffer_pool_load_now( check function */ { if (*(my_bool*) save && !srv_read_only_mode) { + mysql_mutex_unlock(&LOCK_global_system_variables); buf_load_start(); + mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18423,7 +18451,9 @@ buffer_pool_load_abort( check function */ { if (*(my_bool*) save && !srv_read_only_mode) { + mysql_mutex_unlock(&LOCK_global_system_variables); buf_load_abort(); + mysql_mutex_lock(&LOCK_global_system_variables); } } @@ -18474,55 +18504,63 @@ innodb_log_write_ahead_size_update( /** Update innodb_status_output or innodb_status_output_locks, which control InnoDB "status monitor" output to the error log. -@param[out] var_ptr current value +@param[out] var current value @param[in] save to-be-assigned value */ static void -innodb_status_output_update(THD*, st_mysql_sys_var*, void* var_ptr, - const void* save) +innodb_status_output_update(THD*,st_mysql_sys_var*,void*var,const void*save) { - *static_cast<my_bool*>(var_ptr) = *static_cast<const my_bool*>(save); + *static_cast<my_bool*>(var) = *static_cast<const my_bool*>(save); + mysql_mutex_unlock(&LOCK_global_system_variables); /* Wakeup server monitor thread. */ os_event_set(srv_monitor_event); + mysql_mutex_lock(&LOCK_global_system_variables); } -/****************************************************************** -Update the system variable innodb_encryption_threads */ +/** Update the system variable innodb_encryption_threads. +@param[in] save to-be-assigned value */ static void -innodb_encryption_threads_update(THD*, st_mysql_sys_var*, void*, - const void* save) +innodb_encryption_threads_update(THD*,st_mysql_sys_var*,void*,const void*save) { + mysql_mutex_unlock(&LOCK_global_system_variables); fil_crypt_set_thread_cnt(*static_cast<const uint*>(save)); + mysql_mutex_lock(&LOCK_global_system_variables); } -/****************************************************************** -Update the system variable innodb_encryption_rotate_key_age */ +/** Update the system variable innodb_encryption_rotate_key_age. +@param[in] save to-be-assigned value */ static void innodb_encryption_rotate_key_age_update(THD*, st_mysql_sys_var*, void*, const void* save) { + mysql_mutex_unlock(&LOCK_global_system_variables); fil_crypt_set_rotate_key_age(*static_cast<const uint*>(save)); + mysql_mutex_lock(&LOCK_global_system_variables); } -/****************************************************************** -Update the system variable innodb_encryption_rotation_iops */ +/** Update the system variable innodb_encryption_rotation_iops. +@param[in] save to-be-assigned value */ static void innodb_encryption_rotation_iops_update(THD*, st_mysql_sys_var*, void*, const void* save) { + mysql_mutex_unlock(&LOCK_global_system_variables); fil_crypt_set_rotation_iops(*static_cast<const uint*>(save)); + mysql_mutex_lock(&LOCK_global_system_variables); } -/****************************************************************** -Update the system variable innodb_encrypt_tables*/ +/** Update the system variable innodb_encrypt_tables. +@param[in] save to-be-assigned value */ static void innodb_encrypt_tables_update(THD*, st_mysql_sys_var*, void*, const void* save) { + mysql_mutex_unlock(&LOCK_global_system_variables); fil_crypt_set_encrypt_tables(*static_cast<const ulong*>(save)); + mysql_mutex_lock(&LOCK_global_system_variables); } /** Update the innodb_log_checksums parameter. @@ -19749,13 +19787,16 @@ void innobase_disallow_writes_update(THD*, st_mysql_sys_var*, void* var_ptr, const void* save) { - *(my_bool*)var_ptr = *(my_bool*)save; + const my_bool val = *static_cast<const my_bool*>(save); + *static_cast<my_bool*>(var_ptr) = val; ut_a(srv_allow_writes_event); - if (*(my_bool*)var_ptr) { + mysql_mutex_unlock(&LOCK_global_system_variables); + if (val) { os_event_reset(srv_allow_writes_event); } else { os_event_set(srv_allow_writes_event); } + mysql_mutex_lock(&LOCK_global_system_variables); } static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 0d0e597641b..3ee4a5ba9dd 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -893,7 +893,7 @@ ha_innobase::check_if_supported_inplace_alter( /* Before 10.2.2 information about virtual columns was not stored in system tables. We need to do a full alter to rebuild proper 10.2.2+ metadata with the information about virtual columns */ - if (table->s->mysql_version < 100202 && table->s->virtual_fields) { + if (omits_virtual_cols(*table_share)) { DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 79c0fa1aa3f..61703f947e2 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -7188,7 +7188,7 @@ struct st_maria_plugin i_s_innodb_sys_virtual = /* Maria extension */ STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_BETA), + STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; /** SYS_FIELDS ***************************************************/ /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FIELDS */ diff --git a/storage/innobase/include/btr0pcur.h b/storage/innobase/include/btr0pcur.h index f8a3b6ce097..20f4730f48f 100644 --- a/storage/innobase/include/btr0pcur.h +++ b/storage/innobase/include/btr0pcur.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, 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 @@ -333,14 +333,6 @@ btr_pcur_move_to_prev( function may release the page latch */ mtr_t* mtr); /*!< in: mtr */ /*********************************************************//** -Moves the persistent cursor to the last record on the same page. */ -UNIV_INLINE -void -btr_pcur_move_to_last_on_page( -/*==========================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr); /*!< in: mtr */ -/*********************************************************//** Moves the persistent cursor to the next user record in the tree. If no user records are left, the cursor ends up 'after last in tree'. @return TRUE if the cursor moved forward, ending on a user record */ diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index 053c4db692c..4c3c3359262 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, 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 @@ -263,24 +263,6 @@ btr_pcur_move_to_prev_on_page( } /*********************************************************//** -Moves the persistent cursor to the last record on the same page. */ -UNIV_INLINE -void -btr_pcur_move_to_last_on_page( -/*==========================*/ - btr_pcur_t* cursor, /*!< in: persistent cursor */ - mtr_t* mtr) /*!< in: mtr */ -{ - UT_NOT_USED(mtr); - ut_ad(cursor->latch_mode != BTR_NO_LATCHES); - - page_cur_set_after_last(btr_pcur_get_block(cursor), - btr_pcur_get_page_cur(cursor)); - - cursor->old_stored = false; -} - -/*********************************************************//** Moves the persistent cursor to the next user record in the tree. If no user records are left, the cursor ends up 'after last in tree'. @return TRUE if the cursor moved forward, ending on a user record */ diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index 829b9831202..6583629be8c 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, 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 @@ -192,8 +192,8 @@ buf_LRU_old_ratio_update( /*=====================*/ uint old_pct,/*!< in: Reserve this percentage of the buffer pool for "old" blocks. */ - ibool adjust);/*!< in: TRUE=adjust the LRU list; - FALSE=just assign buf_pool->LRU_old_ratio + bool adjust);/*!< in: true=adjust the LRU list; + false=just assign buf_pool->LRU_old_ratio during the initialization of InnoDB */ /********************************************************************//** Update the historical stats that we are collecting for LRU eviction diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 225061f5165..0818d3f0ed1 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -651,6 +651,25 @@ public: @return tablespace @retval NULL if the tablespace does not exist or cannot be read */ fil_space_t* read_page0(ulint id); + + /** Return the next fil_space_t from key rotation list. + Once started, the caller must keep calling this until it returns NULL. + fil_space_acquire() and fil_space_release() are invoked here which + blocks a concurrent operation from dropping the tablespace. + @param[in] prev_space Previous tablespace or NULL to start + from beginning of fil_system->rotation + list + @param[in] recheck recheck of the tablespace is needed or + still encryption thread does write page0 + for it + @param[in] key_version key version of the key state thread + If NULL, use the first fil_space_t on fil_system->space_list. + @return pointer to the next fil_space_t. + @retval NULL if this was the last */ + fil_space_t* keyrotate_next( + fil_space_t* prev_space, + bool remove, + uint key_version); }; /** The tablespace memory cache. */ @@ -845,11 +864,12 @@ fil_space_acquire() and fil_space_t::release() are invoked here which blocks a concurrent operation from dropping the tablespace. @param[in,out] prev_space Pointer to the previous fil_space_t. If NULL, use the first fil_space_t on fil_system.space_list. +@param[in] remove Whether to remove the previous tablespace from + the rotation list @return pointer to the next fil_space_t. @retval NULL if this was the last*/ fil_space_t* -fil_space_keyrotate_next( - fil_space_t* prev_space) +fil_space_keyrotate_next(fil_space_t* prev_space, bool remove) MY_ATTRIBUTE((warn_unused_result)); /********************************************************//** diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index 5375a0f92a7..49eae7e9643 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -49,6 +49,11 @@ dberr_t recv_find_max_checkpoint(ulint* max_field) MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Reduces recv_sys->n_addrs for the corrupted page. +This function should called when srv_force_recovery > 0. +@param[in] bpage buffer pool page */ +void recv_recover_corrupt_page(buf_page_t* bpage); + /** Apply any buffered redo log to a page that was just read from a data file. @param[in,out] bpage buffer pool page */ ATTRIBUTE_COLD void recv_recover_page(buf_page_t* bpage); diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index 7a7d5834e0a..85856660494 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, 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 @@ -68,10 +68,6 @@ ut_dbg_assertion_failed( #define ut_d(EXPR) #endif -/** Silence warnings about an unused variable by doing a null assignment. -@param A the unused variable */ -#define UT_NOT_USED(A) A = A - #if defined(HAVE_SYS_TIME_H) && defined(HAVE_SYS_RESOURCE_H) #define HAVE_UT_CHRONO_T diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 2f048414ad4..68c3e5ccc2c 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2173,6 +2173,32 @@ skip_log: } } +/** Reduces recv_sys->n_addrs for the corrupted page. +This function should called when srv_force_recovery > 0. +@param[in] bpage buffer pool page */ +void recv_recover_corrupt_page(buf_page_t* bpage) +{ + ut_ad(srv_force_recovery); + mutex_enter(&recv_sys->mutex); + + if (!recv_sys->apply_log_recs) { + mutex_exit(&recv_sys->mutex); + return; + } + + recv_addr_t* recv_addr = recv_get_fil_addr_struct( + bpage->id.space(), bpage->id.page_no()); + + ut_ad(recv_addr->state != RECV_WILL_NOT_READ); + + if (recv_addr->state != RECV_BEING_PROCESSED + && recv_addr->state != RECV_PROCESSED) { + recv_sys->n_addrs--; + } + + mutex_exit(&recv_sys->mutex); +} + /** Apply any buffered redo log to a page that was just read from a data file. @param[in,out] bpage buffer pool page */ void recv_recover_page(buf_page_t* bpage) diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index d01e239e214..7750ec11526 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -27,7 +27,6 @@ Completed by Sunny Bains and Marko Makela #include <my_global.h> #include <log.h> #include <sql_class.h> - #include <math.h> #include "row0merge.h" @@ -50,12 +49,6 @@ Completed by Sunny Bains and Marko Makela #include "ut0stage.h" #include "fil0crypt.h" -float my_log2f(float n) -{ - /* log(n) / log(2) is log2. */ - return (float)(log((double)n) / log((double)2)); -} - /* Ignore posix_fadvise() on those platforms where it does not exist */ #if defined _WIN32 # define posix_fadvise(fd, offset, len, advice) /* nothing */ @@ -3336,18 +3329,13 @@ row_merge_sort( stage->begin_phase_sort(log2(num_runs)); } - /* Find the number N which 2^N is greater or equal than num_runs */ - /* N is merge sort running count */ - total_merge_sort_count = (ulint) ceil(my_log2f((float)num_runs)); - if(total_merge_sort_count <= 0) { - total_merge_sort_count=1; - } - /* If num_runs are less than 1, nothing to merge */ if (num_runs <= 1) { DBUG_RETURN(error); } + total_merge_sort_count = ulint(ceil(log2(double(num_runs)))); + /* "run_offset" records each run's first offset number */ run_offset = (ulint*) ut_malloc_nokey(file->offset * sizeof(ulint)); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 959c3f1fdb3..c6674352d56 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4800,8 +4800,9 @@ wrong_offs: << " of table " << index->table->name << ". We try to skip the rest of the page."; - btr_pcur_move_to_last_on_page(pcur, &mtr); - + page_cur_set_after_last(btr_pcur_get_block(pcur), + btr_pcur_get_page_cur(pcur)); + pcur->old_stored = false; goto next_rec; } } @@ -5564,36 +5565,47 @@ next_rec: } if (moves_up) { - bool move; - - if (spatial_search) { - move = rtr_pcur_move_to_next( - search_tuple, mode, pcur, 0, &mtr); - } else { - move = btr_pcur_move_to_next(pcur, &mtr); - } - - if (!move) { -not_moved: - if (!spatial_search) { - btr_pcur_store_position(pcur, &mtr); + if (UNIV_UNLIKELY(spatial_search)) { + if (rtr_pcur_move_to_next( + search_tuple, mode, pcur, 0, &mtr)) { + goto rec_loop; } - - if (match_mode != 0) { - err = DB_RECORD_NOT_FOUND; + } else { + const buf_block_t* block = btr_pcur_get_block(pcur); + /* This is based on btr_pcur_move_to_next(), + but avoids infinite read loop of a corrupted page. */ + ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED); + ut_ad(pcur->latch_mode != BTR_NO_LATCHES); + pcur->old_stored = false; + if (btr_pcur_is_after_last_on_page(pcur)) { + if (btr_pcur_is_after_last_in_tree(pcur)) { + goto not_moved; + } + btr_pcur_move_to_next_page(pcur, &mtr); + if (UNIV_UNLIKELY(btr_pcur_get_block(pcur) + == block)) { + err = DB_CORRUPTION; + goto lock_wait_or_error; + } } else { - err = DB_END_OF_INDEX; + btr_pcur_move_to_next_on_page(pcur); } - goto normal_return; + goto rec_loop; } } else { - if (UNIV_UNLIKELY(!btr_pcur_move_to_prev(pcur, &mtr))) { - goto not_moved; + if (btr_pcur_move_to_prev(pcur, &mtr)) { + goto rec_loop; } } - goto rec_loop; +not_moved: + if (!spatial_search) { + btr_pcur_store_position(pcur, &mtr); + } + + err = match_mode ? DB_RECORD_NOT_FOUND : DB_END_OF_INDEX; + goto normal_return; lock_wait_or_error: /* Reset the old and new "did semi-consistent read" flags. */ |