* bzr merge -r4027..4061 codership/5.6

* Merged Innodb changes to xtradb
This commit is contained in:
Nirbhay Choubey 2014-03-26 11:12:38 -04:00
parent 7d892f69a5
commit b5871a51e9
28 changed files with 520 additions and 509 deletions

View file

@ -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()

View file

@ -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 "")
@ -647,10 +647,6 @@ then
[[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE"
[[ -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 "")
@ -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

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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 : "") : "");
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
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);
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 : "") : "");
const char* binlog_opt= "";
char* binlog_opt_val= NULL;
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 : "");
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)
{

View file

@ -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;

View file

@ -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 */

View file

@ -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,

View file

@ -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);

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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

View file

@ -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));

View file

@ -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);

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);