diff options
28 files changed, 522 insertions, 511 deletions
diff --git a/cmake/install_macros.cmake b/cmake/install_macros.cmake index ebca9f14c31..43a41811e69 100644 --- a/cmake/install_macros.cmake +++ b/cmake/install_macros.cmake @@ -31,6 +31,9 @@ MACRO (INSTALL_DSYM_DIRECTORIES targets) GET_TARGET_PROPERTY(type ${target} TYPE) # It's a dirty hack, but cmake too stupid and mysql cmake files too buggy */ STRING(REPLACE "liblibmysql.dylib" "libmysqlclient.${SHARED_LIB_MAJOR_VERSION}.dylib" location ${location}) + IF(DEBUG_EXTNAME) + STRING(REGEX REPLACE "/mysqld$" "/mysqld-debug" location ${location}) + ENDIF() IF(type MATCHES "EXECUTABLE" OR type MATCHES "MODULE" OR type MATCHES "SHARED_LIBRARY") INSTALL(DIRECTORY "${location}.dSYM" DESTINATION ${ARG_DESTINATION} COMPONENT Debuginfo) ENDIF() diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 59017fff8df..c296c903007 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -294,7 +294,7 @@ read_cnf() ekeyfile=$(parse_cnf sst encrypt-key-file "") fi rlimit=$(parse_cnf sst rlimit "") - uextra=$(parse_cnf sst use_extra 0) + uextra=$(parse_cnf sst use-extra 0) speciald=$(parse_cnf sst sst-special-dirs 1) iopts=$(parse_cnf sst inno-backup-opts "") iapts=$(parse_cnf sst inno-apply-opts "") @@ -648,10 +648,6 @@ then [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE if [[ $speciald -eq 1 ]];then - wsrep_log_info "WARNING: sst-special-dirs feature requires PXC 2.1.6 or latter." - fi - - if [[ $speciald -eq 1 ]];then ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "") ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") if [[ -z $ib_home_dir && -z $ib_log_dir ]];then @@ -827,7 +823,7 @@ then if [[ $incremental -eq 1 ]];then # Added --ibbackup=xtrabackup_55 because it fails otherwise citing connection issues. - INNOAPPLY="${INNOBACKUPEX_BIN} --defaults-file=${WSREP_SST_OPT_CONF} \ + INNOAPPLY="${INNOBACKUPEX_BIN} $disver --defaults-file=${WSREP_SST_OPT_CONF} \ --ibbackup=xtrabackup_55 --apply-log $rebuildcmd --redo-only $BDATA --incremental-dir=${DATA} &>>${BDATA}/innobackup.prepare.log" fi diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index 3948b15c53b..33f2f07946e 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -38,6 +38,8 @@ # Make sure to read that before proceeding! + + . $(dirname $0)/wsrep_sst_common ealgo="" @@ -609,8 +611,6 @@ then if [[ $ecode -ne 0 ]];then wsrep_log_error "Error while getting data from donor node: " \ "exit codes: ${RC[@]}" - wsrep_log_error "Data directory ${DATA} needs to be empty for SST:" \ - "Manual intervention required in that case" exit 32 fi done diff --git a/sql/handler.cc b/sql/handler.cc index 93c0e6f1a04..524f3931f76 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1144,10 +1144,27 @@ int ha_prepare(THD *thd) { if ((err= ht->prepare(ht, thd, all))) { +#ifdef WITH_WSREP + if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) + { + error= 1; + /* avoid sending error, if we need to replay */ + if (thd->wsrep_conflict_state!= MUST_REPLAY) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), err); + } + } + else + { + /* not wsrep hton, bail to native mysql behavior */ +#endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); ha_rollback_trans(thd, all); error=1; break; +#ifdef WITH_WSREP + } +#endif } } else @@ -1419,7 +1436,7 @@ int ha_commit_trans(THD *thd, bool all) my_error(ER_LOCK_DEADLOCK, MYF(0), err); } } - lse + else /* not wsrep hton, bail to native mysql behavior */ #endif /* WITH_WSREP */ my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); @@ -5666,7 +5683,9 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) table->s->cached_row_logging_check && (thd->variables.option_bits & OPTION_BIN_LOG) && #ifdef WITH_WSREP - ((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); + /* applier and replayer should not binlog */ + ((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) || + mysql_bin_log.is_open())); #else mysql_bin_log.is_open()); #endif diff --git a/sql/mdl.cc b/sql/mdl.cc index 399863d4d73..4a3336d0031 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -22,6 +22,8 @@ #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> #include <mysql/psi/mysql_stage.h> +#include <my_murmur3.h> + #ifdef WITH_WSREP #include "wsrep_mysqld.h" #include "wsrep_thd.h" @@ -34,7 +36,6 @@ extern bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx, MDL_ticket *ticket); #endif /* WITH_WSREP */ - #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; static PSI_mutex_key key_MDL_wait_LOCK_wait_status; @@ -1482,7 +1483,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) DBUG_ASSERT(ticket->get_lock()); #ifdef WITH_WSREP if ((this == &(ticket->get_lock()->m_waiting)) && - wsrep_thd_is_BF((void *)(ticket->get_ctx()->get_thd()), false)) + wsrep_thd_is_BF((void *)(ticket->get_ctx()->wsrep_get_thd()), false)) { Ticket_iterator itw(ticket->get_lock()->m_waiting); Ticket_iterator itg(ticket->get_lock()->m_granted); @@ -1493,7 +1494,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) while ((waiting= itw++) && !added) { - if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->get_thd()), true)) + if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->wsrep_get_thd()), true)) { WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", wsrep_thd_thread_id(waiting->get_ctx()->wsrep_get_thd()), @@ -1894,7 +1895,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, ticket->is_incompatible_when_granted(type_arg)) #ifdef WITH_WSREP { - if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) && + if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()),false) && key.mdl_namespace() == MDL_key::GLOBAL) { WSREP_DEBUG("global lock granted for BF: %lu %s", @@ -1935,7 +1936,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, #ifdef WITH_WSREP else { - if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) && + if (wsrep_thd_is_BF((void *)(requestor_ctx->wsrep_get_thd()), false) && key.mdl_namespace() == MDL_key::GLOBAL) { WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b2f0595fe94..f56bb01e0a4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -76,7 +76,6 @@ #include "wsrep_var.h" #include "wsrep_thd.h" #include "wsrep_sst.h" -ulong wsrep_running_threads = 0; // # of currently running wsrep threads #endif #include "sql_callback.h" #include "threadpool.h" @@ -4876,42 +4875,8 @@ will be ignored as the --log-bin option is not defined."); } #endif -#ifdef WITH_WSREP /* WSREP BEFORE SE */ - if (!wsrep_recovery) - { - if (opt_bootstrap) // bootsrap option given - disable wsrep functionality - { - wsrep_provider_init(WSREP_NONE); - if (wsrep_init()) unireg_abort(1); - } - else // full wsrep initialization - { - // add basedir/bin to PATH to resolve wsrep script names - char* const tmp_path((char*)alloca(strlen(mysql_home) + - strlen("/bin") + 1)); - if (tmp_path) - { - strcpy(tmp_path, mysql_home); - strcat(tmp_path, "/bin"); - wsrep_prepend_PATH(tmp_path); - } - else - { - WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); - } DBUG_ASSERT(!opt_bin_log || opt_bin_logname); - if (wsrep_before_SE()) - { -#ifndef EMBEDDED_LIBRARY - set_ports(); // this is also called in network_init() later but we need - // to know mysqld_port now - lp:1071882 -#endif /* !EMBEDDED_LIBRARY */ - wsrep_init_startup(true); - } - } - } -#endif /* WITH_WSREP */ if (opt_bin_log) { /* Reports an error and aborts, if the --log-bin's path @@ -4959,10 +4924,67 @@ a file name for --log-bin-index option", opt_binlog_index_name); { opt_bin_logname= my_once_strdup(buf, MYF(MY_WME)); } +#ifdef WITH_WSREP /* WSREP BEFORE SE */ + /* + Wsrep initialization must happen at this point, because: + - opt_bin_logname must be known when starting replication + since SST may need it + - SST may modify binlog index file, so it must be opened + after SST has happened + */ + } + if (!wsrep_recovery) + { + if (opt_bootstrap) // bootsrap option given - disable wsrep functionality + { + wsrep_provider_init(WSREP_NONE); + if (wsrep_init()) unireg_abort(1); + } + else // full wsrep initialization + { + // add basedir/bin to PATH to resolve wsrep script names + char* const tmp_path((char*)alloca(strlen(mysql_home) + + strlen("/bin") + 1)); + if (tmp_path) + { + strcpy(tmp_path, mysql_home); + strcat(tmp_path, "/bin"); + wsrep_prepend_PATH(tmp_path); + } + else + { + WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); + } + + if (wsrep_before_SE()) + { + set_ports(); // this is also called in network_init() later but we need + // to know mysqld_port now - lp:1071882 + wsrep_init_startup(true); + } + } + } + if (opt_bin_log) + { + /* + Variable ln is not defined at this scope. We use opt_bin_logname instead. + It should be the same as ln since + - mysql_bin_log.generate_name() returns first argument if new log name + is not generated + - if new log name is generated, return value is assigned to ln and copied + to opt_bin_logname above + */ + if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname, + TRUE)) + { + unireg_abort(1); + } +#else if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE)) { unireg_abort(1); } +#endif /* WITH_WSREP */ } /* call ha_init_key_cache() on all key caches to init them */ @@ -5304,21 +5326,10 @@ pthread_handler_t start_wsrep_THD(void *arg) ++connection_count; mysql_mutex_unlock(&LOCK_connection_count); - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads++; - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - processor(thd); close_connection(thd, 0); - mysql_mutex_lock(&LOCK_thread_count); - wsrep_running_threads--; - WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads); - mysql_cond_broadcast(&COND_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - // Note: We can't call THD destructor without crashing // if plugins have not been initialized. However, in most of the // cases this means that pre SE initialization SST failed and diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b1b8a017992..fd49cafb25c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -958,6 +958,10 @@ extern "C" void wsrep_thd_awake(THD *thd, my_bool signal) mysql_mutex_unlock(&LOCK_wsrep_replaying); } } +extern "C" int wsrep_thd_retry_counter(THD *thd) +{ + return(thd->wsrep_retry_counter); +} extern int wsrep_trx_order_before(void *thd1, void *thd2) @@ -2127,7 +2131,19 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use, (e.g. see partitioning code). */ if (!thd_table->needs_reopen()) +#ifdef WITH_WSREP + { + signalled|= mysql_lock_abort_for_thread(this, thd_table); + if (this && WSREP(this) && wsrep_thd_is_BF((void *)this, FALSE)) + { + WSREP_DEBUG("remove_table_from_cache: %llu", + (unsigned long long) this->real_id); + wsrep_abort_thd((void *)this, (void *)in_use, FALSE); + } + } +#else signalled|= mysql_lock_abort_for_thread(this, thd_table); +#endif } mysql_mutex_unlock(&in_use->LOCK_thd_data); } diff --git a/sql/wsrep_binlog.cc b/sql/wsrep_binlog.cc index 8458a299130..62c62cb56f0 100644 --- a/sql/wsrep_binlog.cc +++ b/sql/wsrep_binlog.cc @@ -81,7 +81,7 @@ int wsrep_write_cache_buf(IO_CACHE *cache, uchar **buf, size_t *buf_len) error: if (reinit_io_cache(cache, WRITE_CACHE, saved_pos, 0, 0)) { - WSREP_ERROR("failed to initialize io-cache"); + WSREP_WARN("failed to initialize io-cache"); } cleanup: my_free(*buf); diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index c8a7e0088e2..30264bf24c1 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -160,6 +160,7 @@ extern "C" char * wsrep_thd_query(THD *thd); extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); extern "C" void wsrep_thd_awake(THD *thd, my_bool signal); +extern "C" int wsrep_thd_retry_counter(THD *thd); extern void wsrep_close_client_connections(my_bool wait_to_end); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 23bdf12abe9..ac410438cde 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -51,9 +51,11 @@ extern const char wsrep_defaults_file[]; #define WSREP_SST_OPT_GTID "--gtid" #define WSREP_SST_OPT_BYPASS "--bypass" -#define WSREP_SST_MYSQLDUMP "mysqldump" -#define WSREP_SST_RSYNC "rsync" -#define WSREP_SST_SKIP "skip" +#define WSREP_SST_MYSQLDUMP "mysqldump" +#define WSREP_SST_RSYNC "rsync" +#define WSREP_SST_SKIP "skip" +#define WSREP_SST_XTRABACKUP "xtrabackup" +#define WSREP_SST_XTRABACKUP_V2 "xtrabackup-v2" #define WSREP_SST_DEFAULT WSREP_SST_RSYNC #define WSREP_SST_ADDRESS_AUTO "AUTO" #define WSREP_SST_AUTH_MASK "********" @@ -321,6 +323,33 @@ static char* my_fgets (char* buf, size_t buf_len, FILE* stream) return ret; } +/* + Generate opt_binlog_opt_val for sst_donate_other(), sst_prepare_other(). + + Returns zero on success, negative error code otherwise. + + String containing binlog name is stored in param ret if binlog is enabled + and GTID mode is on, otherwise empty string. Returned string should be + freed with my_free(). + */ +static int generate_binlog_opt_val(char** ret) +{ + DBUG_ASSERT(ret); + *ret= NULL; + if (opt_bin_log && gtid_mode > 0) + { + assert(opt_bin_logname); + *ret= strcmp(opt_bin_logname, "0") ? + my_strdup(opt_bin_logname, MYF(0)) : my_strdup("", MYF(0)); + } + else + { + *ret= my_strdup("", MYF(0)); + } + if (!*ret) return -ENOMEM; + return 0; +} + static void* sst_joiner_thread (void* a) { sst_thread_arg* arg= (sst_thread_arg*) a; @@ -415,21 +444,32 @@ static ssize_t sst_prepare_other (const char* method, ssize_t cmd_len= 1024; char cmd_str[cmd_len]; const char* sst_dir= mysql_real_data_home; - const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : ""); - const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : ""); - - int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s " - WSREP_SST_OPT_ROLE" 'joiner' " - WSREP_SST_OPT_ADDR" '%s' " - WSREP_SST_OPT_AUTH" '%s' " - WSREP_SST_OPT_DATA" '%s' " - WSREP_SST_OPT_CONF" '%s' " - WSREP_SST_OPT_PARENT" '%d'" - " %s '%s' ", - method, addr_in, (sst_auth_real) ? sst_auth_real : "", - sst_dir, wsrep_defaults_file, (int)getpid(), - binlog_opt, binlog_opt_val); + const char* binlog_opt= ""; + char* binlog_opt_val= NULL; + + int ret; + if ((ret= generate_binlog_opt_val(&binlog_opt_val))) + { + WSREP_ERROR("sst_prepare_other(): generate_binlog_opt_val() failed: %d", + ret); + return ret; + } + if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; + + + ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'joiner' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + WSREP_SST_OPT_PARENT" '%d'" + " %s '%s' ", + method, addr_in, (sst_auth_real) ? sst_auth_real : "", + sst_dir, wsrep_defaults_file, (int)getpid(), + binlog_opt, binlog_opt_val); + my_free(binlog_opt_val); if (ret < 0 || ret >= cmd_len) { @@ -965,6 +1005,8 @@ wait_signal: return NULL; } + + static int sst_donate_other (const char* method, const char* addr, const char* uuid, @@ -973,25 +1015,34 @@ static int sst_donate_other (const char* method, { ssize_t cmd_len = 4096; char cmd_str[cmd_len]; - const char* binlog_opt= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? WSREP_SST_OPT_BINLOG : "") : ""); - const char* binlog_opt_val= (opt_bin_logname ? (strcmp(opt_bin_logname, "0") ? opt_bin_logname : "") : ""); - - int ret= snprintf (cmd_str, cmd_len, - "wsrep_sst_%s " - WSREP_SST_OPT_ROLE" 'donor' " - WSREP_SST_OPT_ADDR" '%s' " - WSREP_SST_OPT_AUTH" '%s' " - WSREP_SST_OPT_SOCKET" '%s' " - WSREP_SST_OPT_DATA" '%s' " - WSREP_SST_OPT_CONF" '%s' " - " %s '%s' " - WSREP_SST_OPT_GTID" '%s:%lld'" - "%s", - method, addr, sst_auth_real, mysqld_unix_port, - mysql_real_data_home, wsrep_defaults_file, - binlog_opt, binlog_opt_val, - uuid, (long long) seqno, - bypass ? " "WSREP_SST_OPT_BYPASS : ""); + const char* binlog_opt= ""; + char* binlog_opt_val= NULL; + + int ret; + if ((ret= generate_binlog_opt_val(&binlog_opt_val))) + { + WSREP_ERROR("sst_donate_other(): generate_binlog_opt_val() failed: %d",ret); + return ret; + } + if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; + + ret= snprintf (cmd_str, cmd_len, + "wsrep_sst_%s " + WSREP_SST_OPT_ROLE" 'donor' " + WSREP_SST_OPT_ADDR" '%s' " + WSREP_SST_OPT_AUTH" '%s' " + WSREP_SST_OPT_SOCKET" '%s' " + WSREP_SST_OPT_DATA" '%s' " + WSREP_SST_OPT_CONF" '%s' " + " %s '%s' " + WSREP_SST_OPT_GTID" '%s:%lld'" + "%s", + method, addr, sst_auth_real, mysqld_unix_port, + mysql_real_data_home, wsrep_defaults_file, + binlog_opt, binlog_opt_val, + uuid, (long long) seqno, + bypass ? " "WSREP_SST_OPT_BYPASS : ""); + my_free(binlog_opt_val); if (ret < 0 || ret >= cmd_len) { diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index e68120ee779..78ba559380b 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -472,7 +472,6 @@ void wsrep_create_rollbacker() } } -extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync) { my_bool status = FALSE; @@ -520,7 +519,6 @@ my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync) return status; } -extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) { THD *victim_thd = (THD *) victim_thd_ptr; diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 74e3bff120c..f719deae2b7 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -24,11 +24,13 @@ void wsrep_replay_transaction(THD *thd); void wsrep_create_appliers(long threads); void wsrep_create_rollbacker(); -extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, + my_bool signal); + +extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +//extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync); extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync); -extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, - my_bool signal); extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); #endif /* WSREP_THD_H */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index abbdb94397c..241637bca8a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1184,8 +1184,8 @@ innobase_srv_conc_enter_innodb( trx_t* trx) /*!< in: transaction handle */ { #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) return; + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ if (srv_thread_concurrency) { if (trx->n_tickets_to_enter_innodb > 0) { @@ -1222,8 +1222,8 @@ innobase_srv_conc_exit_innodb( ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); #endif /* UNIV_SYNC_DEBUG */ #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) return; + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ /* This is to avoid making an unnecessary function call. */ @@ -3466,11 +3466,6 @@ innobase_commit_low( /*================*/ trx_t* trx) /*!< in: transaction handle */ { - if (trx_is_started(trx)) { - - trx_commit_for_mysql(trx); - } - #ifdef WITH_WSREP THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; @@ -3488,7 +3483,10 @@ innobase_commit_low( #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ + if (trx_is_started(trx)) { + trx_commit_for_mysql(trx); + } #ifdef WITH_WSREP if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } #endif /* WITH_WSREP */ @@ -5544,7 +5542,7 @@ wsrep_innobase_mysql_sort( tmp_length = charset->coll->strnxfrm(charset, str, str_length, str_length, tmp_str, tmp_length, 0); /**/ - DBUG_ASSERT(tmp_length == str_length); + DBUG_ASSERT(tmp_length <= str_length); break; } @@ -7434,9 +7432,10 @@ no_commit: #ifdef WITH_WSREP /* workaround for LP bug #355000, retrying the insert */ case SQLCOM_INSERT: - if (wsrep_on(current_thd) && - auto_inc_inserted && - wsrep_drupal_282555_workaround && + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + wsrep_thd_retry_counter(current_thd) == 0 && !thd_test_options(current_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -9545,6 +9544,13 @@ ha_innobase::wsrep_append_keys( } else { ut_a(table->s->keys <= 256); uint i; + bool hasPK= false; + + for (i=0; i<table->s->keys && !hasPK; ++i) { + KEY* key_info = table->key_info + i; + if (key_info->flags & HA_NOSAME) hasPK = true; + } + for (i=0; i<table->s->keys; ++i) { uint len; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -9565,14 +9571,11 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } - if (key_info->flags & HA_NOSAME || + if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, record0, &is_null); @@ -9581,6 +9584,10 @@ ha_innobase::wsrep_append_keys( thd, trx, table_share, table, keyval0, len+1, shared); if (rcode) DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; + } else { @@ -16699,6 +16706,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) } /*******************************************************************//** This function is used to kill one transaction in BF. */ + int wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, const trx_t * const bf_trx, diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 08ac2a74405..dc78964a873 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -291,7 +291,7 @@ UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd_ptr, const trx_t *bf_trx, trx_t *victim_trx, ibool signal); -extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); int wsrep_trx_order_before(void *thd1, void *thd2); void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, unsigned char* str, unsigned int str_length); diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 24e612e63f5..2f89c02bb7a 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -873,7 +873,6 @@ lock_trx_has_sys_table_locks( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index f6779ff5acd..0e4c1e7c82f 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -978,47 +978,6 @@ lock_rec_has_to_wait( && !lock_mode_compatible(static_cast<enum lock_mode>( LOCK_MODE_MASK & type_mode), lock_get_mode(lock2))) { -#ifdef WITH_WSREP - /* if BF thread is locking and has conflict with another BF - thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_brute_force(trx->mysql_thd) && - wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) { - - if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); - lock_rec_print(stderr, lock2); - } - - if (wsrep_trx_order_before(trx->mysql_thd, - lock2->trx->mysql_thd) && - (type_mode & LOCK_MODE_MASK) == LOCK_X && - (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) - { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict\n"); - lock_rec_print(stderr, lock2); - - abort(); - } else { - if (wsrep_debug) { - fprintf(stderr, - "BF conflict, modes: %lu %lu\n", - type_mode, - lock2->type_mode); -#ifdef OUT - fprintf(stderr, - "seqnos %llu %llu\n", - (long long)wsrep_thd_trx_seqno( - trx->mysql_thd), - (long long)wsrep_thd_trx_seqno( - lock2->trx->mysql_thd)); -#endif - } - return FALSE; - } - } -#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1068,6 +1027,44 @@ lock_rec_has_to_wait( return(FALSE); } +#ifdef WITH_WSREP + /* if BF thread is locking and has conflict with another BF + thread, we need to look at trx ordering and lock types */ + if (for_locking && + wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { + + if (wsrep_debug) { + fprintf(stderr, "\n BF-BF lock conflict \n"); + lock_rec_print(stderr, lock2); + } + + if (wsrep_trx_order_before(trx->mysql_thd, + lock2->trx->mysql_thd) && + (type_mode & LOCK_MODE_MASK) == LOCK_X && + (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) + { + /* exclusive lock conflicts are not accepted */ + fprintf(stderr, "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else { + /* if lock2->index->n_uniq <= + lock2->index->n_user_defined_cols + operation is on uniq index + */ + if (wsrep_debug) fprintf(stderr, + "BF conflict, modes: %lu %lu, " + "idx: %s-%s n_uniq %u n_user %u\n", + type_mode, lock2->type_mode, + lock2->index->name, + lock2->index->table_name, + lock2->index->n_uniq, + lock2->index->n_user_defined_cols); + return FALSE; + } + } +#endif /* WITH_WSREP */ return(TRUE); } @@ -1630,8 +1627,8 @@ void wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { ut_ad(lock_mutex_own()); ut_ad(trx_mutex_own(lock->trx)); - my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd); + my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); if ((bf_this && !bf_other) || (bf_this && bf_other && wsrep_trx_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { @@ -1929,11 +1926,6 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock->type_mode |= WSREP_BF; - } -#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1953,12 +1945,12 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; while (hash && - wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) && + wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) && wsrep_trx_order_before( ((lock_t *)hash)->trx->mysql_thd, trx->mysql_thd)) { @@ -2361,11 +2353,6 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); @@ -2382,8 +2369,7 @@ lock_rec_lock_fast( #else lock = lock_rec_create( mode, block, heap_no, index, trx, FALSE); -#endif - +#endif /* WITH_WSREP */ } status = LOCK_REC_SUCCESS_CREATED; } else { @@ -2451,11 +2437,6 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); @@ -2564,11 +2545,6 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); #ifdef WITH_WSREP @@ -4023,18 +3999,18 @@ lock_deadlock_select_victim( /* The joining transaction is 'smaller', choose it as the victim and roll it back. */ #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) { - return(ctx->start); - } -#else - return(ctx->start); -#endif + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) + return(ctx->wait_lock->trx); + else +#endif /* WITH_WSREP */ + return(ctx->start); } + #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) { - return(ctx->start); - } -#endif + if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) + return(ctx->start); + else +#endif /* WITH_WSREP */ return(ctx->wait_lock->trx); } @@ -4184,7 +4160,7 @@ lock_deadlock_search( ctx->too_deep = TRUE; #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) return(ctx->wait_lock->trx->id); else #endif /* WITH_WSREP */ @@ -4205,7 +4181,7 @@ lock_deadlock_search( ctx->too_deep = TRUE; #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) return(lock->trx->id); else #endif /* WITH_WSREP */ @@ -4342,7 +4318,7 @@ lock_deadlock_check_and_resolve( ut_a(victim_trx_id == trx->id); #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd)) + if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE)) { #endif /* WITH_WSREP */ if (!srv_read_only_mode) { @@ -4438,7 +4414,7 @@ lock_table_create( UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( un_member.tab_lock.locks, table->locks, c_lock, lock); } else { @@ -6476,7 +6452,7 @@ lock_rec_convert_impl_to_expl( if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) #ifdef WITH_WSREP - && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE) /* BF-BF conflict is possible if advancing into lock_rec_other_has_conflicting*/ #endif /* WITH_WSREP */ diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index f957c1855cc..5a793ae7af8 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -195,7 +195,7 @@ wsrep_is_BF_lock_timeout( trx_t* trx) /* in: trx to check for lock priority */ { if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { fprintf(stderr, "WSREP: BF lock wait long\n"); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 57687e77b2b..14226d04eaa 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1920,9 +1920,6 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* offsets_heap) /*!< in/out: memory heap that can be emptied */ { -#ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr); -#endif ulint n_unique; int cmp; ulint n_fields_cmp; @@ -1980,16 +1977,8 @@ row_ins_scan_sec_index_for_duplicate( if (flags & BTR_NO_LOCKING_FLAG) { /* Set no locks when applying log in online table rebuild. */ -#ifdef WITH_WSREP - /* slave applier must not get duplicate error */ - } else if (allow_duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else } else if (allow_duplicates) { -#endif - /* If the SQL-query will update or replace duplicate key we will take X-lock for duplicates ( REPLACE, LOAD DATAFILE REPLACE, @@ -2000,6 +1989,10 @@ row_ins_scan_sec_index_for_duplicate( rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( LOCK_ORDINARY, block, rec, index, offsets, thr); @@ -2183,13 +2176,7 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -2234,13 +2221,7 @@ duplicate: offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 5d236cc40e5..d3ca4ec6b8e 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -373,6 +373,8 @@ wsrep_row_upd_check_foreign_constraints( trx = thr_get_trx(thr); + /* TODO: make native slave thread bail out here */ + rec = btr_pcur_get_rec(pcur); ut_ad(rec_offs_validate(rec, index, offsets)); diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 0b2837a09b5..2562064b51b 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void) mtr_t mtr; trx_sysf_t* sys_header; +#ifndef WITH_WSREP + /* wsrep_fake_trx_id violates this assert + * Copied from trx_sys_get_new_trx_id + */ ut_ad(mutex_own(&trx_sys->mutex)); +#endif /* WITH_WSREP */ if (!srv_read_only_mode) { mtr_start(&mtr); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index e3a3f71f559..ce3e8f250c9 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1448,9 +1448,8 @@ innobase_srv_conc_enter_innodb( { #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) return; + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; #endif /* WITH_WSREP */ - if (srv_thread_concurrency) { if (trx->n_tickets_to_enter_innodb > 0) { @@ -1482,14 +1481,13 @@ innobase_srv_conc_exit_innodb( /*==========================*/ trx_t* trx) /*!< in: transaction handle */ { -#ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) return; -#endif /* WITH_WSREP */ - #ifdef UNIV_SYNC_DEBUG ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); #endif /* UNIV_SYNC_DEBUG */ +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) return; +#endif /* WITH_WSREP */ /* This is to avoid making an unnecessary function call. */ if (trx->declared_to_be_inside_innodb @@ -3937,12 +3935,10 @@ innobase_commit_low( #endif /* WSREP_PROC_INFO */ } #endif /* WITH_WSREP */ - if (trx_is_started(trx)) { trx_commit_for_mysql(trx); } - #ifdef WITH_WSREP if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } #endif /* WITH_WSREP */ @@ -6002,7 +5998,7 @@ wsrep_innobase_mysql_sort( tmp_length = charset->coll->strnxfrm(charset, str, str_length, str_length, tmp_str, tmp_length, 0); - DBUG_ASSERT(tmp_length == str_length); + DBUG_ASSERT(tmp_length <= str_length); break; } @@ -7896,9 +7892,10 @@ no_commit: #ifdef WITH_WSREP /* workaround for LP bug #355000, retrying the insert */ case SQLCOM_INSERT: - if (wsrep_on(current_thd) && - auto_inc_inserted && - wsrep_drupal_282555_workaround && + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + wsrep_thd_retry_counter(current_thd) == 0 && !thd_test_options(current_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -7910,8 +7907,7 @@ no_commit: error= DB_SUCCESS; wsrep_thd_set_conflict_state( current_thd, MUST_ABORT); - innobase_srv_conc_exit_innodb( - prebuilt->trx); + innobase_srv_conc_exit_innodb(prebuilt->trx); /* jump straight to func exit over * later wsrep hooks */ goto func_exit; @@ -10059,6 +10055,13 @@ ha_innobase::wsrep_append_keys( } else { ut_a(table->s->keys <= 256); uint i; + bool hasPK= false; + + for (i=0; i<table->s->keys && !hasPK; ++i) { + KEY* key_info = table->key_info + i; + if (key_info->flags & HA_NOSAME) hasPK = true; + } + for (i=0; i<table->s->keys; ++i) { uint len; char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; @@ -10079,14 +10082,11 @@ ha_innobase::wsrep_append_keys( table->s->table_name.str, key_info->name); } - if (key_info->flags & HA_NOSAME || + if (!hasPK || key_info->flags & HA_NOSAME || ((tab && dict_table_get_referenced_constraint(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - len = wsrep_store_key_val_for_row( table, i, key0, key_info->key_length, record0, &is_null); @@ -10095,6 +10095,10 @@ ha_innobase::wsrep_append_keys( thd, trx, table_share, table, keyval0, len+1, shared); if (rcode) DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; + } else { @@ -17755,6 +17759,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) } /*******************************************************************//** This function is used to kill one transaction in BF. */ + int wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, const trx_t * const bf_trx, diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index d1652c1f0d8..d027deb6140 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -285,6 +285,19 @@ innobase_casedn_str( /*================*/ char* a); /*!< in/out: string to put in lower case */ +#ifdef WITH_WSREP +UNIV_INTERN +int +wsrep_innobase_kill_one_trx(void *thd_ptr, + const trx_t *bf_trx, trx_t *victim_trx, ibool signal); +my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); +int wsrep_trx_order_before(void *thd1, void *thd2); +void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length); +int +wsrep_on(void *thd_ptr); +extern "C" int wsrep_is_wsrep_xid(const void*); +#endif /* WITH_WSREP */ /**********************************************************************//** Determines the connection character set. @return connection character set */ @@ -375,21 +388,6 @@ thd_flush_log_at_trx_commit( /*================================*/ void* thd); -#ifdef WITH_WSREP -UNIV_INTERN -int -wsrep_innobase_kill_one_trx(void *thd_ptr, - const trx_t *bf_trx, trx_t *victim_trx, ibool signal); - -extern "C" int wsrep_thd_is_brute_force(void *thd_ptr); -int wsrep_trx_order_before(void *thd1, void *thd2); -void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, - unsigned char* str, unsigned int str_length); -//UNIV_INTERN -int -wsrep_on(void *thd_ptr); -extern "C" int wsrep_is_wsrep_xid(const void*); -#endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from mysqld.cc. We do a dirty read because for one there is no synchronization diff --git a/storage/xtradb/include/lock0lock.h b/storage/xtradb/include/lock0lock.h index d11f3b006d4..466e728f65b 100644 --- a/storage/xtradb/include/lock0lock.h +++ b/storage/xtradb/include/lock0lock.h @@ -906,7 +906,6 @@ lock_trx_has_rec_x_lock( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index 8773e2e1868..67985c642c6 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -982,48 +982,6 @@ lock_rec_has_to_wait( LOCK_MODE_MASK & type_mode), lock_get_mode(lock2))) { -#ifdef WITH_WSREP - /* if BF thread is locking and has conflict with another BF - thread, we need to look at trx ordering and lock types */ - if (for_locking && - wsrep_thd_is_brute_force(trx->mysql_thd) && - wsrep_thd_is_brute_force(lock2->trx->mysql_thd)) { - - if (wsrep_debug) { - fprintf(stderr, "\n BF-BF lock conflict \n"); - lock_rec_print(stderr, lock2); - } - - if (wsrep_trx_order_before(trx->mysql_thd, - lock2->trx->mysql_thd) && - (type_mode & LOCK_MODE_MASK) == LOCK_X && - (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) - { - /* exclusive lock conflicts are not accepted */ - fprintf(stderr, "BF-BF X lock conflict\n"); - lock_rec_print(stderr, lock2); - - abort(); - } else { - if (wsrep_debug) { - fprintf(stderr, - "BF conflict, modes: %lu %lu\n", - type_mode, - lock2->type_mode); -#ifdef OUT - fprintf(stderr, - "seqnos %llu %llu\n", - (long long)wsrep_thd_trx_seqno( - trx->mysql_thd), - (long long)wsrep_thd_trx_seqno( - lock2->trx->mysql_thd)); -#endif - } - return FALSE; - } - } -#endif /* WITH_WSREP */ - /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1072,6 +1030,44 @@ lock_rec_has_to_wait( return(FALSE); } +#ifdef WITH_WSREP + /* if BF thread is locking and has conflict with another BF + thread, we need to look at trx ordering and lock types */ + if (for_locking && + wsrep_thd_is_BF(trx->mysql_thd, FALSE) && + wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { + + if (wsrep_debug) { + fprintf(stderr, "\n BF-BF lock conflict \n"); + lock_rec_print(stderr, lock2); + } + + if (wsrep_trx_order_before(trx->mysql_thd, + lock2->trx->mysql_thd) && + (type_mode & LOCK_MODE_MASK) == LOCK_X && + (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) + { + /* exclusive lock conflicts are not accepted */ + fprintf(stderr, "BF-BF X lock conflict\n"); + lock_rec_print(stderr, lock2); + abort(); + } else { + /* if lock2->index->n_uniq <= + lock2->index->n_user_defined_cols + operation is on uniq index + */ + if (wsrep_debug) fprintf(stderr, + "BF conflict, modes: %lu %lu, " + "idx: %s-%s n_uniq %u n_user %u\n", + type_mode, lock2->type_mode, + lock2->index->name, + lock2->index->table_name, + lock2->index->n_uniq, + lock2->index->n_user_defined_cols); + return FALSE; + } + } +#endif /* WITH_WSREP */ return(TRUE); } @@ -1634,10 +1630,8 @@ static void wsrep_kill_victim(trx_t *trx, lock_t *lock) { ut_ad(lock_mutex_own()); ut_ad(trx_mutex_own(lock->trx)); - - my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); - my_bool bf_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd); - + my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); if ((bf_this && !bf_other) || (bf_this && bf_other && wsrep_trx_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { @@ -1935,13 +1929,8 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; -#ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(trx->mysql_thd)) { - lock->type_mode |= WSREP_BF; - } -#endif /* WITH_WSREP */ - lock->index = index; + lock->un_member.rec_lock.space = space; lock->un_member.rec_lock.page_no = page_no; lock->un_member.rec_lock.n_bits = n_bytes * 8; @@ -1959,12 +1948,12 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; while (hash && - wsrep_thd_is_brute_force(((lock_t *)hash)->trx->mysql_thd) && + wsrep_thd_is_BF(((lock_t *)hash)->trx->mysql_thd, TRUE) && wsrep_trx_order_before( ((lock_t *)hash)->trx->mysql_thd, trx->mysql_thd)) { @@ -2378,11 +2367,6 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); @@ -2454,11 +2438,11 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; - lock_t* lock; - dberr_t err = DB_SUCCESS; #ifdef WITH_WSREP lock_t* c_lock = NULL; #endif + lock_t* lock; + dberr_t err = DB_SUCCESS; ut_ad(lock_mutex_own()); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S @@ -2469,11 +2453,6 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); @@ -2582,11 +2561,6 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP -#ifdef WITH_WSREP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP - || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP -#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); #ifdef WITH_WSREP @@ -4040,20 +4014,19 @@ lock_deadlock_select_victim( if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) { /* The joining transaction is 'smaller', choose it as the victim and roll it back. */ - #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) - return(ctx->start); - else + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) + return(ctx->wait_lock->trx); + else #endif /* WITH_WSREP */ return(ctx->start); } #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) { - return(ctx->start); - } -#endif + if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) + return(ctx->start); + else +#endif /* WITH_WSREP */ return(ctx->wait_lock->trx); } @@ -4184,7 +4157,7 @@ lock_deadlock_search( ctx->too_deep = TRUE; #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) return(ctx->wait_lock->trx->id); else #endif /* WITH_WSREP */ @@ -4207,7 +4180,7 @@ lock_deadlock_search( ctx->too_deep = TRUE; #ifdef WITH_WSREP - if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) return(lock->trx->id); else #endif /* WITH_WSREP */ @@ -4330,7 +4303,7 @@ lock_deadlock_check_and_resolve( ut_a(victim_trx_id == trx->id); #ifdef WITH_WSREP - if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd)) + if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE)) { #endif /* WITH_WSREP */ if (!srv_read_only_mode) { @@ -4426,8 +4399,9 @@ lock_table_create( ut_ad(table->n_ref_count > 0 || !table->can_be_evicted); UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); + #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( un_member.tab_lock.locks, table->locks, c_lock, lock); } else { @@ -6533,7 +6507,7 @@ lock_rec_convert_impl_to_expl( if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) #ifdef WITH_WSREP - && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + && !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE) /* BF-BF conflict is possible if advancing into lock_rec_other_has_conflicting*/ #endif /* WITH_WSREP */ diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index 0c1269f02d5..388c847f580 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -195,7 +195,7 @@ wsrep_is_BF_lock_timeout( trx_t* trx) /* in: trx to check for lock priority */ { if (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd)) { + wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { fprintf(stderr, "WSREP: BF lock wait long\n"); srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index d36d589e6c6..9cf2a4fc00d 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1939,9 +1939,6 @@ row_ins_scan_sec_index_for_duplicate( mem_heap_t* offsets_heap) /*!< in/out: memory heap that can be emptied */ { -#ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr); -#endif ulint n_unique; int cmp; ulint n_fields_cmp; @@ -2010,16 +2007,7 @@ row_ins_scan_sec_index_for_duplicate( if (flags & BTR_NO_LOCKING_FLAG) { /* Set no locks when applying log in online table rebuild. */ - -#ifdef WITH_WSREP - /* slave applier must not get duplicate error */ - } else if (allow_duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else - } else if (allow_duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -2030,6 +2018,10 @@ row_ins_scan_sec_index_for_duplicate( lock_type, block, rec, index, offsets, thr); } else { +#ifdef WITH_WSREP + /* appliers don't need dupkey checks */ + if (!wsrep_thd_is_BF(thr_get_trx(thr)->mysql_thd, 0)) +#endif /* WITH_WSREP */ err = row_ins_set_shared_rec_lock( lock_type, block, rec, index, offsets, thr); } @@ -2225,13 +2217,7 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -2276,13 +2262,7 @@ duplicate: offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); -#ifdef WITH_WSREP - if (trx->duplicates || - (wsrep_on(trx->mysql_thd) && - wsrep_thd_is_brute_force(trx->mysql_thd))) { -#else if (trx->duplicates) { -#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc index 9d40848c2fc..5725b229a07 100644 --- a/storage/xtradb/row/row0upd.cc +++ b/storage/xtradb/row/row0upd.cc @@ -175,27 +175,6 @@ func_exit: return(is_referenced); } -#ifdef WITH_WSREP -ulint -wsrep_append_foreign_key( - trx_t* trx, - dict_foreign_t* foreign, - const rec_t* clust_rec, - dict_index_t* clust_index, - ibool referenced, - ibool shared); - -ulint -wsrep_row_upd_check_foreign_constraints( - upd_node_t* node, /*!< in: row update node */ - btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the - cursor position is lost in this function! */ - dict_table_t* table, /*!< in: table in question */ - dict_index_t* index, /*!< in: index of the cursor */ - ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ - que_thr_t* thr, /*!< in: query thread */ - mtr_t* mtr); /*!< in: mtr */ -#endif /* WITH_WSREP */ /*********************************************************************//** Checks if possible foreign key constraints hold after a delete of the record @@ -314,7 +293,125 @@ run_again: } err = DB_SUCCESS; +func_exit: + if (got_s_lock) { + row_mysql_unfreeze_data_dictionary(trx); + } + + mem_heap_free(heap); + + return(err); +} +#ifdef WITH_WSREP +static +dberr_t +wsrep_row_upd_check_foreign_constraints( +/*=================================*/ + upd_node_t* node, /*!< in: row update node */ + btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the + cursor position is lost in this function! */ + dict_table_t* table, /*!< in: table in question */ + dict_index_t* index, /*!< in: index of the cursor */ + ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ + que_thr_t* thr, /*!< in: query thread */ + mtr_t* mtr) /*!< in: mtr */ +{ + dict_foreign_t* foreign; + mem_heap_t* heap; + dtuple_t* entry; + trx_t* trx; + const rec_t* rec; + ulint n_ext; + dberr_t err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); + + /* TODO: make native slave thread bail out here */ + + rec = btr_pcur_get_rec(pcur); + ut_ad(rec_offs_validate(rec, index, offsets)); + + heap = mem_heap_create(500); + + entry = row_rec_to_index_entry(rec, index, offsets, + &n_ext, heap); + + mtr_commit(mtr); + + mtr_start(mtr); + if (trx->dict_operation_lock_mode == 0) { + got_s_lock = TRUE; + + row_mysql_freeze_data_dictionary(trx); + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + /* Note that we may have an update which updates the index + record, but does NOT update the first fields which are + referenced in a foreign key constraint. Then the update does + NOT break the constraint. */ + + if (foreign->foreign_index == index + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + + if (foreign->referenced_table == NULL) { + foreign->referenced_table = + dict_table_open_on_name( + foreign->referenced_table_name_lookup, + FALSE, FALSE, DICT_ERR_IGNORE_NONE); + } + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + (foreign->referenced_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* NOTE that if the thread ends up waiting for a lock + we will release dict_operation_lock temporarily! + But the counter on the table protects 'foreign' from + being dropped while the check is running. */ + + err = row_ins_check_foreign_constraint( + TRUE, foreign, table, entry, thr); + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->referenced_table + ->n_foreign_key_checks_running > 0); + + (foreign->referenced_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + + if (err != DB_SUCCESS) { + + goto func_exit; + } + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + err = DB_SUCCESS; func_exit: if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); @@ -326,6 +423,7 @@ func_exit: return(err); } +#endif /* WITH_WSREP */ /*********************************************************************//** Creates an update node for a query graph. @@ -2015,123 +2113,6 @@ row_upd_clust_rec_by_insert_inherit_func( return(inherit); } -#ifdef WITH_WSREP -ulint -wsrep_row_upd_check_foreign_constraints( -/*=================================*/ - upd_node_t* node, /*!< in: row update node */ - btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the - cursor position is lost in this function! */ - dict_table_t* table, /*!< in: table in question */ - dict_index_t* index, /*!< in: index of the cursor */ - ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ - que_thr_t* thr, /*!< in: query thread */ - mtr_t* mtr) /*!< in: mtr */ -{ - dict_foreign_t* foreign; - mem_heap_t* heap; - dtuple_t* entry; - trx_t* trx; - const rec_t* rec; - ulint n_ext; - ulint err; - ibool got_s_lock = FALSE; - - if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { - - return(DB_SUCCESS); - } - - trx = thr_get_trx(thr); - - rec = btr_pcur_get_rec(pcur); - ut_ad(rec_offs_validate(rec, index, offsets)); - - heap = mem_heap_create(500); - - entry = row_rec_to_index_entry(rec, index, offsets, &n_ext, heap); - - mtr_commit(mtr); - - mtr_start(mtr); - - if (trx->dict_operation_lock_mode == 0) { - got_s_lock = TRUE; - - row_mysql_freeze_data_dictionary(trx); - } - - foreign = UT_LIST_GET_FIRST(table->foreign_list); - - while (foreign) { - /* Note that we may have an update which updates the index - record, but does NOT update the first fields which are - referenced in a foreign key constraint. Then the update does - NOT break the constraint. */ - - if (foreign->foreign_index == index - && (node->is_delete - || row_upd_changes_first_fields_binary( - entry, index, node->update, - foreign->n_fields))) { - - if (foreign->referenced_table == NULL) { - foreign->referenced_table = - dict_table_open_on_name( - foreign->referenced_table_name_lookup, - FALSE, FALSE, DICT_ERR_IGNORE_NONE); - } - - if (foreign->referenced_table) { - mutex_enter(&(dict_sys->mutex)); - - (foreign->referenced_table - ->n_foreign_key_checks_running)++; - - mutex_exit(&(dict_sys->mutex)); - } - - /* NOTE that if the thread ends up waiting for a lock - we will release dict_operation_lock temporarily! - But the counter on the table protects 'foreign' from - being dropped while the check is running. */ - - err = row_ins_check_foreign_constraint( - TRUE, foreign, table, entry, thr); - - if (foreign->referenced_table) { - mutex_enter(&(dict_sys->mutex)); - - ut_a(foreign->referenced_table - ->n_foreign_key_checks_running > 0); - - (foreign->referenced_table - ->n_foreign_key_checks_running)--; - - mutex_exit(&(dict_sys->mutex)); - } - - if (err != DB_SUCCESS) { - - goto func_exit; - } - } - - foreign = UT_LIST_GET_NEXT(foreign_list, foreign); - } - - err = DB_SUCCESS; -func_exit: - if (got_s_lock) { - row_mysql_unfreeze_data_dictionary(trx); - } - - mem_heap_free(heap); - - return(err); -} -#endif /* WITH_WSREP */ - /***********************************************************//** Marks the clustered index record deleted and inserts the updated version of the record to the index. This function should be used when the ordering diff --git a/storage/xtradb/trx/trx0sys.cc b/storage/xtradb/trx/trx0sys.cc index daa13b8b2c5..0a8d41c9a50 100644 --- a/storage/xtradb/trx/trx0sys.cc +++ b/storage/xtradb/trx/trx0sys.cc @@ -178,7 +178,12 @@ trx_sys_flush_max_trx_id(void) mtr_t mtr; trx_sysf_t* sys_header; +#ifndef WITH_WSREP + /* wsrep_fake_trx_id violates this assert + * Copied from trx_sys_get_new_trx_id + */ ut_ad(mutex_own(&trx_sys->mutex)); +#endif /* WITH_WSREP */ if (!srv_read_only_mode) { mtr_start(&mtr); |