diff options
Diffstat (limited to 'storage/innobase/row/row0mysql.cc')
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 135 |
1 files changed, 68 insertions, 67 deletions
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index a6c75f7f450..ce0746f20c6 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -54,7 +54,6 @@ Created 9/17/2000 Heikki Tuuri #include "rem0cmp.h" #include "row0import.h" #include "row0ins.h" -#include "row0merge.h" #include "row0row.h" #include "row0sel.h" #include "row0upd.h" @@ -731,7 +730,7 @@ handle_new_error: /* Roll back the latest, possibly incomplete insertion or update */ - trx_rollback_to_savepoint(trx, savept); + trx->rollback(savept); } /* MySQL will roll back the latest SQL statement */ break; @@ -754,7 +753,7 @@ handle_new_error: /* Roll back the whole transaction; this resolution was added to version 3.23.43 */ - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); break; case DB_MUST_GET_MORE_FILE_SPACE: @@ -1185,7 +1184,7 @@ row_lock_table_autoinc_for_mysql( thr = que_fork_get_first_thr(prebuilt->ins_graph); - que_thr_move_to_run_state_for_mysql(thr, trx); + thr->start_running(); run_again: thr->run_node = node; @@ -1214,7 +1213,7 @@ run_again: return(err); } - que_thr_stop_for_mysql_no_error(thr, trx); + thr->stop_no_error(); trx->op_info = ""; @@ -1244,7 +1243,7 @@ row_lock_table(row_prebuilt_t* prebuilt) thr = que_fork_get_first_thr(prebuilt->sel_graph); - que_thr_move_to_run_state_for_mysql(thr, trx); + thr->start_running(); run_again: thr->run_node = thr; @@ -1276,7 +1275,7 @@ run_again: return(err); } - que_thr_stop_for_mysql_no_error(thr, trx); + thr->stop_no_error(); trx->op_info = ""; @@ -1411,7 +1410,7 @@ row_insert_for_mysql( node->state = INS_NODE_ALLOC_ROW_ID; } - que_thr_move_to_run_state_for_mysql(thr, trx); + thr->start_running(); run_again: thr->run_node = node; @@ -1513,7 +1512,7 @@ error_exit: } } - que_thr_stop_for_mysql_no_error(thr, trx); + thr->stop_no_error(); if (table->is_system_db) { srv_stats.n_system_rows_inserted.inc(size_t(trx->id)); @@ -1825,7 +1824,7 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) ut_ad(!prebuilt->sql_stat_start); - que_thr_move_to_run_state_for_mysql(thr, trx); + thr->start_running(); ut_ad(!prebuilt->versioned_write || node->table->versioned()); @@ -1870,13 +1869,13 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) } } - que_thr_stop_for_mysql_no_error(thr, trx); + thr->stop_no_error(); if (dict_table_has_fts_index(table) && trx->fts_next_doc_id != UINT64_UNDEFINED) { err = row_fts_update_or_delete(prebuilt); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { - ut_ad(!"unexpected error"); + ut_ad("unexpected error" == 0); goto error; } } @@ -1934,8 +1933,8 @@ error: DBUG_RETURN(err); } -/** This can only be used when srv_locks_unsafe_for_binlog is TRUE or this -session is using a READ COMMITTED or READ UNCOMMITTED isolation level. +/** This can only be used when the current transaction is at +READ COMMITTED or READ UNCOMMITTED isolation level. Before calling this function row_search_for_mysql() must have initialized prebuilt->new_rec_locks to store the information which new record locks really were set. This function removes a newly set @@ -1958,17 +1957,8 @@ row_unlock_for_mysql( ut_ad(prebuilt != NULL); ut_ad(trx != NULL); + ut_ad(trx->isolation_level <= TRX_ISO_READ_COMMITTED); - if (UNIV_UNLIKELY - (!srv_locks_unsafe_for_binlog - && trx->isolation_level > TRX_ISO_READ_COMMITTED)) { - - ib::error() << "Calling row_unlock_for_mysql though" - " innodb_locks_unsafe_for_binlog is FALSE and this" - " session is not using READ COMMITTED isolation" - " level."; - return; - } if (dict_index_is_spatial(prebuilt->index)) { return; } @@ -2441,7 +2431,7 @@ err_exit: break; case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); ib::warn() << "Cannot create table " << table->name @@ -2472,7 +2462,7 @@ err_exit: case DB_TABLESPACE_EXISTS: default: trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); dict_mem_table_free(table); break; } @@ -2575,8 +2565,8 @@ row_create_index_for_mysql( ut_ad((index == NULL) == (err != DB_SUCCESS)); if (UNIV_LIKELY(err == DB_SUCCESS)) { ut_ad(!index->is_instant()); - index->n_core_null_bytes = UT_BITS_IN_BYTES( - unsigned(index->n_nullable)); + index->n_core_null_bytes = static_cast<uint8_t>( + UT_BITS_IN_BYTES(unsigned(index->n_nullable))); err = dict_create_index_tree_in_mem(index, trx); #ifdef BTR_CUR_HASH_ADAPT @@ -2784,7 +2774,10 @@ row_mysql_drop_garbage_tables() table_name = mem_heap_strdupl( heap, reinterpret_cast<const char*>(field), len); - if (strstr(table_name, "/" TEMP_FILE_PREFIX "-")) { + if (strstr(table_name, "/" TEMP_FILE_PREFIX "-") && + !strstr(table_name, "/" TEMP_FILE_PREFIX "-backup-") && + !strstr(table_name, "/" TEMP_FILE_PREFIX "-exchange-")) + { btr_pcur_store_position(&pcur, &mtr); btr_pcur_commit_specify_mtr(&pcur, &mtr); @@ -3222,7 +3215,7 @@ row_mysql_lock_table( thr = que_fork_get_first_thr( static_cast<que_fork_t*>(que_node_get_parent(thr))); - que_thr_move_to_run_state_for_mysql(thr, trx); + thr->start_running(); run_again: thr->run_node = thr; @@ -3233,7 +3226,7 @@ run_again: trx->error_state = err; if (err == DB_SUCCESS) { - que_thr_stop_for_mysql_no_error(thr, trx); + thr->stop_no_error(); } else { que_thr_stop_for_mysql(thr); @@ -3388,6 +3381,8 @@ row_drop_table_for_mysql( DBUG_RETURN(DB_TABLE_NOT_FOUND); } + std::vector<pfs_os_file_t> detached_handles; + const bool is_temp_name = strstr(table->name.m_name, "/" TEMP_FILE_PREFIX); @@ -3422,19 +3417,6 @@ row_drop_table_for_mysql( table records yet. Thus it is safe to release and reacquire the data dictionary latches. */ if (table->fts) { - ut_ad(!table->fts->add_wq); - ut_ad(lock_trx_has_sys_table_locks(trx) == 0); - - for (;;) { - bool retry = false; - if (dict_fts_index_syncing(table)) { - retry = true; - } - if (!retry) { - break; - } - DICT_BG_YIELD(trx); - } row_mysql_unlock_data_dictionary(trx); fts_optimize_remove_table(table); row_mysql_lock_data_dictionary(trx); @@ -3455,9 +3437,8 @@ row_drop_table_for_mysql( dict_stats_recalc_pool_del(table); dict_stats_defrag_pool_del(table, NULL); - if (btr_defragment_thread_active) { - /* During fts_drop_orphaned_tables() in - recv_recovery_rollback_active() the + if (btr_defragment_active) { + /* During fts_drop_orphaned_tables() the btr_defragment_mutex has not yet been initialized by btr_defragment_init(). */ btr_defragment_remove_table(table); @@ -3537,7 +3518,15 @@ row_drop_table_for_mysql( if (table->n_foreign_key_checks_running > 0) { defer: - if (!is_temp_name) { + /* Rename #sql-backup to #sql-ib if table has open ref count + while dropping the table. This scenario can happen + when purge thread is waiting for dict_sys.mutex so + that it could close the table. But drop table acquires + dict_sys.mutex. + In the future this should use 'tmp_file_prefix'! + */ + if (!is_temp_name + || strstr(table->name.m_name, "/#sql-backup-")) { heap = mem_heap_create(FN_REFLEN); const char* tmp_name = dict_mem_create_temporary_tablename( @@ -3776,7 +3765,8 @@ do_drop: ut_ad(!filepath); if (space->id != TRX_SYS_SPACE) { - err = fil_delete_tablespace(space->id); + err = fil_delete_tablespace(space->id, false, + &detached_handles); } break; @@ -3803,7 +3793,7 @@ do_drop: << ut_get_name(trx, tablename) << "."; trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); trx->error_state = DB_SUCCESS; /* Mark all indexes available in the data dictionary @@ -3856,9 +3846,12 @@ funct_exit_all_freed: row_mysql_unlock_data_dictionary(trx); } - trx->op_info = ""; + for (const auto& handle : detached_handles) { + ut_ad(handle != OS_FILE_CLOSED); + os_file_close(handle); + } - srv_wake_master_thread(); + trx->op_info = ""; DBUG_RETURN(err); } @@ -4179,7 +4172,6 @@ row_rename_table_for_mysql( FOREIGN KEY constraints */ { dict_table_t* table = NULL; - ibool dict_locked = FALSE; dberr_t err = DB_ERROR; mem_heap_t* heap = NULL; const char** constraints_to_drop = NULL; @@ -4193,6 +4185,8 @@ row_rename_table_for_mysql( ut_a(old_name != NULL); ut_a(new_name != NULL); ut_ad(trx->state == TRX_STATE_ACTIVE); + const bool dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH; + ut_ad(!commit || dict_locked); if (high_level_read_only) { return(DB_READ_ONLY); @@ -4211,8 +4205,6 @@ row_rename_table_for_mysql( old_is_tmp = dict_table_t::is_temporary_name(old_name); new_is_tmp = dict_table_t::is_temporary_name(new_name); - dict_locked = trx->dict_operation_lock_mode == RW_X_LATCH; - table = dict_table_open_on_name(old_name, dict_locked, FALSE, DICT_ERR_IGNORE_FK_NOKEY); @@ -4316,6 +4308,10 @@ row_rename_table_for_mysql( } if (!table->is_temporary()) { + if (commit) { + dict_stats_wait_bg_to_stop_using_table(table, trx); + } + err = trx_undo_report_rename(trx, table); if (err != DB_SUCCESS) { @@ -4340,6 +4336,7 @@ row_rename_table_for_mysql( "END;\n" , FALSE, trx); + /* Assume the caller guarantees destination name doesn't exist. */ ut_ad(err != DB_DUPLICATE_KEY); /* SYS_TABLESPACES and SYS_DATAFILES need to be updated if @@ -4375,7 +4372,7 @@ row_rename_table_for_mysql( ut_free(new_path); } if (err != DB_SUCCESS) { - goto end; + goto err_exit; } if (!new_is_tmp) { @@ -4519,8 +4516,8 @@ row_rename_table_for_mysql( } } -end: if (err != DB_SUCCESS) { +err_exit: if (err == DB_DUPLICATE_KEY) { ib::error() << "Possible reasons:"; ib::error() << "(1) Table rename would cause two" @@ -4549,7 +4546,7 @@ end: " succeed."; } trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); trx->error_state = DB_SUCCESS; } else { /* The following call will also rename the .ibd data file if @@ -4559,7 +4556,7 @@ end: table, new_name, !new_is_tmp); if (err != DB_SUCCESS) { trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); trx->error_state = DB_SUCCESS; goto funct_exit; } @@ -4572,13 +4569,16 @@ end: } /* We only want to switch off some of the type checking in - an ALTER TABLE...ALGORITHM=COPY, not in a RENAME. */ + an ALTER TABLE, not in a RENAME. */ dict_names_t fk_tables; err = dict_load_foreigns( - new_name, NULL, - false, !old_is_tmp || trx->check_foreigns, - DICT_ERR_IGNORE_NONE, fk_tables); + new_name, NULL, false, + !old_is_tmp || trx->check_foreigns, + use_fk + ? DICT_ERR_IGNORE_NONE + : DICT_ERR_IGNORE_FK_NOKEY, + fk_tables); if (err != DB_SUCCESS) { @@ -4605,10 +4605,8 @@ end: " with the new table definition."; } - ut_a(DB_SUCCESS == dict_table_rename_in_cache( - table, old_name, FALSE)); trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); trx->error_state = DB_SUCCESS; } @@ -4620,7 +4618,7 @@ end: ut_a(DB_SUCCESS == dict_table_rename_in_cache( table, old_name, FALSE)); trx->error_state = DB_SUCCESS; - trx_rollback_to_savepoint(trx, NULL); + trx->rollback(); trx->error_state = DB_SUCCESS; goto funct_exit; } @@ -4672,6 +4670,9 @@ funct_exit: } if (table != NULL) { + if (commit && !table->is_temporary()) { + table->stats_bg_flag &= byte(~BG_STAT_SHOULD_QUIT); + } dict_table_close(table, dict_locked, FALSE); } |