* Merged the missing revision 3934 from

codership-mysql/5.5 (missed in the last merge).
* Merged changes from Innodb to xtradb.
* Updated WSREP_PATCH_REVNO
This commit is contained in:
Nirbhay Choubey 2014-02-05 00:28:11 -05:00
parent 7ca53d9479
commit 4cb029b38b
23 changed files with 294 additions and 290 deletions

View file

@ -23,7 +23,7 @@ SET(WSREP_PATCH_VERSION "9")
# MariaDB addition: Revision number of the last revision merged from
# codership branch visible in @@visible_comment.
# Branch : codership-mysql/5.5
SET(WSREP_PATCH_REVNO "3932") # Should be updated on every merge.
SET(WSREP_PATCH_REVNO "3944") # Should be updated on every merge.
# MariaDB: Obtain patch revision number:
# Update WSREP_PATCH_REVNO if WSREP_REV environment variable is set.

View file

@ -22,7 +22,7 @@ extern "C" {
#endif
#ifdef WITH_WSREP
#include <my_sys.h>
typedef int (* wsrep_thd_is_brute_force_fun)(void *);
typedef my_bool (* wsrep_thd_is_brute_force_fun)(void *, my_bool);
typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool);
typedef int (* wsrep_on_fun)(void *);
void wsrep_thr_lock_init(

View file

@ -662,8 +662,111 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
DBUG_RETURN(result);
}
#ifdef WITH_WSREP
/*
* If brute force applier would need to wait for a thr lock,
* it needs to make sure that it will get the lock without (too much)
* delay.
* We identify here the owners of blocking locks and ask them to
* abort. We then put our lock request in the first place in the
* wait queue. When lock holders abort (one by one) the lock release
* algorithm should grant the lock to us. We rely on this and proceed
* to wait_for_locks().
* wsrep_break_locks() should be called in all the cases, where lock
* wait would happen.
*
* TODO: current implementation might not cover all possible lock wait
* situations. This needs an review still.
* TODO: lock release, might favor some other lock (instead our bf).
* This needs an condition to check for bf locks first.
* TODO: we still have a debug fprintf, this should be removed
*/
static inline my_bool
wsrep_break_lock(
THR_LOCK_DATA *data, struct st_lock_list *lock_queue1,
struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue)
{
if (wsrep_on(data->owner->mysql_thd) &&
wsrep_thd_is_brute_force &&
wsrep_thd_is_brute_force(data->owner->mysql_thd, TRUE))
{
THR_LOCK_DATA *holder;
static enum enum_thr_lock_result
/* if locking session conversion to transaction has been enabled,
we know that this conflicting lock must be read lock and furthermore,
lock holder is read-only. It is safe to wait for him.
*/
#ifdef TODO
if (wsrep_convert_LOCK_to_trx &&
(THD*)(data->owner->mysql_thd)->in_lock_tables)
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n");
return FALSE;
}
#endif
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n");
/* aborting lock holder(s) here */
for (holder=(lock_queue1) ? lock_queue1->data : NULL;
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
}
else
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
return FALSE;
}
}
for (holder=(lock_queue2) ? lock_queue2->data : NULL;
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd, TRUE))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
}
else
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
return FALSE;
}
}
/* Add our lock to the head of the wait queue */
if (*(wait_queue->last)==wait_queue->data)
{
wait_queue->last=&data->next;
assert(wait_queue->data==0);
}
else
{
assert(wait_queue->data!=0);
wait_queue->data->prev=&data->next;
}
data->next=wait_queue->data;
data->prev=&wait_queue->data;
wait_queue->data=data;
data->cond=get_cond();
statistic_increment(locks_immediate,&THR_LOCK_lock);
return TRUE;
}
return FALSE;
}
#endif
static
enum enum_thr_lock_result
thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout)
{
THR_LOCK *lock=data->lock;
@ -1164,108 +1267,7 @@ static void sort_locks(THR_LOCK_DATA **data,uint count)
}
}
#ifdef WITH_WSREP
/*
* If brute force applier would need to wait for a thr lock,
* it needs to make sure that it will get the lock without (too much)
* delay.
* We identify here the owners of blocking locks and ask them to
* abort. We then put our lock request in the first place in the
* wait queue. When lock holders abort (one by one) the lock release
* algorithm should grant the lock to us. We rely on this and proceed
* to wait_for_locks().
* wsrep_break_locks() should be called in all the cases, where lock
* wait would happen.
*
* TODO: current implementation might not cover all possible lock wait
* situations. This needs an review still.
* TODO: lock release, might favor some other lock (instead our bf).
* This needs an condition to check for bf locks first.
* TODO: we still have a debug fprintf, this should be removed
*/
static inline my_bool
wsrep_break_lock(
THR_LOCK_DATA *data, struct st_lock_list *lock_queue1,
struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue)
{
if (wsrep_on(data->owner->mysql_thd) &&
wsrep_thd_is_brute_force &&
wsrep_thd_is_brute_force(data->owner->mysql_thd))
{
THR_LOCK_DATA *holder;
/* if locking session conversion to transaction has been enabled,
we know that this conflicting lock must be read lock and furthermore,
lock holder is read-only. It is safe to wait for him.
*/
#ifdef TODO
if (wsrep_convert_LOCK_to_trx &&
(THD*)(data->owner->mysql_thd)->in_lock_tables)
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n");
return FALSE;
}
#endif
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n");
/* aborting lock holder(s) here */
for (holder=(lock_queue1) ? lock_queue1->data : NULL;
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
}
else
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
return FALSE;
}
}
for (holder=(lock_queue2) ? lock_queue2->data : NULL;
holder;
holder=holder->next)
{
if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd))
{
wsrep_abort_thd(data->owner->mysql_thd,
holder->owner->mysql_thd, FALSE);
}
else
{
if (wsrep_debug)
fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n");
return FALSE;
}
}
/* Add our lock to the head of the wait queue */
if (*(wait_queue->last)==wait_queue->data)
{
wait_queue->last=&data->next;
assert(wait_queue->data==0);
}
else
{
assert(wait_queue->data!=0);
wait_queue->data->prev=&data->next;
}
data->next=wait_queue->data;
data->prev=&wait_queue->data;
wait_queue->data=data;
data->cond=get_cond();
statistic_increment(locks_immediate,&THR_LOCK_lock);
return TRUE;
}
return FALSE;
}
#endif
enum enum_thr_lock_result
thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner,

View file

@ -1267,7 +1267,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
DBUG_ASSERT(ticket->get_lock());
#ifdef WITH_WSREP
if ((this == &(ticket->get_lock()->m_waiting)) &&
wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->get_thd())))
wsrep_thd_is_BF((void *)(ticket->get_ctx()->get_thd()), false))
{
Ticket_iterator itw(ticket->get_lock()->m_waiting);
Ticket_iterator itg(ticket->get_lock()->m_granted);
@ -1278,7 +1278,7 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket)
while ((waiting= itw++) && !added)
{
if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->get_thd())))
if (!wsrep_thd_is_BF((void *)(waiting->get_ctx()->get_thd()), true))
{
WSREP_DEBUG("MDL add_ticket inserted before: %lu %s",
wsrep_thd_thread_id(waiting->get_ctx()->get_thd()),
@ -1669,7 +1669,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
ticket->is_incompatible_when_granted(type_arg))
#ifdef WITH_WSREP
{
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) &&
if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF: %lu %s",
@ -1710,7 +1710,7 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg,
#ifdef WITH_WSREP
else
{
if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) &&
if (wsrep_thd_is_BF((void *)(requestor_ctx->get_thd()), false) &&
key.mdl_namespace() == MDL_key::GLOBAL)
{
WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s",

View file

@ -9386,7 +9386,7 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use,
#ifdef WITH_WSREP
{
signalled|= mysql_lock_abort_for_thread(thd, thd_table);
if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd))
if (thd && WSREP(thd) && wsrep_thd_is_BF((void *)thd, true))
{
WSREP_DEBUG("remove_table_from_cache: %llu",
(unsigned long long) thd->real_id);

View file

@ -7254,7 +7254,7 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal)
#ifdef WITH_WSREP
if (((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx)) &&
!wsrep_thd_is_brute_force((void *)tmp))
!wsrep_thd_is_BF((void *)tmp, true))
#else
if ((thd->security_ctx->master_access & SUPER_ACL) ||
thd->security_ctx->user_matches(tmp->security_ctx))

View file

@ -642,7 +642,7 @@ void wsrep_init_startup (bool first)
{
if (wsrep_init()) unireg_abort(1);
wsrep_thr_lock_init(wsrep_thd_is_brute_force, wsrep_abort_thd,
wsrep_thr_lock_init(wsrep_thd_is_BF, wsrep_abort_thd,
wsrep_debug, wsrep_convert_LOCK_to_trx, wsrep_on);
/* Skip replication start if no cluster address */

View file

@ -406,27 +406,51 @@ void wsrep_create_rollbacker()
}
extern "C"
int wsrep_thd_is_brute_force(void *thd_ptr)
{
/*
Brute force:
Appliers and replaying are running in REPL_RECV mode. TOI statements
in TOTAL_ORDER mode. Locally committing transaction that has got
past wsrep->pre_commit() without error is running in LOCAL_COMMIT mode.
Everything else is running in LOCAL_STATE and should not be considered
brute force.
*/
if (thd_ptr) {
switch (((THD *)thd_ptr)->wsrep_exec_mode) {
case LOCAL_STATE: return 0;
case REPL_RECV: return 1;
case TOTAL_ORDER: return 2;
case LOCAL_COMMIT: return 3;
}
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{
my_bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
DBUG_ASSERT(0);
return 0;
return status;
}
extern "C"
my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER) ||
(thd->wsrep_exec_mode == LOCAL_COMMIT));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
extern "C"
my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync)
{
bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = (thd->wsrep_exec_mode == LOCAL_STATE);
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
return status;
}
extern "C"

View file

@ -24,7 +24,9 @@ void wsrep_replay_transaction(THD *thd);
void wsrep_create_appliers(long threads);
void wsrep_create_rollbacker();
extern "C" int wsrep_thd_is_brute_force(void *thd_ptr);
extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync);
extern "C" my_bool wsrep_thd_is_local(void *thd_ptr, my_bool sync);
extern "C" int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
my_bool signal);
extern "C" int wsrep_thd_in_locking_session(void *thd_ptr);

View file

@ -12566,8 +12566,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
(long long)bf_seqno, (long long)victim_seqno);
abort();
}
/*******************************************************************//**
This function is used to kill one transaction in BF. */
int
wsrep_innobase_kill_one_trx(
void *bf_thd_ptr, /*!< in: BF thd */

View file

@ -288,7 +288,8 @@ thd_set_lock_wait_time(
#ifdef WITH_WSREP
UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx,
ibool signal, ibool have_kernel_mutex);
int wsrep_thd_is_brute_force(void *thd_ptr);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
//int64_t wsrep_thd_trx_seqno(THD *thd);
int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length);

View file

@ -799,7 +799,6 @@ lock_rec_get_page_no(
record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error
#endif

View file

@ -932,11 +932,6 @@ lock_rec_has_to_wait(
if (trx != lock2->trx
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
lock_get_mode(lock2))) {
#ifdef WITH_WSREP
if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) {
return FALSE;
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks
cause waits */
@ -1565,9 +1560,8 @@ lock_rec_other_has_expl_req(
#ifdef WITH_WSREP
static void
wsrep_kill_victim(trx_t *trx, lock_t *lock) {
int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
int bf_other =
wsrep_thd_is_brute_force(lock->trx->mysql_thd);
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
@ -1842,11 +1836,6 @@ lock_rec_create(
lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index;
lock->un_member.rec_lock.space = space;
@ -1862,13 +1851,15 @@ lock_rec_create(
lock_rec_set_nth_bit(lock, heap_no);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = c_lock->hash;
lock_t *prev = NULL;
while (hash &&
wsrep_thd_is_brute_force(hash->trx->mysql_thd) &&
wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){
wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before(
hash->trx->mysql_thd, trx->mysql_thd))
{
prev = hash;
hash = hash->hash;
}
@ -2208,11 +2199,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL););
@ -2297,11 +2283,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
trx = thr_get_trx(thr);
@ -2400,17 +2381,7 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
/* We try a simplified and faster subroutine for the most
common cases */
switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
@ -3845,11 +3816,11 @@ lock_deadlock_recursive(
#ifdef WITH_WSREP
if (wsrep_debug)
fputs("WSREP: Deadlock detected\n", stderr);
if (wsrep_thd_is_brute_force(start->mysql_thd) &&
wsrep_thd_is_brute_force(
wait_lock->trx->mysql_thd) &&
(start != wait_lock->trx)) {
if ((start != wait_lock->trx) &&
wsrep_thd_is_BF(start->mysql_thd, TRUE) &&
wsrep_thd_is_BF(
wait_lock->trx->mysql_thd, TRUE))
{
if (wsrep_trx_order_before(
start->mysql_thd,
wait_lock->trx->mysql_thd)) {
@ -3870,8 +3841,9 @@ lock_deadlock_recursive(
back it */
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(
start->mysql_thd)) {
if (!wsrep_thd_is_BF(
start->mysql_thd, FALSE))
{
return(LOCK_VICTIM_IS_START);
}
#else
@ -3879,8 +3851,9 @@ lock_deadlock_recursive(
#endif
}
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(
wait_lock->trx->mysql_thd)) {
if (wsrep_thd_is_BF(
wait_lock->trx->mysql_thd, TRUE))
{
return(LOCK_VICTIM_IS_START);
}
#endif
@ -4008,7 +3981,7 @@ lock_table_create(
lock->un_member.tab_lock.table = table;
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
@ -5641,7 +5614,7 @@ lock_rec_insert_check_and_lock(
#ifdef WITH_WSREP
if ((c_lock = lock_rec_other_has_conflicting(
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF,
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
block, next_rec_heap_no, trx))) {
#else
if (lock_rec_other_has_conflicting(
@ -5745,7 +5718,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd)
&& !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */

View file

@ -1682,9 +1682,6 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_t* entry, /*!< in: index entry */
que_thr_t* thr) /*!< in: query thread */
{
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique;
ulint i;
int cmp;
@ -1748,15 +1745,8 @@ row_ins_scan_sec_index_for_duplicate(
} else {
lock_type = LOCK_ORDINARY;
}
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -1872,13 +1862,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -1922,13 +1906,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for

View file

@ -370,6 +370,12 @@ wsrep_row_upd_check_foreign_constraints(
}
trx = thr_get_trx(thr);
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
return(DB_SUCCESS);
}
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets));

View file

@ -1214,7 +1214,7 @@ srv_conc_enter_innodb(
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) {
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
srv_conc_force_enter_innodb(trx);
return;
}
@ -1844,7 +1844,7 @@ srv_suspend_mysql_thread(
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) {
wsrep_thd_is_BF(trx->mysql_thd, TRUE)) {
fprintf(stderr,
"WSREP: BF long lock wait ended after %.f sec\n",
wait_time);
@ -2421,7 +2421,7 @@ wsrep_is_BF_lock_timeout(
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
wsrep_thd_is_BF((thr_get_trx(slot->thr))->mysql_thd, TRUE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;

View file

@ -4172,6 +4172,9 @@ ha_innobase::max_supported_key_length() const
is 16 kB; but currently MySQL does not work with keys whose
size is > MAX_KEY_LENGTH */
#ifdef WITH_WSREP
/* this may look like obsolete code, but this ifdef is here
just to make sure we will see bzr merge conflict, if Oracle
changes max key length */
return(3500);
#else
return(3500);
@ -5335,7 +5338,7 @@ wsrep_innobase_mysql_sort(
tmp_length = charset->coll->strnxfrm(charset, str, str_length,
tmp_str, str_length);
DBUG_ASSERT(tmp_length == str_length);
DBUG_ASSERT(tmp_length <= str_length);
break;
}
@ -8486,6 +8489,13 @@ ha_innobase::wsrep_append_keys(
} else {
ut_a(table->s->keys <= 256);
uint i;
bool hasPK= false;
for (i=0; i<table->s->keys && !hasPK; ++i) {
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) hasPK = true;
}
for (i=0; i<table->s->keys; ++i) {
uint len;
char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
@ -8506,7 +8516,7 @@ ha_innobase::wsrep_append_keys(
table->s->table_name.str,
key_info->name);
}
if (key_info->flags & HA_NOSAME ||
if (!hasPK || key_info->flags & HA_NOSAME ||
((tab &&
dict_table_get_referenced_constraint(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) {
@ -13891,8 +13901,7 @@ wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno)
(long long)bf_seqno, (long long)victim_seqno);
abort();
}
/*******************************************************************//**
This function is used to kill one transaction in BF. */
int
wsrep_innobase_kill_one_trx(
void *bf_thd_ptr, /*!< in: BF thd */

View file

@ -303,7 +303,8 @@ thd_flush_log_at_trx_commit(
#ifdef WITH_WSREP
UNIV_INTERN int wsrep_innobase_kill_one_trx(void *thd, trx_t *bf_trx, trx_t *victim_trx,
ibool signal, ibool have_kernel_mutex);
int wsrep_thd_is_brute_force(void *thd_ptr);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
//int64_t wsrep_thd_trx_seqno(THD *thd);
int wsrep_trx_order_before(void *thd1, void *thd2);
void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length);

View file

@ -800,7 +800,6 @@ lock_rec_get_page_no(
record */
#define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created
by other transaction */
#define WSREP_BF 8192
#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK
# error
#endif

View file

@ -910,6 +910,9 @@ UNIV_INLINE
ibool
lock_rec_has_to_wait(
/*=================*/
#ifdef WITH_WSREP
ibool for_locking, /*!< is caller locking or releasing */
#endif /* WITH_WSREP */
const trx_t* trx, /*!< in: trx of new lock */
ulint type_mode,/*!< in: precise mode of the new lock
to set: LOCK_S or LOCK_X, possibly
@ -930,11 +933,6 @@ lock_rec_has_to_wait(
if (trx != lock2->trx
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
lock_get_mode(lock2))) {
#ifdef WITH_WSREP
if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) {
return FALSE;
}
#endif /* WITH_WSREP */
/* We have somewhat complex rules when gap type record locks
cause waits */
@ -984,6 +982,44 @@ lock_rec_has_to_wait(
return(FALSE);
}
#ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */
if (for_locking &&
wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) {
fprintf(stderr, "\n BF-BF lock conflict \n");
lock_rec_print(stderr, lock2);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd) &&
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X)
{
/* exclusive lock conflicts are not accepted */
fprintf(stderr, "BF-BF X lock conflict\n");
lock_rec_print(stderr, lock2);
abort();
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) fprintf(stderr,
"BF conflict, modes: %lu %lu, "
"idx: %s-%s n_uniq %u n_user %u\n",
type_mode, lock2->type_mode,
lock2->index->name,
lock2->index->table_name,
lock2->index->n_uniq,
lock2->index->n_user_defined_cols);
return FALSE;
}
}
#endif /* WITH_WSREP */
return(TRUE);
}
@ -1014,7 +1050,11 @@ lock_has_to_wait(
/* If this lock request is for a supremum record
then the second bit on the lock bitmap is set */
#ifdef WITH_WSREP
return(lock_rec_has_to_wait(FALSE, lock1->trx,
#else
return(lock_rec_has_to_wait(lock1->trx,
#endif /* WITH_WSREP */
lock1->type_mode, lock2,
lock_rec_get_nth_bit(
lock1, 1)));
@ -1521,9 +1561,8 @@ lock_rec_other_has_expl_req(
#ifdef WITH_WSREP
static void
wsrep_kill_victim(trx_t *trx, lock_t *lock) {
int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd);
int bf_other =
wsrep_thd_is_brute_force(lock->trx->mysql_thd);
my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((bf_this && !bf_other) ||
(bf_this && bf_other && wsrep_trx_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
@ -1593,7 +1632,11 @@ lock_rec_other_has_conflicting(
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
do {
if (lock_rec_has_to_wait(trx, mode, lock,
#ifdef WITH_WSREP
if (lock_rec_has_to_wait(TRUE, trx, mode, lock,
#else
if (lock_rec_has_to_wait(trx, mode, lock,
#endif /* WITH_WSREP */
TRUE)) {
#ifdef WITH_WSREP
wsrep_kill_victim(trx, lock);
@ -1606,7 +1649,11 @@ lock_rec_other_has_conflicting(
} else {
do {
if (lock_rec_has_to_wait(trx, mode, lock,
#ifdef WITH_WSREP
if (lock_rec_has_to_wait(TRUE, trx, mode, lock,
#else
if (lock_rec_has_to_wait(trx, mode, lock,
#endif /* WITH_WSREP */
FALSE)) {
#ifdef WITH_WSREP
wsrep_kill_victim(trx, lock);
@ -1790,11 +1837,6 @@ lock_rec_create(
lock->trx = trx;
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(trx->mysql_thd)) {
lock->type_mode |= WSREP_BF;
}
#endif /* WITH_WSREP */
lock->index = index;
lock->un_member.rec_lock.space = space;
@ -1810,13 +1852,15 @@ lock_rec_create(
lock_rec_set_nth_bit(lock, heap_no);
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = c_lock->hash;
lock_t *prev = NULL;
while (hash &&
wsrep_thd_is_brute_force(hash->trx->mysql_thd) &&
wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){
wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) &&
wsrep_trx_order_before(
hash->trx->mysql_thd, trx->mysql_thd))
{
prev = hash;
hash = hash->hash;
}
@ -2162,11 +2206,6 @@ lock_rec_lock_fast(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
DBUG_EXECUTE_IF("innodb_report_deadlock", return(LOCK_REC_FAIL););
@ -2251,11 +2290,6 @@ lock_rec_lock_slow(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == 0
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
trx = thr_get_trx(thr);
@ -2354,17 +2388,7 @@ lock_rec_lock(
|| (LOCK_MODE_MASK & mode) == LOCK_X);
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
#ifdef WITH_WSREP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP
|| mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP
#endif /* WITH_WSREP */
|| mode - (LOCK_MODE_MASK & mode) == 0);
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) {
mode |= WSREP_BF;
}
#endif
/* We try a simplified and faster subroutine for the most
common cases */
switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
@ -3802,11 +3826,11 @@ lock_deadlock_recursive(
#ifdef WITH_WSREP
if (wsrep_debug)
fputs("WSREP: Deadlock detected\n", stderr);
if (wsrep_thd_is_brute_force(start->mysql_thd) &&
wsrep_thd_is_brute_force(
wait_lock->trx->mysql_thd) &&
(start != wait_lock->trx)) {
if ((start != wait_lock->trx) &&
wsrep_thd_is_BF(start->mysql_thd, TRUE) &&
wsrep_thd_is_BF(
wait_lock->trx->mysql_thd, TRUE))
{
if (wsrep_trx_order_before(
start->mysql_thd,
wait_lock->trx->mysql_thd)) {
@ -3827,8 +3851,9 @@ lock_deadlock_recursive(
back it */
#ifdef WITH_WSREP
if (!wsrep_thd_is_brute_force(
start->mysql_thd)) {
if (!wsrep_thd_is_BF(
start->mysql_thd, FALSE))
{
return(LOCK_VICTIM_IS_START);
}
#else
@ -3836,8 +3861,9 @@ lock_deadlock_recursive(
#endif
}
#ifdef WITH_WSREP
if (wsrep_thd_is_brute_force(
wait_lock->trx->mysql_thd)) {
if (wsrep_thd_is_BF(
wait_lock->trx->mysql_thd, TRUE))
{
return(LOCK_VICTIM_IS_START);
}
#endif
@ -3965,7 +3991,7 @@ lock_table_create(
lock->un_member.tab_lock.table = table;
#ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock);
} else {
@ -5619,7 +5645,7 @@ lock_rec_insert_check_and_lock(
#ifdef WITH_WSREP
if ((c_lock = lock_rec_other_has_conflicting(
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF,
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
block, next_rec_heap_no, trx))) {
#else
if (lock_rec_other_has_conflicting(
@ -5723,7 +5749,7 @@ lock_rec_convert_impl_to_expl(
if (rec_get_deleted_flag(rec, rec_offs_comp(offsets))
#ifdef WITH_WSREP
&& !wsrep_thd_is_brute_force(impl_trx->mysql_thd)
&& !wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)
/* BF-BF conflict is possible if advancing into
lock_rec_other_has_conflicting*/
#endif /* WITH_WSREP */

View file

@ -1694,9 +1694,6 @@ row_ins_scan_sec_index_for_duplicate(
dtuple_t* entry, /*!< in: index entry */
que_thr_t* thr) /*!< in: query thread */
{
#ifdef WITH_WSREP
trx_t* trx = thr_get_trx(thr);
#endif
ulint n_unique;
ulint i;
int cmp;
@ -1760,14 +1757,8 @@ row_ins_scan_sec_index_for_duplicate(
} else {
lock_type = LOCK_ORDINARY;
}
#ifdef WITH_WSREP
/* slave applier must not get duplicate error */
if (allow_duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (allow_duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -1883,13 +1874,7 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate
errors as in original execution */
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for
@ -1933,13 +1918,7 @@ row_ins_duplicate_error_in_clust(
offsets = rec_get_offsets(rec, cursor->index, offsets,
ULINT_UNDEFINED, &heap);
#ifdef WITH_WSREP
if (trx->duplicates ||
(wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd))) {
#else
if (trx->duplicates) {
#endif
/* If the SQL-query will update or replace
duplicate key we will take X-lock for

View file

@ -370,6 +370,12 @@ wsrep_row_upd_check_foreign_constraints(
}
trx = thr_get_trx(thr);
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
return(DB_SUCCESS);
}
/* TODO: make native slave thread bail out here */
rec = btr_pcur_get_rec(pcur);
ut_ad(rec_offs_validate(rec, index, offsets));

View file

@ -1401,7 +1401,7 @@ srv_conc_enter_innodb(
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) {
wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
srv_conc_force_enter_innodb(trx);
return;
}
@ -2070,7 +2070,7 @@ srv_suspend_mysql_thread(
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_brute_force(trx->mysql_thd)) {
wsrep_thd_is_BF(trx->mysql_thd, TRUE)) {
fprintf(stderr,
"WSREP: BF long lock wait ended after %.f sec\n",
wait_time);
@ -2891,7 +2891,7 @@ wsrep_is_BF_lock_timeout(
srv_slot_t* slot) /* in: lock slot to check for lock priority */
{
if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) &&
wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) {
wsrep_thd_is_BF((thr_get_trx(slot->thr))->mysql_thd, TRUE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;