mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Merging InnoDB changes to xtradb (r3783..3808).
This commit is contained in:
parent
7b57c5ea6f
commit
71dafbf9c2
14 changed files with 485 additions and 330 deletions
|
@ -16826,7 +16826,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
lock_cancel_waiting_and_release(wait_lock);
|
||||
}
|
||||
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
} else {
|
||||
/* abort currently executing query */
|
||||
|
@ -16834,7 +16833,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
wsrep_thd_thread_id(thd)));
|
||||
WSREP_DEBUG("kill query for: %ld",
|
||||
wsrep_thd_thread_id(thd));
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
|
||||
/* for BF thd, we need to prevent him from committing */
|
||||
|
@ -16891,16 +16889,15 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
WSREP_DEBUG("signaling aborter");
|
||||
mysql_cond_signal(&COND_wsrep_rollback);
|
||||
mysql_mutex_unlock(&LOCK_wsrep_rollback);
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WSREP_WARN("bad wsrep query state: %d",
|
||||
wsrep_thd_query_state(thd));
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
break;
|
||||
}
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
|
@ -4026,15 +4026,14 @@ lock_deadlock_select_victim(
|
|||
if (!wsrep_thd_is_brute_force(ctx->start->mysql_thd)) {
|
||||
return(ctx->start);
|
||||
}
|
||||
#else
|
||||
#endif /* WITH_WSREP */
|
||||
return(ctx->start);
|
||||
#endif
|
||||
}
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
#endif /* WITH_WSREP */
|
||||
return(ctx->wait_lock->trx);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,26 +147,6 @@ extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key,
|
|||
extern handlerton * wsrep_hton;
|
||||
extern TC_LOG* tc_log;
|
||||
extern void wsrep_cleanup_transaction(THD *thd);
|
||||
|
||||
static int
|
||||
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
|
||||
my_bool signal);
|
||||
static void
|
||||
wsrep_fake_trx_id(handlerton* hton, THD *thd);
|
||||
static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
|
||||
static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
dict_index_t*
|
||||
wsrep_dict_foreign_find_index(
|
||||
dict_table_t* table,
|
||||
const char** col_names,
|
||||
const char** columns,
|
||||
ulint n_cols,
|
||||
dict_index_t* types_idx,
|
||||
ibool check_charsets,
|
||||
ulint check_null);
|
||||
|
||||
#endif /* WITH_WSREP */
|
||||
/** to protect innobase_open_files */
|
||||
static mysql_mutex_t innobase_share_mutex;
|
||||
|
@ -1447,10 +1427,9 @@ innobase_srv_conc_enter_innodb(
|
|||
trx_t* trx) /*!< in: transaction handle */
|
||||
{
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_on(trx->mysql_thd) &&
|
||||
if (wsrep_on(trx->mysql_thd) &&
|
||||
wsrep_thd_is_brute_force(trx->mysql_thd)) return;
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
if (srv_thread_concurrency) {
|
||||
if (trx->n_tickets_to_enter_innodb > 0) {
|
||||
|
||||
|
@ -1482,14 +1461,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_brute_force(trx->mysql_thd)) return;
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/* This is to avoid making an unnecessary function call. */
|
||||
if (trx->declared_to_be_inside_innodb
|
||||
|
@ -1672,6 +1650,15 @@ innobase_release_temporary_latches(
|
|||
return(0);
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
static int
|
||||
wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
|
||||
my_bool signal);
|
||||
static void
|
||||
wsrep_fake_trx_id(handlerton* hton, THD *thd);
|
||||
static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
|
||||
static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
|
||||
#endif
|
||||
/********************************************************************//**
|
||||
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
|
||||
time calls srv_active_wake_master_thread. This function should be used
|
||||
|
@ -3920,6 +3907,11 @@ 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;
|
||||
|
@ -3938,11 +3930,6 @@ innobase_commit_low(
|
|||
}
|
||||
#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 */
|
||||
|
@ -6000,8 +5987,13 @@ wsrep_innobase_mysql_sort(
|
|||
ut_a(str_length <= tmp_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,
|
||||
str_length, tmp_str, tmp_length, 0);
|
||||
str_length, tmp_str, tmp_length, 0);
|
||||
/**/
|
||||
DBUG_ASSERT(tmp_length == str_length);
|
||||
|
||||
break;
|
||||
|
@ -6543,10 +6535,10 @@ innobase_read_from_2_little_endian(
|
|||
return((uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1]))));
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
/*******************************************************************//**
|
||||
Stores a key value for a row to a buffer.
|
||||
@return key value length as stored in buff */
|
||||
#ifdef WITH_WSREP
|
||||
UNIV_INTERN
|
||||
uint
|
||||
wsrep_store_key_val_for_row(
|
||||
|
@ -8506,7 +8498,8 @@ func_exit:
|
|||
innobase_active_small();
|
||||
|
||||
#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)) {
|
||||
|
||||
DBUG_PRINT("wsrep", ("update row key"));
|
||||
|
@ -9777,9 +9770,18 @@ ha_innobase::ft_end()
|
|||
|
||||
rnd_end();
|
||||
}
|
||||
#ifdef WITH_WSREP
|
||||
extern dict_index_t*
|
||||
wsrep_dict_foreign_find_index(
|
||||
dict_table_t* table,
|
||||
const char** columns,
|
||||
ulint n_cols,
|
||||
dict_index_t* types_idx,
|
||||
ibool check_charsets,
|
||||
ulint check_null);
|
||||
|
||||
extern
|
||||
dberr_t
|
||||
|
||||
extern dberr_t
|
||||
wsrep_append_foreign_key(
|
||||
/*===========================*/
|
||||
trx_t* trx, /*!< in: trx */
|
||||
|
@ -9809,7 +9811,7 @@ wsrep_append_foreign_key(
|
|||
((!foreign->referenced_table) ?
|
||||
"referenced table" : "foreign table")),
|
||||
(thd && wsrep_thd_query(thd)) ?
|
||||
wsrep_thd_query(thd) : "void");
|
||||
wsrep_thd_query(thd) : "void");
|
||||
return DB_ERROR;
|
||||
}
|
||||
|
||||
|
@ -10004,7 +10006,7 @@ wsrep_append_key(
|
|||
WSREP_WARN("Appending row key failed: %s, %d",
|
||||
(wsrep_thd_query(thd)) ?
|
||||
wsrep_thd_query(thd) : "void", rcode);
|
||||
DBUG_RETURN(-1);
|
||||
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -17831,8 +17833,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
|
||||
WSREP_DEBUG("kill query for: %ld",
|
||||
wsrep_thd_thread_id(thd));
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu",
|
||||
victim_trx->id);
|
||||
|
||||
|
@ -17849,6 +17849,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
case WSREP_WARNING:
|
||||
WSREP_DEBUG("cancel commit warning: %llu",
|
||||
victim_trx->id);
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
DBUG_RETURN(1);
|
||||
break;
|
||||
case WSREP_OK:
|
||||
|
@ -17866,6 +17868,8 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
break;
|
||||
}
|
||||
}
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
break;
|
||||
case QUERY_EXEC:
|
||||
/* it is possible that victim trx is itself waiting for some
|
||||
|
@ -17884,7 +17888,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
lock_cancel_waiting_and_release(wait_lock);
|
||||
}
|
||||
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
wsrep_thd_awake(thd, signal);
|
||||
} else {
|
||||
/* abort currently executing query */
|
||||
|
@ -17892,7 +17895,6 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
wsrep_thd_thread_id(thd)));
|
||||
WSREP_DEBUG("kill query for: %ld",
|
||||
wsrep_thd_thread_id(thd));
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
/* Note that innobase_kill_connection will take lock_mutex
|
||||
and trx_mutex */
|
||||
wsrep_thd_awake(thd, signal);
|
||||
|
@ -17951,16 +17953,15 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
|
|||
WSREP_DEBUG("signaling aborter");
|
||||
mysql_cond_signal(&COND_wsrep_rollback);
|
||||
mysql_mutex_unlock(&LOCK_wsrep_rollback);
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WSREP_WARN("bad wsrep query state: %d",
|
||||
wsrep_thd_query_state(thd));
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
break;
|
||||
}
|
||||
wsrep_thd_UNLOCK(thd);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
|
@ -458,6 +458,40 @@ __attribute__((nonnull));
|
|||
extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file);
|
||||
|
||||
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;
|
||||
|
||||
|
@ -495,6 +529,9 @@ innobase_index_name_is_reserved(
|
|||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/*****************************************************************//**
|
||||
#ifdef WITH_WSREP
|
||||
extern "C" int wsrep_trx_is_aborting(void *thd_ptr);
|
||||
#endif
|
||||
Determines InnoDB table flags.
|
||||
@retval true if successful, false if error */
|
||||
UNIV_INTERN
|
||||
|
@ -657,35 +694,3 @@ innobase_copy_frm_flags_from_table_share(
|
|||
/*=====================================*/
|
||||
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
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.
|
||||
@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
|
||||
|
|
|
@ -256,7 +256,10 @@ mutex_enter_func(
|
|||
ulint line) /*!< in: line where locked */
|
||||
{
|
||||
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));
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/* 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. */
|
||||
|
|
|
@ -41,10 +41,10 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "ut0bh.h"
|
||||
#include "read0types.h"
|
||||
#include "page0types.h"
|
||||
#include "ut0bh.h"
|
||||
#ifdef WITH_WSREP
|
||||
#include "trx0xa.h"
|
||||
#endif /* WITH_WSREP */
|
||||
#include "ut0bh.h"
|
||||
|
||||
typedef UT_LIST_BASE_NODE_T(trx_t) trx_list_t;
|
||||
|
||||
|
@ -328,6 +328,19 @@ UNIV_INTERN
|
|||
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
|
||||
the magic number shows it valid. */
|
||||
|
@ -485,19 +498,6 @@ trx_sys_validate_trx_list(void);
|
|||
/*===========================*/
|
||||
#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 */
|
||||
#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 */
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused
|
||||
otherwise (see comments for MySQL bug #34058). */
|
||||
/** */
|
||||
#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
/* The offset to WSREP XID headers */
|
||||
#define TRX_SYS_WSREP_XID_INFO (UNIV_PAGE_SIZE - 3500)
|
||||
#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0
|
||||
#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265
|
||||
|
||||
|
|
|
@ -474,7 +474,10 @@ trx_id_t
|
|||
trx_sys_get_new_trx_id(void)
|
||||
/*========================*/
|
||||
{
|
||||
#ifndef WITH_WSREP
|
||||
/* wsrep_fake_trx_id violates this assert */
|
||||
ut_ad(mutex_own(&trx_sys->mutex));
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/* VERY important: after the database is started, max_trx_id value is
|
||||
divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the following if
|
||||
|
|
|
@ -981,7 +981,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 */
|
||||
|
@ -1021,7 +1020,7 @@ lock_rec_has_to_wait(
|
|||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/* We have somewhat complex rules when gap type record locks
|
||||
|
@ -1630,14 +1629,13 @@ lock_rec_other_has_expl_req(
|
|||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
static void
|
||||
wsrep_kill_victim(trx_t *trx, lock_t *lock) {
|
||||
static
|
||||
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);
|
||||
|
||||
if ((bf_this && !bf_other) ||
|
||||
(bf_this && bf_other && wsrep_trx_order_before(
|
||||
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,
|
||||
(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
|
||||
in the queue, so that we have to wait.
|
||||
|
@ -1719,6 +1716,7 @@ lock_rec_other_has_conflicting(
|
|||
#else
|
||||
if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) {
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
return(lock);
|
||||
}
|
||||
}
|
||||
|
@ -1879,7 +1877,7 @@ lock_t*
|
|||
lock_rec_create(
|
||||
/*============*/
|
||||
#ifdef WITH_WSREP
|
||||
lock_t* const c_lock, /* conflicting lock */
|
||||
lock_t* const c_lock, /* conflicting lock */
|
||||
que_thr_t* thr,
|
||||
#endif
|
||||
ulint type_mode,/*!< in: lock mode and wait
|
||||
|
@ -1940,8 +1938,8 @@ lock_rec_create(
|
|||
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;
|
||||
|
@ -2144,7 +2142,7 @@ lock_rec_enqueue_waiting(
|
|||
lock = lock_rec_create(
|
||||
type_mode | LOCK_WAIT, block, heap_no,
|
||||
index, trx, TRUE);
|
||||
#endif /* WITH_WSREP */
|
||||
#endif /*WITH_WSREP */
|
||||
} else {
|
||||
ut_ad(lock->type_mode & LOCK_WAIT);
|
||||
ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER);
|
||||
|
@ -2401,7 +2399,8 @@ lock_rec_lock_fast(
|
|||
#else
|
||||
lock = lock_rec_create(
|
||||
mode, block, heap_no, index, trx, FALSE);
|
||||
#endif /* WITH_WSREP */
|
||||
#endif
|
||||
|
||||
}
|
||||
status = LOCK_REC_SUCCESS_CREATED;
|
||||
} else {
|
||||
|
@ -2454,11 +2453,11 @@ lock_rec_lock_slow(
|
|||
que_thr_t* thr) /*!< in: query thread */
|
||||
{
|
||||
trx_t* trx;
|
||||
#ifdef WITH_WSREP
|
||||
lock_t* c_lock(NULL);
|
||||
#endif
|
||||
lock_t* lock;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
#ifdef WITH_WSREP
|
||||
lock_t* c_lock = NULL;
|
||||
#endif
|
||||
|
||||
ut_ad(lock_mutex_own());
|
||||
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
|
||||
|
@ -2533,6 +2532,7 @@ enqueue_waiting:
|
|||
err = lock_rec_enqueue_waiting(
|
||||
mode, block, heap_no, lock, index, thr);
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
} else if (!impl) {
|
||||
/* Set the requested lock on the record, note that
|
||||
we already own the transaction mutex. */
|
||||
|
@ -4040,20 +4040,18 @@ 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
|
||||
#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
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd))
|
||||
return(ctx->start);
|
||||
else
|
||||
#endif /* WITH_WSREP */
|
||||
return(ctx->wait_lock->trx);
|
||||
}
|
||||
|
||||
|
@ -4426,6 +4424,7 @@ 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)) {
|
||||
UT_LIST_INSERT_AFTER(
|
||||
|
@ -4464,7 +4463,6 @@ lock_table_create(
|
|||
}
|
||||
if (c_lock) trx_mutex_exit(c_lock->trx);
|
||||
#else
|
||||
|
||||
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
|
|
|
@ -919,7 +919,7 @@ row_ins_invalidate_query_cache(
|
|||
mem_free(buf);
|
||||
}
|
||||
#ifdef WITH_WSREP
|
||||
ulint wsrep_append_foreign_key(trx_t *trx,
|
||||
dberr_t wsrep_append_foreign_key(trx_t *trx,
|
||||
dict_foreign_t* foreign,
|
||||
const rec_t* clust_rec,
|
||||
dict_index_t* clust_index,
|
||||
|
@ -1278,20 +1278,19 @@ row_ins_foreign_check_on_constraint(
|
|||
cascade->state = UPD_NODE_UPDATE_CLUSTERED;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
err = (dberr_t)wsrep_append_foreign_key(
|
||||
thr_get_trx(thr),
|
||||
foreign,
|
||||
clust_rec,
|
||||
clust_index,
|
||||
FALSE, FALSE);
|
||||
|
||||
err = wsrep_append_foreign_key(
|
||||
thr_get_trx(thr),
|
||||
foreign,
|
||||
clust_rec,
|
||||
clust_index,
|
||||
FALSE, FALSE);
|
||||
if (err != DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
"WSREP: foreign key append failed: %d\n", err);
|
||||
} else
|
||||
#endif /* WITH_WSREP */
|
||||
err = row_update_cascade_for_mysql(thr, cascade,
|
||||
foreign->foreign_table);
|
||||
foreign->foreign_table);
|
||||
|
||||
if (foreign->foreign_table->n_foreign_key_checks_running == 0) {
|
||||
fprintf(stderr,
|
||||
|
@ -1629,11 +1628,11 @@ run_again:
|
|||
if (check_ref) {
|
||||
err = DB_SUCCESS;
|
||||
#ifdef WITH_WSREP
|
||||
err = (dberr_t) wsrep_append_foreign_key(
|
||||
err = wsrep_append_foreign_key(
|
||||
thr_get_trx(thr),
|
||||
foreign,
|
||||
rec,
|
||||
check_index,
|
||||
rec,
|
||||
check_index,
|
||||
check_ref, TRUE);
|
||||
#endif /* WITH_WSREP */
|
||||
goto end_scan;
|
||||
|
|
|
@ -176,25 +176,47 @@ func_exit:
|
|||
}
|
||||
|
||||
#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);
|
||||
static
|
||||
ibool
|
||||
wsrep_row_upd_index_is_foreign(
|
||||
/*========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
trx_t* trx) /*!< in: transaction */
|
||||
{
|
||||
dict_table_t* table = index->table;
|
||||
dict_foreign_t* foreign;
|
||||
ibool froze_data_dict = FALSE;
|
||||
ibool is_referenced = FALSE;
|
||||
|
||||
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 */
|
||||
if (!UT_LIST_GET_FIRST(table->foreign_list)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (trx->dict_operation_lock_mode == 0) {
|
||||
row_mysql_freeze_data_dictionary(trx);
|
||||
froze_data_dict = TRUE;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
/*********************************************************************//**
|
||||
|
@ -314,7 +336,123 @@ 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);
|
||||
|
||||
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 +464,7 @@ func_exit:
|
|||
|
||||
return(err);
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates an update node for a query graph.
|
||||
|
@ -1700,6 +1839,9 @@ row_upd_sec_index_entry(
|
|||
index = node->index;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -1830,6 +1972,9 @@ row_upd_sec_index_entry(
|
|||
row_ins_sec_index_entry() below */
|
||||
if (!rec_get_deleted_flag(
|
||||
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(
|
||||
0, btr_cur, TRUE, thr, &mtr);
|
||||
|
||||
|
@ -1848,29 +1993,32 @@ row_upd_sec_index_entry(
|
|||
index, offsets, thr, &mtr);
|
||||
}
|
||||
#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 =
|
||||
rec_get_offsets(
|
||||
rec, index, NULL, ULINT_UNDEFINED,
|
||||
&heap);
|
||||
err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
|
||||
rec, index, NULL, ULINT_UNDEFINED,
|
||||
&heap);
|
||||
err = wsrep_row_upd_check_foreign_constraints(
|
||||
node, &pcur, index->table,
|
||||
index, offsets, thr, &mtr);
|
||||
|
||||
switch (err) {
|
||||
case DB_SUCCESS:
|
||||
case DB_NO_REFERENCED_ROW:
|
||||
err = DB_SUCCESS;
|
||||
break;
|
||||
case DB_DEADLOCK:
|
||||
if (wsrep_debug)
|
||||
fprintf (stderr,
|
||||
"WSREP: sec index FK check fail for deadlock");
|
||||
if (wsrep_debug) fprintf (stderr,
|
||||
"WSREP: sec index FK check fail for deadlock");
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr,
|
||||
"WSREP: referenced FK check fail: %d",
|
||||
err);
|
||||
fprintf (stderr,
|
||||
"WSREP: referenced FK check fail: %d",
|
||||
(int)err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2015,123 +2163,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
|
||||
|
@ -2148,6 +2179,9 @@ row_upd_clust_rec_by_insert(
|
|||
que_thr_t* thr, /*!< in: query thread */
|
||||
ibool referenced,/*!< in: TRUE if index may be referenced in
|
||||
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 */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
|
@ -2161,6 +2195,9 @@ row_upd_clust_rec_by_insert(
|
|||
rec_t* rec;
|
||||
ulint* offsets = NULL;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
que_node_t *parent = que_node_get_parent(node);
|
||||
#endif /* WITH_WSREP */
|
||||
ut_ad(node);
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
|
||||
|
@ -2241,23 +2278,26 @@ err_exit:
|
|||
}
|
||||
}
|
||||
#ifdef WITH_WSREP
|
||||
if (!referenced) {
|
||||
err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
|
||||
if (!referenced &&
|
||||
!(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);
|
||||
|
||||
switch (err) {
|
||||
case DB_SUCCESS:
|
||||
case DB_NO_REFERENCED_ROW:
|
||||
err = DB_SUCCESS;
|
||||
break;
|
||||
case DB_DEADLOCK:
|
||||
if (wsrep_debug) fprintf (stderr,
|
||||
if (wsrep_debug) fprintf (stderr,
|
||||
"WSREP: insert FK check fail for deadlock");
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr,
|
||||
"WSREP: referenced FK check fail: %d",
|
||||
err);
|
||||
"WSREP: referenced FK check fail: %d",
|
||||
(int)err);
|
||||
break;
|
||||
}
|
||||
if (err != DB_SUCCESS) {
|
||||
|
@ -2495,6 +2535,9 @@ row_upd_del_mark_clust_rec(
|
|||
ibool referenced,
|
||||
/*!< in: TRUE if index may be referenced in
|
||||
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 */
|
||||
{
|
||||
btr_pcur_t* pcur;
|
||||
|
@ -2502,6 +2545,7 @@ row_upd_del_mark_clust_rec(
|
|||
dberr_t err;
|
||||
#ifdef WITH_WSREP
|
||||
rec_t* rec;
|
||||
que_node_t *parent = que_node_get_parent(node);
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
ut_ad(node);
|
||||
|
@ -2524,25 +2568,27 @@ row_upd_del_mark_clust_rec(
|
|||
#endif /* WITH_WSREP */
|
||||
|
||||
err = btr_cur_del_mark_set_clust_rec(
|
||||
btr_cur_get_block(btr_cur),
|
||||
#ifdef WITH_WSREP
|
||||
rec, index, offsets, thr, mtr);
|
||||
btr_cur_get_block(btr_cur), rec,
|
||||
#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 */
|
||||
|
||||
index, offsets, thr, mtr);
|
||||
if (err == DB_SUCCESS && referenced) {
|
||||
/* NOTE that the following call loses the position of pcur ! */
|
||||
|
||||
err = row_upd_check_references_constraints(
|
||||
node, pcur, index->table, index, offsets, thr, mtr);
|
||||
}
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (err == DB_SUCCESS && !referenced) {
|
||||
err = (dberr_t) wsrep_row_upd_check_foreign_constraints(
|
||||
if (err == DB_SUCCESS && !referenced &&
|
||||
!(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);
|
||||
|
||||
switch (err) {
|
||||
case DB_SUCCESS:
|
||||
case DB_NO_REFERENCED_ROW:
|
||||
|
@ -2554,8 +2600,8 @@ row_upd_del_mark_clust_rec(
|
|||
break;
|
||||
default:
|
||||
fprintf (stderr,
|
||||
"WSREP: clust rec referenced FK check fail: %u",
|
||||
err);
|
||||
"WSREP: clust rec referenced FK check fail: %d",
|
||||
(int)err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2592,6 +2638,10 @@ row_upd_clust_step(
|
|||
index = dict_table_get_first_index(node->table);
|
||||
|
||||
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;
|
||||
|
||||
|
@ -2688,7 +2738,11 @@ row_upd_clust_step(
|
|||
|
||||
if (node->is_delete) {
|
||||
err = row_upd_del_mark_clust_rec(
|
||||
#ifdef WITH_WSREP
|
||||
node, index, offsets, thr, referenced, foreign, &mtr);
|
||||
#else
|
||||
node, index, offsets, thr, referenced, &mtr);
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
node->state = UPD_NODE_UPDATE_ALL_SEC;
|
||||
|
@ -2733,7 +2787,11 @@ row_upd_clust_step(
|
|||
externally! */
|
||||
|
||||
err = row_upd_clust_rec_by_insert(
|
||||
#ifdef WITH_WSREP
|
||||
node, index, thr, referenced, foreign, &mtr);
|
||||
#else
|
||||
node, index, thr, referenced, &mtr);
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
|
|
|
@ -91,6 +91,9 @@ struct srv_conc_slot_t{
|
|||
reserved may still be TRUE at that
|
||||
point */
|
||||
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 */
|
||||
|
@ -150,6 +153,9 @@ srv_conc_init(void)
|
|||
|
||||
conc_slot->event = os_event_create();
|
||||
ut_a(conc_slot->event);
|
||||
#ifdef WITH_WSREP
|
||||
conc_slot->thd = NULL;
|
||||
#endif /* WITH_WSREP */
|
||||
}
|
||||
#endif /* !HAVE_ATOMIC_BUILTINS */
|
||||
}
|
||||
|
@ -207,6 +213,16 @@ srv_conc_enter_innodb_with_atomics(
|
|||
|
||||
for (;;) {
|
||||
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) {
|
||||
ulint n_active;
|
||||
|
@ -325,6 +341,9 @@ srv_conc_exit_innodb_without_atomics(
|
|||
slot = NULL;
|
||||
|
||||
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
|
||||
thread has yet released the thread */
|
||||
|
||||
|
@ -335,6 +354,19 @@ srv_conc_exit_innodb_without_atomics(
|
|||
/* 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) {
|
||||
slot->wait_ended = TRUE;
|
||||
|
||||
|
@ -394,6 +426,13 @@ retry:
|
|||
|
||||
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
|
||||
for srv_thread_sleep_delay microseconds, and try again then */
|
||||
|
@ -461,6 +500,9 @@ retry:
|
|||
/* Add to the queue */
|
||||
slot->reserved = TRUE;
|
||||
slot->wait_ended = FALSE;
|
||||
#ifdef WITH_WSREP
|
||||
slot->thd = trx->mysql_thd;
|
||||
#endif
|
||||
|
||||
UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
|
||||
|
||||
|
@ -468,6 +510,18 @@ retry:
|
|||
|
||||
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);
|
||||
|
||||
/* Go to wait for the event; when a thread leaves InnoDB it will
|
||||
|
@ -491,6 +545,9 @@ retry:
|
|||
|
||||
os_event_wait(slot->event);
|
||||
thd_wait_end(trx->mysql_thd);
|
||||
#ifdef WITH_WSREP
|
||||
trx->wsrep_event = NULL;
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
|
@ -508,6 +565,9 @@ retry:
|
|||
incremented the thread counter on behalf of this thread */
|
||||
|
||||
slot->reserved = FALSE;
|
||||
#ifdef WITH_WSREP
|
||||
slot->thd = NULL;
|
||||
#endif
|
||||
|
||||
UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
|
||||
|
||||
|
@ -629,7 +689,7 @@ wsrep_srv_conc_cancel_wait(
|
|||
thread */
|
||||
{
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
/* aborting transactions will enter innodb by force in
|
||||
/* aborting transactions will enter innodb by force in
|
||||
srv_conc_enter_innodb_with_atomics(). No need to cancel here,
|
||||
thr will wake up after os_sleep and let to enter innodb
|
||||
*/
|
||||
|
|
|
@ -213,7 +213,8 @@ trx_sys_update_mysql_binlog_offset(
|
|||
{
|
||||
#ifndef WITH_WSREP
|
||||
trx_sysf_t* sys_header;
|
||||
#endif
|
||||
#endif /* !WITH_WSREP */
|
||||
|
||||
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
|
||||
|
||||
/* 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
|
||||
sys_header = trx_sysf_get(mtr);
|
||||
#endif
|
||||
#endif /* !WITH_WSREP */
|
||||
|
||||
if (mach_read_from_4(sys_header + field
|
||||
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
|
||||
|
@ -312,12 +313,49 @@ trx_sys_print_mysql_binlog_offset(void)
|
|||
|
||||
#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
|
||||
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 */
|
||||
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_a(xid->formatID == -1 || wsrep_is_wsrep_xid((const void *)xid));
|
||||
|
||||
|
|
|
@ -1190,12 +1190,12 @@ trx_write_serialisation_history(
|
|||
MONITOR_INC(MONITOR_TRX_COMMIT_UNDO);
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
sys_header = trx_sysf_get(mtr);
|
||||
/* Update latest MySQL wsrep XID in trx sys header. */
|
||||
if (wsrep_is_wsrep_xid((const void *)&trx->xid))
|
||||
{
|
||||
trx_sys_update_wsrep_checkpoint(&trx->xid, sys_header, mtr);
|
||||
}
|
||||
sys_header = trx_sysf_get(&mtr);
|
||||
/* Update latest MySQL wsrep XID in trx sys header. */
|
||||
if (wsrep_is_wsrep_xid(&trx->xid))
|
||||
{
|
||||
trx_sys_update_wsrep_checkpoint(&trx->xid, sys_header, &mtr);
|
||||
}
|
||||
#endif /* WITH_WSREP */
|
||||
|
||||
/* Update the latest MySQL binlog name and offset info
|
||||
|
@ -1517,8 +1517,6 @@ trx_commit_in_memory(
|
|||
ut_ad(!trx->in_ro_trx_list);
|
||||
ut_ad(!trx->in_rw_trx_list);
|
||||
|
||||
trx->dict_operation = TRX_DICT_OP_NONE;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (wsrep_on(trx->mysql_thd)) {
|
||||
trx->lock.was_chosen_as_deadlock_victim = FALSE;
|
||||
|
|
Loading…
Reference in a new issue