Merging wsrep specific changes from InnoDB to

xtradb (r3683..3808).
This commit is contained in:
Nirbhay Choubey 2014-03-26 15:17:51 -04:00
commit 09e3094945
14 changed files with 456 additions and 296 deletions

View File

@ -16984,7 +16984,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
lock_cancel_waiting_and_release(wait_lock); lock_cancel_waiting_and_release(wait_lock);
} }
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
} else { } else {
/* abort currently executing query */ /* abort currently executing query */
@ -16992,7 +16991,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_thread_id(thd))); wsrep_thd_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld", WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd)); wsrep_thd_thread_id(thd));
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
/* for BF thd, we need to prevent him from committing */ /* for BF thd, we need to prevent him from committing */
@ -17049,16 +17047,15 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("signaling aborter"); WSREP_DEBUG("signaling aborter");
mysql_cond_signal(&COND_wsrep_rollback); mysql_cond_signal(&COND_wsrep_rollback);
mysql_mutex_unlock(&LOCK_wsrep_rollback); mysql_mutex_unlock(&LOCK_wsrep_rollback);
wsrep_thd_UNLOCK(thd);
break; break;
} }
default: default:
WSREP_WARN("bad wsrep query state: %d", WSREP_WARN("bad wsrep query state: %d",
wsrep_thd_query_state(thd)); wsrep_thd_query_state(thd));
wsrep_thd_UNLOCK(thd);
break; break;
} }
wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -4029,15 +4029,14 @@ lock_deadlock_select_victim(
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) { if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) {
return(ctx->start); return(ctx->start);
} }
#else #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
#endif
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) { if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
return(ctx->start); return(ctx->start);
} else
#endif #endif /* WITH_WSREP */
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
} }

View File

@ -1471,15 +1471,14 @@ innobase_srv_conc_exit_innodb(
/*==========================*/ /*==========================*/
trx_t* trx) /*!< in: transaction handle */ trx_t* trx) /*!< in: transaction handle */
{ {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) && if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) return; wsrep_thd_is_brute_force(trx->mysql_thd)) return;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
/* This is to avoid making an unnecessary function call. */ /* This is to avoid making an unnecessary function call. */
if (trx->declared_to_be_inside_innodb if (trx->declared_to_be_inside_innodb
&& trx->n_tickets_to_enter_innodb == 0) { && trx->n_tickets_to_enter_innodb == 0) {
@ -3968,6 +3967,11 @@ innobase_commit_low(
/*================*/ /*================*/
trx_t* trx) /*!< in: transaction handle */ trx_t* trx) /*!< in: transaction handle */
{ {
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
THD* thd = (THD*)trx->mysql_thd; THD* thd = (THD*)trx->mysql_thd;
const char* tmp = 0; const char* tmp = 0;
@ -3986,11 +3990,6 @@ innobase_commit_low(
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (trx_is_started(trx)) {
trx_commit_for_mysql(trx);
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
@ -6048,8 +6047,13 @@ wsrep_innobase_mysql_sort(
ut_a(str_length <= tmp_length); ut_a(str_length <= tmp_length);
memcpy(tmp_str, str, str_length); memcpy(tmp_str, str, str_length);
//tmp_length = charset->coll->strnxfrm(charset, str, str_length,
// tmp_str, str_length);
/* Note: in MySQL 5.6:
*/
tmp_length = charset->coll->strnxfrm(charset, str, str_length, tmp_length = charset->coll->strnxfrm(charset, str, str_length,
str_length, tmp_str, tmp_length, 0); str_length, tmp_str, tmp_length, 0);
/**/
DBUG_ASSERT(tmp_length == str_length); DBUG_ASSERT(tmp_length == str_length);
break; break;
@ -6592,10 +6596,10 @@ innobase_read_from_2_little_endian(
return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])))); return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
} }
#ifdef WITH_WSREP
/*******************************************************************//** /*******************************************************************//**
Stores a key value for a row to a buffer. Stores a key value for a row to a buffer.
@return key value length as stored in buff */ @return key value length as stored in buff */
#ifdef WITH_WSREP
UNIV_INTERN UNIV_INTERN
uint uint
wsrep_store_key_val_for_row( wsrep_store_key_val_for_row(
@ -8559,7 +8563,8 @@ func_exit:
innobase_active_small(); innobase_active_small();
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!err && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && if (error == DB_SUCCESS &&
wsrep_thd_exec_mode(user_thd) == LOCAL_STATE &&
wsrep_on(user_thd)) { wsrep_on(user_thd)) {
DBUG_PRINT("wsrep", ("update row key")); DBUG_PRINT("wsrep", ("update row key"));
@ -17830,8 +17835,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("kill query for: %ld", WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd)); wsrep_thd_thread_id(thd));
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu",
victim_trx->id); victim_trx->id);
@ -17848,6 +17851,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
case WSREP_WARNING: case WSREP_WARNING:
WSREP_DEBUG("cancel commit warning: %llu", WSREP_DEBUG("cancel commit warning: %llu",
victim_trx->id); victim_trx->id);
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
DBUG_RETURN(1); DBUG_RETURN(1);
break; break;
case WSREP_OK: case WSREP_OK:
@ -17865,6 +17870,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
break; break;
} }
} }
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal);
break; break;
case QUERY_EXEC: case QUERY_EXEC:
/* it is possible that victim trx is itself waiting for some /* it is possible that victim trx is itself waiting for some
@ -17883,7 +17890,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
lock_cancel_waiting_and_release(wait_lock); lock_cancel_waiting_and_release(wait_lock);
} }
wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
} else { } else {
/* abort currently executing query */ /* abort currently executing query */
@ -17891,7 +17897,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_thread_id(thd))); wsrep_thd_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld", WSREP_DEBUG("kill query for: %ld",
wsrep_thd_thread_id(thd)); wsrep_thd_thread_id(thd));
wsrep_thd_UNLOCK(thd);
/* Note that innobase_kill_connection will take lock_mutex /* Note that innobase_kill_connection will take lock_mutex
and trx_mutex */ and trx_mutex */
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
@ -17950,16 +17955,15 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
WSREP_DEBUG("signaling aborter"); WSREP_DEBUG("signaling aborter");
mysql_cond_signal(&COND_wsrep_rollback); mysql_cond_signal(&COND_wsrep_rollback);
mysql_mutex_unlock(&LOCK_wsrep_rollback); mysql_mutex_unlock(&LOCK_wsrep_rollback);
wsrep_thd_UNLOCK(thd);
break; break;
} }
default: default:
WSREP_WARN("bad wsrep query state: %d", WSREP_WARN("bad wsrep query state: %d",
wsrep_thd_query_state(thd)); wsrep_thd_query_state(thd));
wsrep_thd_UNLOCK(thd);
break; break;
} }
wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -458,6 +458,40 @@ __attribute__((nonnull));
extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
struct trx_t; struct trx_t;
#ifdef WITH_WSREP
#include <wsrep_mysqld.h>
//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd);
extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd);
extern "C" const char * wsrep_thd_exec_mode_str(THD *thd);
extern "C" const char * wsrep_thd_conflict_state_str(THD *thd);
extern "C" const char * wsrep_thd_query_state_str(THD *thd);
extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd);
extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
extern "C" void wsrep_thd_set_query_state(
THD *thd, enum wsrep_query_state state);
extern "C" void wsrep_thd_set_conflict_state(
THD *thd, enum wsrep_conflict_state state);
extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
extern "C"void wsrep_thd_LOCK(THD *thd);
extern "C"void wsrep_thd_UNLOCK(THD *thd);
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
extern "C" time_t wsrep_thd_query_start(THD *thd);
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
extern "C" int64_t wsrep_thd_trx_seqno(THD *thd);
extern "C" query_id_t wsrep_thd_query_id(THD *thd);
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);
#endif
extern const struct _ft_vft ft_vft_result; extern const struct _ft_vft ft_vft_result;
@ -495,6 +529,9 @@ innobase_index_name_is_reserved(
__attribute__((nonnull, warn_unused_result)); __attribute__((nonnull, warn_unused_result));
/*****************************************************************//** /*****************************************************************//**
#ifdef WITH_WSREP
extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
#endif
Determines InnoDB table flags. Determines InnoDB table flags.
@retval true if successful, false if error */ @retval true if successful, false if error */
UNIV_INTERN UNIV_INTERN
@ -657,35 +694,3 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/ /*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */ dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */ const TABLE_SHARE* table_share); /*!< in: table share */
#ifdef WITH_WSREP
#include <wsrep_mysqld.h>
//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd);
extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd);
extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd);
extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
extern "C" void wsrep_thd_set_query_state(
THD *thd, enum wsrep_query_state state);
extern "C" void wsrep_thd_set_conflict_state(
THD *thd, enum wsrep_conflict_state state);
extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
extern "C"void wsrep_thd_LOCK(THD *thd);
extern "C"void wsrep_thd_UNLOCK(THD *thd);
extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
extern "C" time_t wsrep_thd_query_start(THD *thd);
extern "C" my_thread_id wsrep_thd_thread_id(THD *thd);
extern "C" int64_t wsrep_thd_trx_seqno(THD *thd);
extern "C" query_id_t wsrep_thd_query_id(THD *thd);
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);
#endif

View File

@ -285,6 +285,19 @@ innobase_casedn_str(
/*================*/ /*================*/
char* a); /*!< in/out: string to put in lower case */ 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);
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);
int
wsrep_on(void *thd_ptr);
extern "C" int wsrep_is_wsrep_xid(const void*);
#endif /* WITH_WSREP */
/**********************************************************************//** /**********************************************************************//**
Determines the connection character set. Determines the connection character set.
@return connection character set */ @return connection character set */
@ -375,21 +388,6 @@ thd_flush_log_at_trx_commit(
/*================================*/ /*================================*/
void* thd); 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 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 mysqld.cc. We do a dirty read because for one there is no synchronization

View File

@ -255,7 +255,10 @@ mutex_enter_func(
ulint line) /*!< in: line where locked */ ulint line) /*!< in: line where locked */
{ {
ut_ad(mutex_validate(mutex)); ut_ad(mutex_validate(mutex));
#ifndef WITH_WSREP
/* this cannot be be granted when BF trx kills a trx in lock wait state */
ut_ad(!mutex_own(mutex)); ut_ad(!mutex_own(mutex));
#endif /* WITH_WSREP */
/* Note that we do not peek at the value of lock_word before trying /* Note that we do not peek at the value of lock_word before trying
the atomic test_and_set; we could peek, and possibly save time. */ the atomic test_and_set; we could peek, and possibly save time. */

View File

@ -41,10 +41,10 @@ Created 3/26/1996 Heikki Tuuri
#include "ut0bh.h" #include "ut0bh.h"
#include "read0types.h" #include "read0types.h"
#include "page0types.h" #include "page0types.h"
#include "ut0bh.h"
#ifdef WITH_WSREP #ifdef WITH_WSREP
#include "trx0xa.h" #include "trx0xa.h"
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#include "ut0bh.h"
typedef UT_LIST_BASE_NODE_T(trx_t) trx_list_t; typedef UT_LIST_BASE_NODE_T(trx_t) trx_list_t;
@ -328,6 +328,19 @@ UNIV_INTERN
void void
trx_sys_print_mysql_binlog_offset(void); trx_sys_print_mysql_binlog_offset(void);
/*===================================*/ /*===================================*/
#ifdef WITH_WSREP
/** Update WSREP checkpoint XID in sys header. */
void
trx_sys_update_wsrep_checkpoint(
const XID* xid, /*!< in: WSREP XID */
trx_sysf_t* sys_header, /*!< in: sys_header */
mtr_t* mtr); /*!< in: mtr */
void
/** Read WSREP checkpoint XID from sys header. */
trx_sys_read_wsrep_checkpoint(
XID* xid); /*!< out: WSREP XID */
#endif /* WITH_WSREP */
/*****************************************************************//** /*****************************************************************//**
Prints to stderr the MySQL master log offset info in the trx system header if Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */ the magic number shows it valid. */
@ -485,19 +498,6 @@ trx_sys_validate_trx_list(void);
/*===========================*/ /*===========================*/
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP
/** Update WSREP checkpoint XID in sys header. */
void
trx_sys_update_wsrep_checkpoint(
const XID* xid, /*!< in: WSREP XID */
trx_sysf_t* sys_header, /*!< in: sys_header */
mtr_t* mtr); /*!< in: mtr */
void
/** Read WSREP checkpoint XID from sys header. */
trx_sys_read_wsrep_checkpoint(
XID* xid); /*!< out: WSREP XID */
#endif /* WITH_WSREP */
/* The automatically created system rollback segment has this id */ /* The automatically created system rollback segment has this id */
#define TRX_SYS_SYSTEM_RSEG_ID 0 #define TRX_SYS_SYSTEM_RSEG_ID 0
@ -570,10 +570,8 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
#define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused /* The offset to WSREP XID headers */
otherwise (see comments for MySQL bug #34058). */ #define TRX_SYS_WSREP_XID_INFO (UNIV_PAGE_SIZE - 3500)
/** */
#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO
#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 #define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0
#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 #define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265

View File

@ -474,7 +474,10 @@ trx_id_t
trx_sys_get_new_trx_id(void) trx_sys_get_new_trx_id(void)
/*========================*/ /*========================*/
{ {
#ifndef WITH_WSREP
/* wsrep_fake_trx_id violates this assert */
ut_ad(mutex_own(&trx_sys->mutex)); ut_ad(mutex_own(&trx_sys->mutex));
#endif /* WITH_WSREP */
/* VERY important: after the database is started, max_trx_id value is /* VERY important: after the database is started, max_trx_id value is
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if

View File

@ -981,7 +981,6 @@ lock_rec_has_to_wait(
&& !lock_mode_compatible(static_cast<enum lock_mode>( && !lock_mode_compatible(static_cast<enum lock_mode>(
LOCK_MODE_MASK & type_mode), LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) { lock_get_mode(lock2))) {
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF /* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */ thread, we need to look at trx ordering and lock types */
@ -1630,14 +1629,13 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
static void static
wsrep_kill_victim(trx_t *trx, lock_t *lock) { void
wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad(trx_mutex_own(lock->trx)); ut_ad(trx_mutex_own(lock->trx));
my_bool bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); 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_other = wsrep_thd_is_brute_force(lock->trx->mysql_thd);
if ((bf_this && !bf_other) || if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before( (bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) { trx->mysql_thd, lock->trx->mysql_thd))) {
@ -1677,12 +1675,11 @@ wsrep_kill_victim(trx_t *trx, lock_t *lock) {
} }
} }
wsrep_innobase_kill_one_trx(trx->mysql_thd, wsrep_innobase_kill_one_trx(trx->mysql_thd,
(const trx_t*)trx, lock->trx, TRUE); (const trx_t*) trx, lock->trx, TRUE);
} }
} }
} }
#endif /* WITH_WSREP */ #endif
/*********************************************************************//** /*********************************************************************//**
Checks if some other transaction has a conflicting explicit lock request Checks if some other transaction has a conflicting explicit lock request
in the queue, so that we have to wait. in the queue, so that we have to wait.
@ -1719,6 +1716,7 @@ lock_rec_other_has_conflicting(
#else #else
if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) { if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) {
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(lock); return(lock);
} }
} }
@ -1940,8 +1938,8 @@ lock_rec_create(
lock->type_mode |= WSREP_BF; lock->type_mode |= WSREP_BF;
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
lock->index = index; lock->index = index;
lock->un_member.rec_lock.space = space; lock->un_member.rec_lock.space = space;
lock->un_member.rec_lock.page_no = page_no; lock->un_member.rec_lock.page_no = page_no;
lock->un_member.rec_lock.n_bits = n_bytes * 8; lock->un_member.rec_lock.n_bits = n_bytes * 8;
@ -2144,7 +2142,7 @@ lock_rec_enqueue_waiting(
lock = lock_rec_create( lock = lock_rec_create(
type_mode | LOCK_WAIT, block, heap_no, type_mode | LOCK_WAIT, block, heap_no,
index, trx, TRUE); index, trx, TRUE);
#endif /* WITH_WSREP */ #endif /*WITH_WSREP */
} else { } else {
ut_ad(lock->type_mode & LOCK_WAIT); ut_ad(lock->type_mode & LOCK_WAIT);
ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER); ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER);
@ -2401,7 +2399,8 @@ lock_rec_lock_fast(
#else #else
lock = lock_rec_create( lock = lock_rec_create(
mode, block, heap_no, index, trx, FALSE); mode, block, heap_no, index, trx, FALSE);
#endif /* WITH_WSREP */ #endif
} }
status = LOCK_REC_SUCCESS_CREATED; status = LOCK_REC_SUCCESS_CREATED;
} else { } else {
@ -2454,11 +2453,11 @@ lock_rec_lock_slow(
que_thr_t* thr) /*!< in: query thread */ que_thr_t* thr) /*!< in: query thread */
{ {
trx_t* trx; trx_t* trx;
#ifdef WITH_WSREP
lock_t* c_lock(NULL);
#endif
lock_t* lock; lock_t* lock;
dberr_t err = DB_SUCCESS; dberr_t err = DB_SUCCESS;
#ifdef WITH_WSREP
lock_t* c_lock = NULL;
#endif
ut_ad(lock_mutex_own()); ut_ad(lock_mutex_own());
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
@ -2533,6 +2532,7 @@ enqueue_waiting:
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
mode, block, heap_no, lock, index, thr); mode, block, heap_no, lock, index, thr);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
} else if (!impl) { } else if (!impl) {
/* Set the requested lock on the record, note that /* Set the requested lock on the record, note that
we already own the transaction mutex. */ we already own the transaction mutex. */
@ -4040,7 +4040,6 @@ lock_deadlock_select_victim(
if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) { if (trx_weight_ge(ctx->wait_lock->trx, ctx->start)) {
/* The joining transaction is 'smaller', /* The joining transaction is 'smaller',
choose it as the victim and roll it back. */ choose it as the victim and roll it back. */
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd))
return(ctx->start); return(ctx->start);
@ -4048,12 +4047,11 @@ lock_deadlock_select_victim(
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) { if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
return(ctx->start); return(ctx->start);
} else
#endif #endif /* WITH_WSREP */
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
} }
@ -4426,6 +4424,7 @@ lock_table_create(
ut_ad(table->n_ref_count > 0 || !table->can_be_evicted); ut_ad(table->n_ref_count > 0 || !table->can_be_evicted);
UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
UT_LIST_INSERT_AFTER( UT_LIST_INSERT_AFTER(
@ -4464,7 +4463,6 @@ lock_table_create(
} }
if (c_lock) trx_mutex_exit(c_lock->trx); if (c_lock) trx_mutex_exit(c_lock->trx);
#else #else
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */

View File

@ -919,7 +919,7 @@ row_ins_invalidate_query_cache(
mem_free(buf); mem_free(buf);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
ulint wsrep_append_foreign_key(trx_t *trx, dberr_t wsrep_append_foreign_key(trx_t *trx,
dict_foreign_t* foreign, dict_foreign_t* foreign,
const rec_t* clust_rec, const rec_t* clust_rec,
dict_index_t* clust_index, dict_index_t* clust_index,
@ -1278,13 +1278,12 @@ row_ins_foreign_check_on_constraint(
cascade->state = UPD_NODE_UPDATE_CLUSTERED; cascade->state = UPD_NODE_UPDATE_CLUSTERED;
#ifdef WITH_WSREP #ifdef WITH_WSREP
err = (dberr_t)wsrep_append_foreign_key( err = wsrep_append_foreign_key(
thr_get_trx(thr), thr_get_trx(thr),
foreign, foreign,
clust_rec, clust_rec,
clust_index, clust_index,
FALSE, FALSE); FALSE, FALSE);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err); "WSREP: foreign key append failed: %d\n", err);
@ -1629,7 +1628,7 @@ run_again:
if (check_ref) { if (check_ref) {
err = DB_SUCCESS; err = DB_SUCCESS;
#ifdef WITH_WSREP #ifdef WITH_WSREP
err = (dberr_t) wsrep_append_foreign_key( err = wsrep_append_foreign_key(
thr_get_trx(thr), thr_get_trx(thr),
foreign, foreign,
rec, rec,

View File

@ -176,25 +176,47 @@ func_exit:
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
ulint static
wsrep_append_foreign_key( ibool
trx_t* trx, wsrep_row_upd_index_is_foreign(
dict_foreign_t* foreign, /*========================*/
const rec_t* clust_rec, dict_index_t* index, /*!< in: index */
dict_index_t* clust_index, trx_t* trx) /*!< in: transaction */
ibool referenced, {
ibool shared); dict_table_t* table = index->table;
dict_foreign_t* foreign;
ibool froze_data_dict = FALSE;
ibool is_referenced = FALSE;
ulint if (!UT_LIST_GET_FIRST(table->foreign_list)) {
wsrep_row_upd_check_foreign_constraints(
upd_node_t* node, /*!< in: row update node */ return(FALSE);
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 */ if (trx->dict_operation_lock_mode == 0) {
dict_index_t* index, /*!< in: index of the cursor */ row_mysql_freeze_data_dictionary(trx);
ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ froze_data_dict = TRUE;
que_thr_t* thr, /*!< in: query thread */ }
mtr_t* mtr); /*!< in: mtr */
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign) {
if (foreign->foreign_index == index) {
is_referenced = TRUE;
goto func_exit;
}
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
func_exit:
if (froze_data_dict) {
row_mysql_unfreeze_data_dictionary(trx);
}
return(is_referenced);
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/*********************************************************************//** /*********************************************************************//**
@ -314,7 +336,123 @@ run_again:
} }
err = DB_SUCCESS; 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);
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: func_exit:
if (got_s_lock) { if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx); row_mysql_unfreeze_data_dictionary(trx);
@ -326,6 +464,7 @@ func_exit:
return(err); return(err);
} }
#endif /* WITH_WSREP */
/*********************************************************************//** /*********************************************************************//**
Creates an update node for a query graph. Creates an update node for a query graph.
@ -1700,6 +1839,9 @@ row_upd_sec_index_entry(
index = node->index; index = node->index;
referenced = row_upd_index_is_referenced(index, trx); referenced = row_upd_index_is_referenced(index, trx);
#ifdef WITH_WSREP
ibool foreign = wsrep_row_upd_index_is_foreign(index, trx);
#endif /* WITH_WSREP */
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
@ -1830,6 +1972,9 @@ row_upd_sec_index_entry(
row_ins_sec_index_entry() below */ row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag( if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) { rec, dict_table_is_comp(index->table))) {
#ifdef WITH_WSREP
que_node_t *parent = que_node_get_parent(node);
#endif /* WITH_WSREP */
err = btr_cur_del_mark_set_sec_rec( err = btr_cur_del_mark_set_sec_rec(
0, btr_cur, TRUE, thr, &mtr); 0, btr_cur, TRUE, thr, &mtr);
@ -1848,29 +1993,32 @@ row_upd_sec_index_entry(
index, offsets, thr, &mtr); index, offsets, thr, &mtr);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (err == DB_SUCCESS && !referenced) { if (err == DB_SUCCESS && !referenced &&
!(parent && que_node_get_type(parent) ==
QUE_NODE_UPDATE &&
((upd_node_t*)parent)->cascade_node == node) &&
foreign
) {
ulint* offsets = ulint* offsets =
rec_get_offsets( rec_get_offsets(
rec, index, NULL, ULINT_UNDEFINED, rec, index, NULL, ULINT_UNDEFINED,
&heap); &heap);
err = (dberr_t) wsrep_row_upd_check_foreign_constraints( err = wsrep_row_upd_check_foreign_constraints(
node, &pcur, index->table, node, &pcur, index->table,
index, offsets, thr, &mtr); index, offsets, thr, &mtr);
switch (err) { switch (err) {
case DB_SUCCESS: case DB_SUCCESS:
case DB_NO_REFERENCED_ROW: case DB_NO_REFERENCED_ROW:
err = DB_SUCCESS; err = DB_SUCCESS;
break; break;
case DB_DEADLOCK: case DB_DEADLOCK:
if (wsrep_debug) if (wsrep_debug) fprintf (stderr,
fprintf (stderr,
"WSREP: sec index FK check fail for deadlock"); "WSREP: sec index FK check fail for deadlock");
break; break;
default: default:
fprintf (stderr, fprintf (stderr,
"WSREP: referenced FK check fail: %d", "WSREP: referenced FK check fail: %d",
err); (int)err);
break; break;
} }
} }
@ -2015,123 +2163,6 @@ row_upd_clust_rec_by_insert_inherit_func(
return(inherit); 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 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 of the record to the index. This function should be used when the ordering
@ -2148,6 +2179,9 @@ row_upd_clust_rec_by_insert(
que_thr_t* thr, /*!< in: query thread */ que_thr_t* thr, /*!< in: query thread */
ibool referenced,/*!< in: TRUE if index may be referenced in ibool referenced,/*!< in: TRUE if index may be referenced in
a foreign key constraint */ a foreign key constraint */
#ifdef WITH_WSREP
ibool foreign, /*!< in: TRUE if index is foreign key index */
#endif /* WITH_WSREP */
mtr_t* mtr) /*!< in/out: mtr; gets committed here */ mtr_t* mtr) /*!< in/out: mtr; gets committed here */
{ {
mem_heap_t* heap; mem_heap_t* heap;
@ -2161,6 +2195,9 @@ row_upd_clust_rec_by_insert(
rec_t* rec; rec_t* rec;
ulint* offsets = NULL; ulint* offsets = NULL;
#ifdef WITH_WSREP
que_node_t *parent = que_node_get_parent(node);
#endif /* WITH_WSREP */
ut_ad(node); ut_ad(node);
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
@ -2241,10 +2278,13 @@ err_exit:
} }
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (!referenced) { if (!referenced &&
err = (dberr_t) wsrep_row_upd_check_foreign_constraints( !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE &&
((upd_node_t*)parent)->cascade_node == node) &&
foreign
) {
err = wsrep_row_upd_check_foreign_constraints(
node, pcur, table, index, offsets, thr, mtr); node, pcur, table, index, offsets, thr, mtr);
switch (err) { switch (err) {
case DB_SUCCESS: case DB_SUCCESS:
case DB_NO_REFERENCED_ROW: case DB_NO_REFERENCED_ROW:
@ -2257,7 +2297,7 @@ err_exit:
default: default:
fprintf (stderr, fprintf (stderr,
"WSREP: referenced FK check fail: %d", "WSREP: referenced FK check fail: %d",
err); (int)err);
break; break;
} }
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
@ -2495,6 +2535,9 @@ row_upd_del_mark_clust_rec(
ibool referenced, ibool referenced,
/*!< in: TRUE if index may be referenced in /*!< in: TRUE if index may be referenced in
a foreign key constraint */ a foreign key constraint */
#ifdef WITH_WSREP
ibool foreign,/*!< in: TRUE if index is foreign key index */
#endif /* WITH_WSREP */
mtr_t* mtr) /*!< in: mtr; gets committed here */ mtr_t* mtr) /*!< in: mtr; gets committed here */
{ {
btr_pcur_t* pcur; btr_pcur_t* pcur;
@ -2502,6 +2545,7 @@ row_upd_del_mark_clust_rec(
dberr_t err; dberr_t err;
#ifdef WITH_WSREP #ifdef WITH_WSREP
rec_t* rec; rec_t* rec;
que_node_t *parent = que_node_get_parent(node);
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
ut_ad(node); ut_ad(node);
@ -2524,25 +2568,27 @@ row_upd_del_mark_clust_rec(
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
err = btr_cur_del_mark_set_clust_rec( err = btr_cur_del_mark_set_clust_rec(
btr_cur_get_block(btr_cur),
#ifdef WITH_WSREP #ifdef WITH_WSREP
rec, index, offsets, thr, mtr); btr_cur_get_block(btr_cur), rec,
#else #else
btr_cur_get_rec(btr_cur), index, offsets, thr, mtr); btr_cur_get_block(btr_cur), btr_cur_get_rec(btr_cur),
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
index, offsets, thr, mtr);
if (err == DB_SUCCESS && referenced) { if (err == DB_SUCCESS && referenced) {
/* NOTE that the following call loses the position of pcur ! */ /* NOTE that the following call loses the position of pcur ! */
err = row_upd_check_references_constraints( err = row_upd_check_references_constraints(
node, pcur, index->table, index, offsets, thr, mtr); node, pcur, index->table, index, offsets, thr, mtr);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (err == DB_SUCCESS && !referenced) { if (err == DB_SUCCESS && !referenced &&
err = (dberr_t) wsrep_row_upd_check_foreign_constraints( !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE &&
((upd_node_t*)parent)->cascade_node == node) &&
thr_get_trx(thr) &&
foreign
) {
err = wsrep_row_upd_check_foreign_constraints(
node, pcur, index->table, index, offsets, thr, mtr); node, pcur, index->table, index, offsets, thr, mtr);
switch (err) { switch (err) {
case DB_SUCCESS: case DB_SUCCESS:
case DB_NO_REFERENCED_ROW: case DB_NO_REFERENCED_ROW:
@ -2554,8 +2600,8 @@ row_upd_del_mark_clust_rec(
break; break;
default: default:
fprintf (stderr, fprintf (stderr,
"WSREP: clust rec referenced FK check fail: %u", "WSREP: clust rec referenced FK check fail: %d",
err); (int)err);
break; break;
} }
} }
@ -2592,6 +2638,10 @@ row_upd_clust_step(
index = dict_table_get_first_index(node->table); index = dict_table_get_first_index(node->table);
referenced = row_upd_index_is_referenced(index, thr_get_trx(thr)); referenced = row_upd_index_is_referenced(index, thr_get_trx(thr));
#ifdef WITH_WSREP
ibool foreign = wsrep_row_upd_index_is_foreign(
index, thr_get_trx(thr));
#endif /* WITH_WSREP */
pcur = node->pcur; pcur = node->pcur;
@ -2688,7 +2738,11 @@ row_upd_clust_step(
if (node->is_delete) { if (node->is_delete) {
err = row_upd_del_mark_clust_rec( err = row_upd_del_mark_clust_rec(
#ifdef WITH_WSREP
node, index, offsets, thr, referenced, foreign, &mtr);
#else
node, index, offsets, thr, referenced, &mtr); node, index, offsets, thr, referenced, &mtr);
#endif /* WITH_WSREP */
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
node->state = UPD_NODE_UPDATE_ALL_SEC; node->state = UPD_NODE_UPDATE_ALL_SEC;
@ -2733,7 +2787,11 @@ row_upd_clust_step(
externally! */ externally! */
err = row_upd_clust_rec_by_insert( err = row_upd_clust_rec_by_insert(
#ifdef WITH_WSREP
node, index, thr, referenced, foreign, &mtr);
#else
node, index, thr, referenced, &mtr); node, index, thr, referenced, &mtr);
#endif /* WITH_WSREP */
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {

View File

@ -91,6 +91,9 @@ struct srv_conc_slot_t{
reserved may still be TRUE at that reserved may still be TRUE at that
point */ point */
srv_conc_node_t srv_conc_queue; /*!< queue node */ srv_conc_node_t srv_conc_queue; /*!< queue node */
#ifdef WITH_WSREP
void *thd; /*!< to see priority */
#endif
}; };
/** Queue of threads waiting to get in */ /** Queue of threads waiting to get in */
@ -150,6 +153,9 @@ srv_conc_init(void)
conc_slot->event = os_event_create(); conc_slot->event = os_event_create();
ut_a(conc_slot->event); ut_a(conc_slot->event);
#ifdef WITH_WSREP
conc_slot->thd = NULL;
#endif /* WITH_WSREP */
} }
#endif /* !HAVE_ATOMIC_BUILTINS */ #endif /* !HAVE_ATOMIC_BUILTINS */
} }
@ -207,6 +213,16 @@ srv_conc_enter_innodb_with_atomics(
for (;;) { for (;;) {
ulint sleep_in_us; ulint sleep_in_us;
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_trx_is_aborting(trx->mysql_thd)) {
if (wsrep_debug)
fprintf(stderr,
"srv_conc_enter due to MUST_ABORT");
srv_conc_force_enter_innodb(trx);
return;
}
#endif /* WITH_WSREP */
if (srv_conc.n_active < (lint) srv_thread_concurrency) { if (srv_conc.n_active < (lint) srv_thread_concurrency) {
ulint n_active; ulint n_active;
@ -325,6 +341,9 @@ srv_conc_exit_innodb_without_atomics(
slot = NULL; slot = NULL;
if (srv_conc.n_active < (lint) srv_thread_concurrency) { if (srv_conc.n_active < (lint) srv_thread_concurrency) {
#ifdef WITH_WSREP
srv_conc_slot_t* wsrep_slot;
#endif
/* Look for a slot where a thread is waiting and no other /* Look for a slot where a thread is waiting and no other
thread has yet released the thread */ thread has yet released the thread */
@ -335,6 +354,19 @@ srv_conc_exit_innodb_without_atomics(
/* No op */ /* No op */
} }
#ifdef WITH_WSREP
/* look for aborting trx, they must be released asap */
wsrep_slot= slot;
while (wsrep_slot && (wsrep_slot->wait_ended == TRUE ||
!wsrep_trx_is_aborting(wsrep_slot->thd))) {
wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot);
}
if (wsrep_slot) {
slot = wsrep_slot;
if (wsrep_debug)
fprintf(stderr, "WSREP: releasing aborting thd\n");
}
#endif
if (slot != NULL) { if (slot != NULL) {
slot->wait_ended = TRUE; slot->wait_ended = TRUE;
@ -394,6 +426,13 @@ retry:
return; return;
} }
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) {
srv_conc_force_enter_innodb(trx);
return;
}
#endif
/* If the transaction is not holding resources, let it sleep /* If the transaction is not holding resources, let it sleep
for srv_thread_sleep_delay microseconds, and try again then */ for srv_thread_sleep_delay microseconds, and try again then */
@ -461,6 +500,9 @@ retry:
/* Add to the queue */ /* Add to the queue */
slot->reserved = TRUE; slot->reserved = TRUE;
slot->wait_ended = FALSE; slot->wait_ended = FALSE;
#ifdef WITH_WSREP
slot->thd = trx->mysql_thd;
#endif
UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
@ -468,6 +510,18 @@ retry:
srv_conc.n_waiting++; srv_conc.n_waiting++;
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_trx_is_aborting(trx->mysql_thd)) {
os_fast_mutex_unlock(&srv_conc_mutex);
if (wsrep_debug)
fprintf(stderr, "srv_conc_enter due to MUST_ABORT");
trx->declared_to_be_inside_innodb = TRUE;
trx->n_tickets_to_enter_innodb = srv_n_free_tickets_to_enter;
return;
}
trx->wsrep_event = slot->event;
#endif /* WITH_WSREP */
os_fast_mutex_unlock(&srv_conc_mutex); os_fast_mutex_unlock(&srv_conc_mutex);
/* Go to wait for the event; when a thread leaves InnoDB it will /* Go to wait for the event; when a thread leaves InnoDB it will
@ -491,6 +545,9 @@ retry:
os_event_wait(slot->event); os_event_wait(slot->event);
thd_wait_end(trx->mysql_thd); thd_wait_end(trx->mysql_thd);
#ifdef WITH_WSREP
trx->wsrep_event = NULL;
#endif /* WITH_WSREP */
trx->op_info = ""; trx->op_info = "";
@ -508,6 +565,9 @@ retry:
incremented the thread counter on behalf of this thread */ incremented the thread counter on behalf of this thread */
slot->reserved = FALSE; slot->reserved = FALSE;
#ifdef WITH_WSREP
slot->thd = NULL;
#endif
UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);

View File

@ -213,7 +213,8 @@ trx_sys_update_mysql_binlog_offset(
{ {
#ifndef WITH_WSREP #ifndef WITH_WSREP
trx_sysf_t* sys_header; trx_sysf_t* sys_header;
#endif #endif /* !WITH_WSREP */
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) { if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
/* We cannot fit the name to the 512 bytes we have reserved */ /* We cannot fit the name to the 512 bytes we have reserved */
@ -223,7 +224,7 @@ trx_sys_update_mysql_binlog_offset(
#ifndef WITH_WSREP #ifndef WITH_WSREP
sys_header = trx_sysf_get(mtr); sys_header = trx_sysf_get(mtr);
#endif #endif /* !WITH_WSREP */
if (mach_read_from_4(sys_header + field if (mach_read_from_4(sys_header + field
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD) + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
@ -312,12 +313,49 @@ trx_sys_print_mysql_binlog_offset(void)
#ifdef WITH_WSREP #ifdef WITH_WSREP
#ifdef UNIV_DEBUG
static long long trx_sys_cur_xid_seqno = -1;
static unsigned char trx_sys_cur_xid_uuid[16];
long long read_wsrep_xid_seqno(const XID* xid)
{
long long seqno;
memcpy(&seqno, xid->data + 24, sizeof(long long));
return seqno;
}
void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf)
{
memcpy(buf, xid->data + 8, 16);
}
#endif /* UNIV_DEBUG */
void void
trx_sys_update_wsrep_checkpoint( trx_sys_update_wsrep_checkpoint(
const XID* xid, /*!< in: transaction XID */ const XID* xid, /*!< in: transaction XID */
trx_sysf_t* sys_header, /*!< in: sys_header */ trx_sysf_t* sys_header, /*!< in: sys_header */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */
{ {
#ifdef UNIV_DEBUG
{
/* Check that seqno is monotonically increasing */
unsigned char xid_uuid[16];
long long xid_seqno = read_wsrep_xid_seqno(xid);
read_wsrep_xid_uuid(xid, xid_uuid);
if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8))
{
ut_ad(xid_seqno > trx_sys_cur_xid_seqno);
trx_sys_cur_xid_seqno = xid_seqno;
}
else
{
memcpy(trx_sys_cur_xid_uuid, xid_uuid, 16);
}
trx_sys_cur_xid_seqno = xid_seqno;
}
#endif /* UNIV_DEBUG */
ut_ad(xid && mtr); ut_ad(xid && mtr);
ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid((const void *)xid)); ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid((const void *)xid));