diff options
Diffstat (limited to 'storage/innobase/row/row0mysql.cc')
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 133 |
1 files changed, 73 insertions, 60 deletions
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); |