diff options
Diffstat (limited to 'storage/innobase/row')
-rw-r--r-- | storage/innobase/row/row0import.cc | 11 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.cc | 9 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 96 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 133 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.cc | 10 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 18 | ||||
-rw-r--r-- | storage/innobase/row/row0trunc.cc | 9 |
7 files changed, 172 insertions, 114 deletions
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 01a55d0dc61..a2773baa34e 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1959,16 +1959,13 @@ PageConverter::validate( buf_block_t* block) UNIV_NOTHROW { buf_frame_t* page = get_frame(block); - ulint space_id = mach_read_from_4( - page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - fil_space_t* space = fil_space_found_by_id(space_id); /* Check that the page number corresponds to the offset in the file. Flag as corrupt if it doesn't. Disable the check for LSN in buf_page_is_corrupted() */ if (buf_page_is_corrupted( - false, page, get_page_size(), space) + false, page, get_page_size(), NULL) || (page_get_page_no(page) != offset / m_page_size.physical() && page_get_page_no(page) != 0)) { @@ -2101,7 +2098,7 @@ row_import_discard_changes( index->space = FIL_NULL; } - table->ibd_file_missing = TRUE; + table->file_unreadable = true; fil_close_tablespace(trx, table->space); } @@ -3357,7 +3354,7 @@ row_import_for_mysql( ut_a(table->space); ut_ad(prebuilt->trx); - ut_a(table->ibd_file_missing); + ut_a(!table->is_readable()); ibuf_delete_for_discarded_space(table->space); @@ -3691,7 +3688,7 @@ row_import_for_mysql( return(row_import_error(prebuilt, trx, err)); } - table->ibd_file_missing = false; + table->file_unreadable = false; table->flags2 &= ~DICT_TF2_DISCARDED; /* Set autoinc value read from .cfg file, if one was specified. diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 5803bc226cd..fb162592f75 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1656,7 +1656,7 @@ row_ins_check_foreign_constraint( } if (check_table == NULL - || check_table->ibd_file_missing + || !check_table->is_readable() || check_index == NULL) { if (!srv_read_only_mode && check_ref) { @@ -2617,6 +2617,11 @@ row_ins_clust_index_entry_low( __FILE__, __LINE__, auto_inc, &mtr); cursor = btr_pcur_get_btr_cur(&pcur); cursor->thr = thr; + if (err != DB_SUCCESS) { + index->table->file_unreadable = true; + mtr_commit(&mtr); + goto func_exit; + } #ifdef UNIV_DEBUG { @@ -2950,7 +2955,7 @@ row_ins_sec_index_entry_low( " used key_id is not available. " " Can't continue reading table.", index->table->name); - index->table->is_encrypted = true; + index->table->file_unreadable = true; } goto func_exit; } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 82da61dc03b..4c30d0bfa49 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2014, 2017, 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 @@ -26,6 +26,7 @@ Completed by Sunny Bains and Marko Makela *******************************************************/ #include <my_config.h> #include <log.h> +#include <sql_class.h> #include <math.h> @@ -1995,7 +1996,8 @@ row_merge_read_clustered_index( page_cur_t* cur = btr_pcur_get_page_cur(&pcur); /* Do not continue if table pages are still encrypted */ - if (old_table->is_encrypted || new_table->is_encrypted) { + if (!old_table->is_readable() || + !new_table->is_readable()) { err = DB_DECRYPTION_FAILED; trx->error_key_num = 0; goto func_exit; @@ -3300,7 +3302,11 @@ row_merge_sort( } #endif /* UNIV_SOLARIS */ - sql_print_information("InnoDB: Online DDL : merge-sorting has estimated %lu runs", num_runs); + if (global_system_variables.log_warnings > 2) { + sql_print_information("InnoDB: Online DDL : merge-sorting" + " has estimated " ULINTPF " runs", + num_runs); + } /* Merge the runs until we have one big run */ do { @@ -4295,7 +4301,7 @@ row_merge_rename_tables_dict( renamed along with the table. */ if (err == DB_SUCCESS && dict_table_is_file_per_table(old_table) - && !old_table->ibd_file_missing) { + && fil_space_get(old_table->space) != NULL) { /* Make pathname to update SYS_DATAFILES. */ char* tmp_path = row_make_new_pathname(old_table, tmp_name); @@ -4765,20 +4771,24 @@ row_merge_build_indexes( duplicate keys. */ innobase_rec_reset(table); - sql_print_information("InnoDB: Online DDL : Start"); - sql_print_information("InnoDB: Online DDL : Start reading clustered " - "index of the table and create temporary files"); + if (global_system_variables.log_warnings > 2) { + sql_print_information("InnoDB: Online DDL : Start reading" + " clustered index of the table" + " and create temporary files"); + } pct_cost = COST_READ_CLUSTERED_INDEX * 100 / (total_static_cost + total_dynamic_cost); /* Do not continue if we can't encrypt table pages */ - if (old_table->is_encrypted || new_table->is_encrypted) { + if (!old_table->is_readable() || + !new_table->is_readable()) { error = DB_DECRYPTION_FAILED; ib_push_warning(trx->mysql_thd, DB_DECRYPTION_FAILED, "Table %s is encrypted but encryption service or" " used key_id is not available. " " Can't continue reading table.", - old_table->is_encrypted ? old_table->name : new_table->name); + !old_table->is_readable() ? old_table->name : + new_table->name); goto func_exit; } @@ -4795,8 +4805,11 @@ row_merge_build_indexes( pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : End of reading " - "clustered index of the table and create temporary files"); + if (global_system_variables.log_warnings > 2) { + sql_print_information("InnoDB: Online DDL : End of reading " + "clustered index of the table" + " and create temporary files"); + } for (i = 0; i < n_indexes; i++) { total_index_blocks += merge_files[i].offset; @@ -4895,8 +4908,7 @@ wait_again: DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n"); #endif } else if (merge_files[i].fd >= 0) { - char buf[3 * NAME_LEN]; - char *bufend; + char buf[NAME_LEN + 1]; row_merge_dup_t dup = { sort_idx, table, col_map, 0}; @@ -4905,17 +4917,24 @@ wait_again: total_index_blocks)) / (total_static_cost + total_dynamic_cost) * PCT_COST_MERGESORT_INDEX * 100; - - bufend = innobase_convert_name( + char* bufend = innobase_convert_name( buf, sizeof buf, - indexes[i]->name, strlen(indexes[i]->name), + indexes[i]->name, + strlen(indexes[i]->name), trx->mysql_thd); - buf[bufend - buf]='\0'; - sql_print_information("InnoDB: Online DDL : Start merge-sorting" - " index %s (%lu / %lu), estimated cost : %2.4f", - buf, (i+1), n_indexes, pct_cost); + if (global_system_variables.log_warnings > 2) { + sql_print_information("InnoDB: Online DDL :" + " Start merge-sorting" + " index %s" + " (" ULINTPF + " / " ULINTPF ")," + " estimated cost :" + " %2.4f", + buf, i + 1, n_indexes, + pct_cost); + } error = row_merge_sort( trx, &dup, &merge_files[i], @@ -4925,9 +4944,14 @@ wait_again: pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : End of " - " merge-sorting index %s (%lu / %lu)", - buf, (i+1), n_indexes); + if (global_system_variables.log_warnings > 2) { + sql_print_information("InnoDB: Online DDL :" + " End of " + " merge-sorting index %s" + " (" ULINTPF + " / " ULINTPF ")", + buf, i + 1, n_indexes); + } DBUG_EXECUTE_IF( "ib_merge_wait_after_sort", @@ -4944,10 +4968,15 @@ wait_again: (total_static_cost + total_dynamic_cost) * PCT_COST_INSERT_INDEX * 100; - sql_print_information("InnoDB: Online DDL : Start " - "building index %s (%lu / %lu), estimated " - "cost : %2.4f", buf, (i+1), - n_indexes, pct_cost); + if (global_system_variables.log_warnings > 2) { + sql_print_information( + "InnoDB: Online DDL : Start " + "building index %s" + " (" ULINTPF + " / " ULINTPF "), estimated " + "cost : %2.4f", buf, i + 1, + n_indexes, pct_cost); + } error = row_merge_insert_index_tuples( trx->id, sort_idx, old_table, @@ -4960,9 +4989,13 @@ wait_again: pct_progress += pct_cost; - sql_print_information("InnoDB: Online DDL : " - "End of building index %s (%lu / %lu)", - buf, (i+1), n_indexes); + if (global_system_variables.log_warnings > 2) { + sql_print_information( + "InnoDB: Online DDL : " + "End of building index %s" + " (" ULINTPF " / " ULINTPF ")", + buf, i + 1, n_indexes); + } } } @@ -4988,11 +5021,8 @@ wait_again: DEBUG_SYNC_C("row_log_apply_before"); error = row_log_apply(trx, sort_idx, table, stage); DEBUG_SYNC_C("row_log_apply_after"); - sql_print_information("InnoDB: Online DDL : End of applying row log"); } - sql_print_information("InnoDB: Online DDL : Completed"); - if (error != DB_SUCCESS) { trx->error_key_num = key_numbers[i]; goto func_exit; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 20a8777b71e..6160450d510 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2015, 2017, 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 @@ -819,6 +819,7 @@ handle_new_error: break; case DB_CORRUPTION: + case DB_PAGE_CORRUPTED: ib::error() << "We detected index corruption in an InnoDB type" " table. You have to dump + drop + reimport the" " table or, in a case of widespread corruption," @@ -1402,6 +1403,63 @@ run_again: /** Does an insert for MySQL. @param[in] mysql_rec row in the MySQL format @param[in,out] prebuilt prebuilt struct in MySQL handle +@param[in] table Table +@param[in] trx Transaction +@param[in] push_warning true if we should push warning to user +@return DB_DECRYPTION_FAILED table is encrypted but decryption failed +DB_CORRUPTION table is corrupted +DB_TABLESPACE_NOT_FOUND tablespace .ibd file not found */ +static +dberr_t +row_mysql_get_table_status( + const dict_table_t* table, + trx_t* trx, + bool push_warning = true) +{ + dberr_t err = DB_SUCCESS; + if (fil_space_t* space = fil_space_acquire_silent(table->space)) { + if (space->crypt_data && space->crypt_data->is_encrypted()) { + // maybe we cannot access the table due to failing + // to decrypt + if (push_warning) { + ib_push_warning(trx, DB_DECRYPTION_FAILED, + "Table %s in tablespace %lu encrypted." + "However key management plugin or used key_id is not found or" + " used encryption algorithm or method does not match.", + table->name, table->space); + } + + err = DB_DECRYPTION_FAILED; + } else { + if (push_warning) { + ib_push_warning(trx, DB_CORRUPTION, + "Table %s in tablespace %lu corrupted.", + table->name, table->space); + } + + err = DB_CORRUPTION; + } + + fil_space_release(space); + } else { + ib::error() + << "InnoDB: MySQL is trying to use a table handle" + " but the .ibd file for" + " table " << table->name << " does not exist." + " Have you deleted the .ibd file" + " from the database directory under" + " the MySQL datadir, or have you" + " used DISCARD TABLESPACE?" + " Look from " REFMAN "innodb-troubleshooting.html" + " how you can resolve the problem."; + + err = DB_TABLESPACE_NOT_FOUND; + } + + return (err); +} + +/*********************************************************************//** @return error code or DB_SUCCESS */ dberr_t row_insert_for_mysql( @@ -1432,32 +1490,10 @@ row_insert_for_mysql( return(DB_TABLESPACE_DELETED); - } else if (prebuilt->table->ibd_file_missing) { - - ib::error() << ".ibd file is missing for table " - << prebuilt->table->name; - - return(DB_TABLESPACE_NOT_FOUND); - } else if (prebuilt->table->is_encrypted) { - ib_push_warning(trx, DB_DECRYPTION_FAILED, - "Table %s in tablespace " ULINTPF " encrypted." - "However key management plugin or used key_id is not found or" - " used encryption algorithm or method does not match.", - prebuilt->table->name, prebuilt->table->space); - return(DB_DECRYPTION_FAILED); + } else if (!prebuilt->table->is_readable()) { + return (row_mysql_get_table_status(prebuilt->table, trx, true)); } else if (srv_force_recovery) { - ib::error() << MODIFICATIONS_NOT_ALLOWED_MSG_FORCE_RECOVERY; - return(DB_READ_ONLY); - } - DBUG_EXECUTE_IF("mark_table_corrupted", { - /* Mark the table corrupted for the clustered index */ - dict_index_t* index = dict_table_get_first_index(table); - ut_ad(dict_index_is_clust(index)); - dict_set_corrupted(index, trx, "INSERT TABLE"); }); - - if (dict_table_is_corrupted(table)) { - ib::error() << "Table " << table->name << " is corrupt."; return(DB_TABLE_CORRUPT); } @@ -1852,27 +1888,17 @@ row_update_for_mysql_using_upd_graph( bool got_s_lock = false; DBUG_ENTER("row_update_for_mysql_using_upd_graph"); + if (!table->is_readable()) { + return (row_mysql_get_table_status(table, trx, true)); + } ut_ad(trx); ut_a(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED); ut_a(prebuilt->magic_n2 == ROW_PREBUILT_ALLOCATED); UT_NOT_USED(mysql_rec); - if (prebuilt->table->ibd_file_missing) { - ib::error() << "MySQL is trying to use a table handle but the" - " .ibd file for table " << prebuilt->table->name - << " does not exist. Have you deleted" - " the .ibd file from the database directory under" - " the MySQL datadir, or have you used DISCARD" - " TABLESPACE? " << TROUBLESHOOTING_MSG; - DBUG_RETURN(DB_ERROR); - } else if (prebuilt->table->is_encrypted) { - ib_push_warning(trx, DB_DECRYPTION_FAILED, - "Table %s in tablespace " ULINTPF " encrypted." - "However key management plugin or used key_id is not found or" - " used encryption algorithm or method does not match.", - prebuilt->table->name, prebuilt->table->space); - return (DB_TABLE_NOT_FOUND); + if (UNIV_UNLIKELY(prebuilt->table->file_unreadable)) { + return (row_mysql_get_table_status(table, trx, true)); } if(srv_force_recovery) { @@ -3259,7 +3285,7 @@ row_discard_tablespace( /* All persistent operations successful, update the data dictionary memory cache. */ - table->ibd_file_missing = TRUE; + table->file_unreadable = true; table->flags2 |= DICT_TF2_DISCARDED; @@ -3315,8 +3341,6 @@ row_discard_tablespace_for_mysql( if (table == 0) { err = DB_TABLE_NOT_FOUND; - } else if (table->is_encrypted) { - err = DB_DECRYPTION_FAILED; } else if (dict_table_is_temporary(table)) { ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, @@ -3487,7 +3511,6 @@ row_drop_ancillary_fts_tables( /* Drop ancillary FTS tables */ if (dict_table_has_fts_index(table) || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { - ut_ad(table->get_ref_count() == 0); ut_ad(trx_is_started(trx)); @@ -3655,18 +3678,6 @@ row_drop_table_for_mysql( err = DB_TABLE_NOT_FOUND; goto funct_exit; } - /* If table is encrypted and table page encryption failed - return error. */ - if (table->is_encrypted) { - - if (table->can_be_evicted) { - dict_table_move_from_lru_to_non_lru(table); - } - - dict_table_close(table, TRUE, FALSE); - err = DB_DECRYPTION_FAILED; - goto funct_exit; - } /* This function is called recursively via fts_drop_tables(). */ if (!trx_is_started(trx)) { @@ -4071,7 +4082,7 @@ row_drop_table_for_mysql( case DB_SUCCESS: space_id = table->space; - ibd_file_missing = table->ibd_file_missing; + ibd_file_missing = table->file_unreadable; is_discarded = dict_table_is_discarded(table); table_flags = table->flags; ut_ad(!dict_table_is_temporary(table)); @@ -4336,7 +4347,8 @@ loop: << table->name << ".frm' was lost."; } - if (table->ibd_file_missing) { + if (!table->is_readable() + && fil_space_get(table->space) == NULL) { ib::warn() << "Missing .ibd file for table " << table->name << "."; } @@ -4592,7 +4604,8 @@ row_rename_table_for_mysql( err = DB_TABLE_NOT_FOUND; goto funct_exit; - } else if (table->ibd_file_missing + } else if (!table->is_readable() + && fil_space_get(table->space) == NULL && !dict_table_is_discarded(table)) { err = DB_TABLE_NOT_FOUND; @@ -4659,7 +4672,7 @@ row_rename_table_for_mysql( the table is in a single-table tablespace. */ if (err == DB_SUCCESS && dict_table_is_file_per_table(table) - && !table->ibd_file_missing) { + && table->is_readable()) { /* Make a new pathname to update SYS_DATAFILES. */ char* new_path = row_make_new_pathname(table, new_name); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 492d864ec96..37d3fd3ad89 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -880,6 +880,16 @@ try_again: innobase_init_vc_templ(node->table); } + if (!node->table->is_readable()) { + /* We skip purge of missing .ibd files */ + + dict_table_close(node->table, FALSE, FALSE); + + node->table = NULL; + + goto err_exit; + } + clust_index = dict_table_get_first_index(node->table); if (clust_index == NULL diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 229bd567c48..f7ba78c9f0b 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4191,13 +4191,12 @@ row_search_mvcc( DBUG_RETURN(DB_TABLESPACE_DELETED); - } else if (prebuilt->table->ibd_file_missing) { - - DBUG_RETURN(DB_TABLESPACE_NOT_FOUND); - - } else if (prebuilt->table->is_encrypted) { - - return(DB_DECRYPTION_FAILED); + } else if (!prebuilt->table->is_readable()) { + if (fil_space_get(prebuilt->table->space) == NULL) { + return(DB_TABLESPACE_NOT_FOUND); + } else { + return(DB_DECRYPTION_FAILED); + } } else if (!prebuilt->index_usable) { DBUG_RETURN(DB_MISSING_HISTORY); @@ -4673,7 +4672,7 @@ wait_table_again: " used key_id is not available. " " Can't continue reading table.", prebuilt->table->name); - index->table->is_encrypted = true; + index->table->file_unreadable = true; } rec = NULL; goto lock_wait_or_error; @@ -4695,7 +4694,7 @@ rec_loop: rec = btr_pcur_get_rec(pcur); - if (!rec) { + if (!index->table->is_readable()) { err = DB_DECRYPTION_FAILED; goto lock_wait_or_error; } @@ -4787,6 +4786,7 @@ wrong_offs: << ". Run CHECK TABLE. You may need to" " restore from a backup, or dump + drop +" " reimport the table."; + ut_ad(0); err = DB_CORRUPTION; diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 1fc30e714f4..5724fad801f 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -1681,10 +1681,13 @@ row_truncate_sanity_checks( return(DB_TABLESPACE_DELETED); - } else if (table->ibd_file_missing) { - - return(DB_TABLESPACE_NOT_FOUND); + } else if (!table->is_readable()) { + if (fil_space_get(table->space) == NULL) { + return(DB_TABLESPACE_NOT_FOUND); + } else { + return(DB_DECRYPTION_FAILED); + } } else if (dict_table_is_corrupted(table)) { return(DB_TABLE_CORRUPT); |