diff options
Diffstat (limited to 'storage/innobase/row/row0trunc.cc')
-rw-r--r-- | storage/innobase/row/row0trunc.cc | 263 |
1 files changed, 101 insertions, 162 deletions
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index fce512afa81..b3a996d990a 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -295,14 +295,12 @@ public: snprintf(m_log_file_name + log_file_name_len, log_file_name_buf_sz - log_file_name_len, - "%s%lu_%lu_%s", + "%s" ULINTPF "_" IB_ID_FMT "_%s", TruncateLogger::s_log_prefix, - (ulong) m_table->space, - (ulong) m_table->id, + m_table->space_id, m_table->id, TruncateLogger::s_log_ext); return(DB_SUCCESS); - } /** @@ -375,7 +373,7 @@ public: which is currently 0. */ err = m_truncate.write( log_buf + 4, log_buf + sz - 4, - m_table->space, m_table->name.m_name, + m_table->space_id, m_table->name.m_name, m_flags, m_table->flags, lsn); DBUG_EXECUTE_IF("ib_err_trunc_oom_logging", @@ -438,7 +436,7 @@ public: - If checkpoint happens post truncate and crash happens post this point then neither MLOG_TRUNCATE nor REDO record from action before truncate are accessible. */ - if (!is_system_tablespace(m_table->space)) { + if (!is_system_tablespace(m_table->space_id)) { mtr_t mtr; byte* log_ptr; @@ -446,7 +444,7 @@ public: log_ptr = mlog_open(&mtr, 11 + 8); log_ptr = mlog_write_initial_log_record_low( - MLOG_TRUNCATE, m_table->space, 0, + MLOG_TRUNCATE, m_table->space_id, 0, log_ptr, &mtr); mach_write_to_8(log_ptr, lsn); @@ -983,8 +981,7 @@ DropIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const } #endif /* UNIV_DEBUG */ - DBUG_EXECUTE_IF("ib_err_trunc_drop_index", - freed = false;); + DBUG_EXECUTE_IF("ib_err_trunc_drop_index", return DB_ERROR;); if (freed) { @@ -1001,16 +998,8 @@ DropIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); } else { - /* Check if the .ibd file is missing. */ - bool found; - - fil_space_get_page_size(m_table->space, &found); - - DBUG_EXECUTE_IF("ib_err_trunc_drop_index", - found = false;); - - if (!found) { - return(DB_ERROR); + if (!m_table->space) { + return DB_ERROR; } } @@ -1069,8 +1058,7 @@ CreateIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const } #endif /* UNIV_DEBUG */ - DBUG_EXECUTE_IF("ib_err_trunc_create_index", - root_page_no = FIL_NULL;); + DBUG_EXECUTE_IF("ib_err_trunc_create_index", return DB_ERROR;); if (root_page_no != FIL_NULL) { @@ -1092,13 +1080,7 @@ CreateIndex::operator()(mtr_t* mtr, btr_pcur_t* pcur) const btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr); } else { - bool found; - fil_space_get_page_size(m_table->space, &found); - - DBUG_EXECUTE_IF("ib_err_trunc_create_index", - found = false;); - - if (!found) { + if (!m_table->space) { return(DB_ERROR); } } @@ -1144,6 +1126,7 @@ row_truncate_rollback( bool corrupted, bool unlock_index) { + ut_ad(!table->is_temporary()); if (unlock_index) { dict_table_x_unlock_indexes(table); } @@ -1154,7 +1137,7 @@ row_truncate_rollback( trx->error_state = DB_SUCCESS; - if (corrupted && !dict_table_is_temporary(table)) { + if (corrupted) { /* Cleanup action to ensure we don't left over stale entries if we are marking table as corrupted. This will ensure @@ -1190,21 +1173,6 @@ row_truncate_rollback( trx_commit_for_mysql(trx); } - - } else if (corrupted && dict_table_is_temporary(table)) { - - dict_table_x_lock_indexes(table); - - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != NULL; - index = UT_LIST_GET_NEXT(indexes, index)) { - - dict_drop_index_tree_in_mem(index, index->page); - - index->page = FIL_NULL; - } - - dict_table_x_unlock_indexes(table); } table->corrupted = corrupted; @@ -1262,7 +1230,7 @@ row_truncate_complete( /* This function will reset back the stop_new_ops and is_being_truncated so that fil-ops can re-start. */ dberr_t err2 = truncate_t::truncate( - table->space, + table->space_id, table->data_dir_path, table->name.m_name, fsp_flags, false); @@ -1569,37 +1537,6 @@ row_truncate_update_system_tables( } /** -Prepare for the truncate process. On success all of the table's indexes will -be locked in X mode. -@param table table to truncate -@param flags tablespace flags -@return error code or DB_SUCCESS */ -static MY_ATTRIBUTE((warn_unused_result)) -dberr_t -row_truncate_prepare(dict_table_t* table, ulint* flags) -{ - ut_ad(!dict_table_is_temporary(table)); - ut_ad(dict_table_is_file_per_table(table)); - - *flags = fil_space_get_flags(table->space); - - ut_ad(!dict_table_is_temporary(table)); - - dict_get_and_save_data_dir_path(table, true); - - if (*flags != ULINT_UNDEFINED) { - - dberr_t err = fil_prepare_for_truncate(table->space); - - if (err != DB_SUCCESS) { - return(err); - } - } - - return(DB_SUCCESS); -} - -/** Do foreign key checks before starting TRUNCATE. @param table table being truncated @param trx transaction covering the truncate @@ -1666,7 +1603,7 @@ row_truncate_sanity_checks( return(DB_TABLESPACE_DELETED); } else if (!table->is_readable()) { - if (fil_space_get(table->space) == NULL) { + if (!table->space) { return(DB_TABLESPACE_NOT_FOUND); } else { @@ -1691,9 +1628,9 @@ fil_reinit_space_header_for_table( ulint size, trx_t* trx) { - ulint id = table->space; - - ut_a(!is_system_tablespace(id)); + fil_space_t* space = table->space; + ut_a(!is_system_tablespace(space->id)); + ut_ad(space->id == table->space_id); /* Invalidate in the buffer pool all pages belonging to the tablespace. The buffer pool scan may take long @@ -1710,7 +1647,7 @@ fil_reinit_space_header_for_table( from disabling AHI during the scan */ btr_search_s_lock_all(); DEBUG_SYNC_C("buffer_pool_scan"); - buf_LRU_flush_or_remove_pages(id, NULL); + buf_LRU_flush_or_remove_pages(space->id, NULL); btr_search_s_unlock_all(); row_mysql_lock_data_dictionary(trx); @@ -1718,15 +1655,7 @@ fil_reinit_space_header_for_table( dict_table_x_lock_indexes(table); /* Remove all insert buffer entries for the tablespace */ - ibuf_delete_for_discarded_space(id); - - mutex_enter(&fil_system.mutex); - fil_space_t* space = fil_space_get_by_id(id); - /* TRUNCATE TABLE is protected by an exclusive table lock. - The table cannot be dropped or the tablespace discarded - while we are holding the transactional table lock. Thus, - there is no need to invoke fil_space_acquire(). */ - mutex_exit(&fil_system.mutex); + ibuf_delete_for_discarded_space(space->id); mtr_t mtr; @@ -1753,10 +1682,8 @@ row_truncate_table_for_mysql( { bool is_file_per_table = dict_table_is_file_per_table(table); dberr_t err; -#ifdef UNIV_DEBUG - ulint old_space = table->space; -#endif /* UNIV_DEBUG */ TruncateLogger* logger = NULL; + ut_d(const fil_space_t* old_space = table->space); /* Understanding the truncate flow. @@ -1922,10 +1849,18 @@ row_truncate_table_for_mysql( dict_table_x_lock_indexes(table); if (!dict_table_is_temporary(table)) { + fsp_flags = table->space + ? table->space->flags + : ULINT_UNDEFINED; if (is_file_per_table) { + ut_ad(!table->is_temporary()); + ut_ad(dict_table_is_file_per_table(table)); - err = row_truncate_prepare(table, &fsp_flags); + dict_get_and_save_data_dir_path(table, true); + err = table->space + ? fil_prepare_for_truncate(table->space_id) + : DB_TABLESPACE_NOT_FOUND; DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", err = DB_ERROR;); @@ -1939,8 +1874,6 @@ row_truncate_table_for_mysql( table, trx, fsp_flags, logger, err)); } } else { - fsp_flags = fil_space_get_flags(table->space); - DBUG_EXECUTE_IF("ib_err_trunc_preparing_for_truncate", fsp_flags = ULINT_UNDEFINED;); @@ -2012,28 +1945,55 @@ row_truncate_table_for_mysql( dict_table_get_first_index(table)->remove_instant(); } else { ut_ad(!table->is_instant()); - /* For temporary tables we don't have entries in SYSTEM TABLES*/ - ut_ad(fsp_is_system_temporary(table->space)); + ut_ad(table->space == fil_system.temp_space); + bool fail = false; for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index != NULL; index = UT_LIST_GET_NEXT(indexes, index)) { + if (index->page != FIL_NULL) { + btr_free(page_id_t(SRV_TMP_SPACE_ID, + index->page), + univ_page_size); + } - err = dict_truncate_index_tree_in_mem(index); - - if (err != DB_SUCCESS) { - row_truncate_rollback( - table, trx, new_id, has_internal_doc_id, - no_redo, true, true); - return(row_truncate_complete( - table, trx, fsp_flags, logger, err)); + mtr_t mtr; + mtr.start(); + mtr.set_log_mode(MTR_LOG_NO_REDO); + index->page = btr_create( + index->type, table->space, index->id, index, + NULL, &mtr); + DBUG_EXECUTE_IF("ib_err_trunc_temp_recreate_index", + index->page = FIL_NULL;); + mtr.commit(); + if (index->page == FIL_NULL) { + fail = true; + break; } + } + if (fail) { + for (dict_index_t* index = UT_LIST_GET_FIRST( + table->indexes); + index != NULL; + index = UT_LIST_GET_NEXT(indexes, index)) { + if (index->page != FIL_NULL) { + btr_free(page_id_t(SRV_TMP_SPACE_ID, + index->page), + univ_page_size); + index->page = FIL_NULL; + } + } + } - DBUG_EXECUTE_IF( - "ib_trunc_crash_during_drop_index_temp_table", - log_buffer_flush_to_disk(); - os_thread_sleep(2000000); - DBUG_SUICIDE();); + table->corrupted = fail; + if (fail) { + return row_truncate_complete( + table, trx, fsp_flags, logger, DB_ERROR); } + + DBUG_EXECUTE_IF( + "ib_trunc_crash_during_drop_index_temp_table", + log_buffer_flush_to_disk(); + DBUG_SUICIDE();); } if (is_file_per_table && fsp_flags != ULINT_UNDEFINED) { @@ -2169,12 +2129,11 @@ fil_recreate_table( /* Step-1: Scan for active indexes from REDO logs and drop all the indexes using low level function that take root_page_no and space-id. */ - truncate.drop_indexes(TRX_SYS_SPACE); + truncate.drop_indexes(fil_system.sys_space); /* Step-2: Scan for active indexes and re-create them. */ dberr_t err = truncate.create_indexes( - name, TRX_SYS_SPACE, univ_page_size, - fil_system.sys_space->flags, format_flags); + name, fil_system.sys_space, format_flags); if (err != DB_SUCCESS) { ib::info() << "Recovery failed for TRUNCATE TABLE '" << name << "' within the system tablespace"; @@ -2292,8 +2251,7 @@ fil_recreate_tablespace( /* Step-4: Re-Create Indexes to newly re-created tablespace. This operation will restore tablespace back to what it was when it was created during CREATE TABLE. */ - err = truncate.create_indexes( - name, space_id, page_size, flags, format_flags); + err = truncate.create_indexes(name, space, format_flags); if (err != DB_SUCCESS) { goto func_exit; } @@ -2955,8 +2913,7 @@ truncate_t::index_t::set( /** Create an index for a table. @param[in] table_name table name, for which to create the index -@param[in] space_id space id where we have to -create the index +@param[in] space tablespace @param[in] page_size page size of the .ibd file @param[in] index_type type of index to truncate @param[in] index_id id of index to truncate @@ -2967,15 +2924,14 @@ create index inline ulint truncate_t::create_index( const char* table_name, - ulint space_id, - const page_size_t& page_size, + fil_space_t* space, ulint index_type, index_id_t index_id, const btr_create_t& btr_redo_create_info, mtr_t* mtr) const { ulint root_page_no = btr_create( - index_type, space_id, page_size, index_id, + index_type, space, index_id, NULL, &btr_redo_create_info, mtr); if (root_page_no == FIL_NULL) { @@ -2984,7 +2940,7 @@ truncate_t::create_index( << srv_force_recovery << ". Continuing crash recovery" " even though we failed to create index " << index_id << " for compressed table '" << table_name << "' with" - " tablespace " << space_id << " during recovery"; + " file " << space->chain.start->name; } return(root_page_no); @@ -2992,30 +2948,27 @@ truncate_t::create_index( /** Check if index has been modified since TRUNCATE log snapshot was recorded. -@param space_id space_id where table/indexes resides. -@param root_page_no root page of index that needs to be verified. +@param[in] space tablespace +@param[in] root_page_no index root page number @return true if modified else false */ - +inline bool truncate_t::is_index_modified_since_logged( - ulint space_id, - ulint root_page_no) const + const fil_space_t* space, + ulint root_page_no) const { - mtr_t mtr; - bool found; - const page_size_t& page_size = fil_space_get_page_size(space_id, - &found); - dberr_t err = DB_SUCCESS; - - ut_ad(found); + dberr_t err; + mtr_t mtr; mtr_start(&mtr); /* Root page could be in free state if truncate crashed after drop_index and page was not allocated for any other object. */ buf_block_t* block= buf_page_get_gen( - page_id_t(space_id, root_page_no), page_size, RW_X_LATCH, NULL, + page_id_t(space->id, root_page_no), page_size_t(space->flags), + RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err); + if (!block) return true; page_t* root = buf_block_get_frame(block); @@ -3039,31 +2992,21 @@ truncate_t::is_index_modified_since_logged( } /** Drop indexes for a table. -@param space_id space_id where table/indexes resides. */ - -void -truncate_t::drop_indexes( - ulint space_id) const +@param[in,out] space tablespace */ +void truncate_t::drop_indexes(fil_space_t* space) const { mtr_t mtr; - ulint root_page_no = FIL_NULL; indexes_t::const_iterator end = m_indexes.end(); + const page_size_t page_size(space->flags); for (indexes_t::const_iterator it = m_indexes.begin(); it != end; ++it) { - root_page_no = it->m_root_page_no; - - bool found; - const page_size_t& page_size - = fil_space_get_page_size(space_id, &found); - - ut_ad(found); + ulint root_page_no = it->m_root_page_no; - if (is_index_modified_since_logged( - space_id, root_page_no)) { + if (is_index_modified_since_logged(space, root_page_no)) { /* Page has been modified since TRUNCATE log snapshot was recorded so not safe to drop the index. */ continue; @@ -3071,14 +3014,14 @@ truncate_t::drop_indexes( mtr_start(&mtr); - if (space_id != TRX_SYS_SPACE) { + if (space->id != TRX_SYS_SPACE) { /* Do not log changes for single-table tablespaces, we are in recovery mode. */ mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); } if (root_page_no != FIL_NULL) { - const page_id_t root_page_id(space_id, root_page_no); + const page_id_t root_page_id(space->id, root_page_no); btr_free_if_exists( root_page_id, page_size, it->m_id, &mtr); @@ -3094,24 +3037,20 @@ truncate_t::drop_indexes( /** Create the indexes for a table @param[in] table_name table name, for which to create the indexes -@param[in] space_id space id where we have to create the indexes -@param[in] page_size page size of the .ibd file -@param[in] flags tablespace flags +@param[in,out] space tablespace @param[in] format_flags page format flags @return DB_SUCCESS or error code. */ inline dberr_t truncate_t::create_indexes( const char* table_name, - ulint space_id, - const page_size_t& page_size, - ulint flags, + fil_space_t* space, ulint format_flags) { mtr_t mtr; mtr_start(&mtr); - if (space_id != TRX_SYS_SPACE) { + if (space->id != TRX_SYS_SPACE) { /* Do not log changes for single-table tablespaces, we are in recovery mode. */ mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); @@ -3128,12 +3067,12 @@ truncate_t::create_indexes( ++it) { btr_create_t btr_redo_create_info( - FSP_FLAGS_GET_ZIP_SSIZE(flags) + FSP_FLAGS_GET_ZIP_SSIZE(space->flags) ? &it->m_fields[0] : NULL); btr_redo_create_info.format_flags = format_flags; - if (FSP_FLAGS_GET_ZIP_SSIZE(flags)) { + if (FSP_FLAGS_GET_ZIP_SSIZE(space->flags)) { btr_redo_create_info.n_fields = it->m_n_fields; /* Skip the NUL appended field */ @@ -3143,7 +3082,7 @@ truncate_t::create_indexes( } root_page_no = create_index( - table_name, space_id, page_size, it->m_type, it->m_id, + table_name, space, it->m_type, it->m_id, btr_redo_create_info, &mtr); if (root_page_no == FIL_NULL) { |