Commit 9b506d4b authored by Jan Lindström's avatar Jan Lindström

MDEV-6602: rpl.rpl_mdev6020 fails sporadically with SIGABRT

Analysis: Problem is that we execute galera code when we are actually
executing asyncronoush replication.

Fix: Do not execute galera code if wsrep provider is not set.
parent de38fcfb
...@@ -503,17 +503,35 @@ int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync) ...@@ -503,17 +503,35 @@ int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync)
return state; return state;
} }
my_bool wsrep_thd_is_wsrep(void *thd_ptr)
{
my_bool status = FALSE;
if (thd_ptr)
{
THD* thd = (THD*)thd_ptr;
status = (WSREP(thd) && WSREP_PROVIDER_EXISTS);
}
return status;
}
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync) my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync)
{ {
my_bool status = FALSE; my_bool status = FALSE;
if (thd_ptr) if (thd_ptr)
{ {
THD* thd = (THD*)thd_ptr; THD* thd = (THD*)thd_ptr;
if (sync) mysql_mutex_lock(&thd->LOCK_wsrep_thd); // THD can be BF only if provider exists
if (wsrep_thd_is_wsrep(thd_ptr))
{
if (sync)
mysql_mutex_lock(&thd->LOCK_wsrep_thd);
status = ((thd->wsrep_exec_mode == REPL_RECV) || status = ((thd->wsrep_exec_mode == REPL_RECV) ||
(thd->wsrep_exec_mode == TOTAL_ORDER)); (thd->wsrep_exec_mode == TOTAL_ORDER));
if (sync) mysql_mutex_unlock(&thd->LOCK_wsrep_thd); if (sync)
mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
}
} }
return status; return status;
} }
......
...@@ -29,6 +29,8 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, ...@@ -29,6 +29,8 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr,
extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); extern my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
extern my_bool wsrep_thd_is_wsrep(void *thd_ptr);
extern int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); extern int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
//extern "C" my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); //extern "C" my_bool wsrep_thd_is_BF(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_BF_or_commit(void *thd_ptr, my_bool sync);
......
...@@ -294,6 +294,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr, ...@@ -294,6 +294,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr,
my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_wsrep(void *thd_ptr);
int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_trx_order_before(void *thd1, void *thd2);
int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length, unsigned char* str, unsigned int str_length,
......
...@@ -1664,8 +1664,12 @@ lock_rec_other_has_expl_req( ...@@ -1664,8 +1664,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
static void static
wsrep_kill_victim(const trx_t * const trx, const 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_BF(trx->mysql_thd, FALSE); my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
...@@ -1676,30 +1680,36 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { ...@@ -1676,30 +1680,36 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
trx->mysql_thd, lock->trx->mysql_thd))) { trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) if (wsrep_debug) {
fprintf(stderr, "WSREP: BF victim waiting\n"); fprintf(stderr, "WSREP: BF victim waiting\n");
}
/* cannot release lock, until our lock /* cannot release lock, until our lock
is in the queue*/ is in the queue*/
} else if (lock->trx != trx) { } else if (lock->trx != trx) {
if (wsrep_log_conflicts) { if (wsrep_log_conflicts) {
mutex_enter(&trx_sys->mutex); mutex_enter(&trx_sys->mutex);
if (bf_this) if (bf_this) {
fputs("\n*** Priority TRANSACTION:\n", fputs("\n*** Priority TRANSACTION:\n",
stderr); stderr);
else } else {
fputs("\n*** Victim TRANSACTION:\n", fputs("\n*** Victim TRANSACTION:\n",
stderr); stderr);
}
trx_print_latched(stderr, trx, 3000); trx_print_latched(stderr, trx, 3000);
if (bf_other) if (bf_other) {
fputs("\n*** Priority TRANSACTION:\n", fputs("\n*** Priority TRANSACTION:\n",
stderr); stderr);
else } else {
fputs("\n*** Victim TRANSACTION:\n", fputs("\n*** Victim TRANSACTION:\n",
stderr); stderr);
}
trx_print_latched(stderr, lock->trx, 3000); trx_print_latched(stderr, lock->trx, 3000);
mutex_exit(&trx_sys->mutex); mutex_exit(&trx_sys->mutex);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
stderr); stderr);
...@@ -1709,6 +1719,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { ...@@ -1709,6 +1719,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
lock_table_print(stderr, lock); lock_table_print(stderr, 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);
} }
...@@ -2038,7 +2049,6 @@ lock_rec_create( ...@@ -2038,7 +2049,6 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash; lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL; lock_t *prev = NULL;
...@@ -2066,7 +2076,9 @@ lock_rec_create( ...@@ -2066,7 +2076,9 @@ lock_rec_create(
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock); if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
}
trx->lock.que_state = TRX_QUE_LOCK_WAIT; trx->lock.que_state = TRX_QUE_LOCK_WAIT;
lock_set_lock_and_trx_wait(lock, trx); lock_set_lock_and_trx_wait(lock, trx);
...@@ -2080,10 +2092,15 @@ lock_rec_create( ...@@ -2080,10 +2092,15 @@ lock_rec_create(
victim lock release. This will eventually call victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again lock_grant, which wants to grant trx mutex again
*/ */
if (caller_owns_trx_mutex) trx_mutex_exit(trx); if (caller_owns_trx_mutex) {
trx_mutex_exit(trx);
}
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
c_lock->trx->lock.wait_lock); c_lock->trx->lock.wait_lock);
if (caller_owns_trx_mutex) trx_mutex_enter(trx);
if (caller_owns_trx_mutex) {
trx_mutex_enter(trx);
}
/* trx might not wait for c_lock, but some other lock /* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above does not matter if wait_lock was released above
...@@ -2091,12 +2108,15 @@ lock_rec_create( ...@@ -2091,12 +2108,15 @@ lock_rec_create(
if (c_lock->trx->lock.wait_lock == c_lock) { if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock); lock_reset_lock_and_trx_wait(lock);
} }
trx_mutex_exit(c_lock->trx); trx_mutex_exit(c_lock->trx);
if (wsrep_debug) fprintf( if (wsrep_debug) {
fprintf(
stderr, stderr,
"WSREP: c_lock canceled %llu\n", "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id); (ulonglong) c_lock->trx->id);
}
/* have to bail out here to avoid lock_set_lock... */ /* have to bail out here to avoid lock_set_lock... */
return(lock); return(lock);
...@@ -2310,7 +2330,7 @@ lock_rec_add_to_queue( ...@@ -2310,7 +2330,7 @@ lock_rec_add_to_queue(
block, heap_no, trx); block, heap_no, trx);
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* this can potentionally assert with wsrep */ /* this can potentionally assert with wsrep */
if (wsrep_on(trx->mysql_thd)) { if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug && other_lock) { if (wsrep_debug && other_lock) {
fprintf(stderr, fprintf(stderr,
"WSREP: InnoDB assert ignored\n"); "WSREP: InnoDB assert ignored\n");
...@@ -2555,8 +2575,8 @@ lock_rec_lock_slow( ...@@ -2555,8 +2575,8 @@ lock_rec_lock_slow(
/* c_lock is NULL here if jump to enqueue_waiting happened /* c_lock is NULL here if jump to enqueue_waiting happened
but it's ok because lock is not NULL in that case and c_lock but it's ok because lock is not NULL in that case and c_lock
is not used. */ is not used. */
err= err = lock_rec_enqueue_waiting(c_lock,
lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, index, thr); mode, block, heap_no, index, thr);
#else #else
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
mode, block, heap_no, index, thr); mode, block, heap_no, index, thr);
...@@ -4058,16 +4078,18 @@ lock_deadlock_select_victim( ...@@ -4058,16 +4078,18 @@ lock_deadlock_select_victim(
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_BF(ctx->start->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) {
return(ctx->start); return(ctx->start);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
...@@ -4201,8 +4223,9 @@ lock_deadlock_search( ...@@ -4201,8 +4223,9 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx->id); return(ctx->wait_lock->trx->id);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* Select the joining transaction as the victim. */ /* Select the joining transaction as the victim. */
...@@ -4528,6 +4551,7 @@ lock_table_create( ...@@ -4528,6 +4551,7 @@ lock_table_create(
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 (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER( UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock); un_member.tab_lock.locks, table->locks, c_lock, lock);
...@@ -4535,12 +4559,18 @@ lock_table_create( ...@@ -4535,12 +4559,18 @@ lock_table_create(
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
} }
if (c_lock) trx_mutex_enter(c_lock->trx); if (c_lock) {
trx_mutex_enter(c_lock->trx);
}
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock); if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
wsrep_print_wait_locks(c_lock->trx->lock.wait_lock);
}
/* have to release trx mutex for the duration of /* have to release trx mutex for the duration of
victim lock release. This will eventually call victim lock release. This will eventually call
...@@ -4563,7 +4593,12 @@ lock_table_create( ...@@ -4563,7 +4593,12 @@ lock_table_create(
(ulonglong) c_lock->trx->id); (ulonglong) c_lock->trx->id);
} }
} }
if (c_lock) trx_mutex_exit(c_lock->trx); if (c_lock) {
trx_mutex_exit(c_lock->trx);
}
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
#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 */
...@@ -4850,11 +4885,15 @@ lock_table_other_has_incompatible( ...@@ -4850,11 +4885,15 @@ lock_table_other_has_incompatible(
&& (wait || !lock_get_wait(lock))) { && (wait || !lock_get_wait(lock))) {
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_debug) if(wsrep_thd_is_wsrep(trx->mysql_thd)) {
fprintf(stderr, "WSREP: table lock abort"); if (wsrep_debug) {
fprintf(stderr, "WSREP: trx %ld table lock abort\n",
trx->id);
}
trx_mutex_enter(lock->trx); trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx); trx_mutex_exit(lock->trx);
}
#endif #endif
return(lock); return(lock);
...@@ -6110,6 +6149,7 @@ lock_rec_queue_validate( ...@@ -6110,6 +6149,7 @@ lock_rec_queue_validate(
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
#ifndef WITH_WSREP #ifndef WITH_WSREP
if (wsrep_thd_is_wsrep(lock->trx->mysql_thd)) {
enum lock_mode mode; enum lock_mode mode;
if (lock_get_mode(lock) == LOCK_S) { if (lock_get_mode(lock) == LOCK_S) {
...@@ -6119,6 +6159,7 @@ lock_rec_queue_validate( ...@@ -6119,6 +6159,7 @@ lock_rec_queue_validate(
} }
ut_a(!lock_rec_other_has_expl_req( ut_a(!lock_rec_other_has_expl_req(
mode, 0, 0, block, heap_no, lock->trx)); mode, 0, 0, block, heap_no, lock->trx));
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
......
...@@ -10371,7 +10371,6 @@ ha_innobase::wsrep_append_keys( ...@@ -10371,7 +10371,6 @@ ha_innobase::wsrep_append_keys(
uint len; uint len;
char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
char *key = &keyval[0]; char *key = &keyval[0];
KEY *key_info = table->key_info;
ibool is_null; ibool is_null;
len = wsrep_store_key_val_for_row( len = wsrep_store_key_val_for_row(
...@@ -18218,18 +18217,18 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18218,18 +18217,18 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
if (!thd) { if (!thd) {
DBUG_PRINT("wsrep", ("no thd for conflicting lock")); DBUG_PRINT("wsrep", ("no thd for conflicting lock"));
WSREP_WARN("no THD for trx: %llu", victim_trx->id); WSREP_WARN("no THD for trx: %lu", victim_trx->id);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (!bf_thd) { if (!bf_thd) {
DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); DBUG_PRINT("wsrep", ("no BF thd for conflicting lock"));
WSREP_WARN("no BF THD for trx: %llu", (bf_trx) ? bf_trx->id : 0); WSREP_WARN("no BF THD for trx: %lu", (bf_trx) ? bf_trx->id : 0);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %lu",
signal, (long long)bf_seqno, signal, (long long)bf_seqno,
wsrep_thd_thread_id(thd), wsrep_thd_thread_id(thd),
victim_trx->id); victim_trx->id);
...@@ -18240,12 +18239,12 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18240,12 +18239,12 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_LOCK(thd); wsrep_thd_LOCK(thd);
if (wsrep_thd_query_state(thd) == QUERY_EXITING) { if (wsrep_thd_query_state(thd) == QUERY_EXITING) {
WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id); WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id);
wsrep_thd_UNLOCK(thd); wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
WSREP_DEBUG("withdraw for BF trx: %llu, state: %d", WSREP_DEBUG("withdraw for BF trx: %lu, state: %d",
victim_trx->id, victim_trx->id,
wsrep_thd_conflict_state(thd)); wsrep_thd_conflict_state(thd));
} }
...@@ -18255,7 +18254,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18255,7 +18254,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
wsrep_thd_set_conflict_state(thd, MUST_ABORT); wsrep_thd_set_conflict_state(thd, MUST_ABORT);
break; break;
case MUST_ABORT: case MUST_ABORT:
WSREP_DEBUG("victim %llu in MUST ABORT state", WSREP_DEBUG("victim %lu in MUST ABORT state",
victim_trx->id); victim_trx->id);
wsrep_thd_UNLOCK(thd); wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
...@@ -18264,7 +18263,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18264,7 +18263,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
case ABORTED: case ABORTED:
case ABORTING: // fall through case ABORTING: // fall through
default: default:
WSREP_DEBUG("victim %llu in state %d", WSREP_DEBUG("victim %lu in state %d",
victim_trx->id, wsrep_thd_conflict_state(thd)); victim_trx->id, wsrep_thd_conflict_state(thd));
wsrep_thd_UNLOCK(thd); wsrep_thd_UNLOCK(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
...@@ -18277,7 +18276,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18277,7 +18276,7 @@ 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_DEBUG("kill trx QUERY_COMMITTING for %llu", WSREP_DEBUG("kill trx QUERY_COMMITTING for %lu",
victim_trx->id); victim_trx->id);
if (wsrep_thd_exec_mode(thd) == REPL_RECV) { if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
...@@ -18291,7 +18290,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18291,7 +18290,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
switch (rcode) { switch (rcode) {
case WSREP_WARNING: case WSREP_WARNING:
WSREP_DEBUG("cancel commit warning: %llu", WSREP_DEBUG("cancel commit warning: %lu",
victim_trx->id); victim_trx->id);
wsrep_thd_UNLOCK(thd); wsrep_thd_UNLOCK(thd);
wsrep_thd_awake(thd, signal); wsrep_thd_awake(thd, signal);
...@@ -18301,7 +18300,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18301,7 +18300,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
break; break;
default: default:
WSREP_ERROR( WSREP_ERROR(
"cancel commit bad exit: %d %llu", "cancel commit bad exit: %d %lu",
rcode, rcode,
victim_trx->id); victim_trx->id);
/* unable to interrupt, must abort */ /* unable to interrupt, must abort */
...@@ -18319,7 +18318,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18319,7 +18318,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
/* it is possible that victim trx is itself waiting for some /* it is possible that victim trx is itself waiting for some
* other lock. We need to cancel this waiting * other lock. We need to cancel this waiting
*/ */
WSREP_DEBUG("kill trx QUERY_EXEC for %llu", victim_trx->id); WSREP_DEBUG("kill trx QUERY_EXEC for %lu", victim_trx->id);
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
if (victim_trx->lock.wait_lock) { if (victim_trx->lock.wait_lock) {
...@@ -18357,7 +18356,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr, ...@@ -18357,7 +18356,7 @@ wsrep_innobase_kill_one_trx(void * const bf_thd_ptr,
bool skip_abort= false; bool skip_abort= false;
wsrep_aborting_thd_t abortees; wsrep_aborting_thd_t abortees;
WSREP_DEBUG("kill IDLE for %llu", victim_trx->id); WSREP_DEBUG("kill IDLE for %lu", victim_trx->id);
if (wsrep_thd_exec_mode(thd) == REPL_RECV) { if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
WSREP_DEBUG("kill BF IDLE, seqno: %lld", WSREP_DEBUG("kill BF IDLE, seqno: %lld",
......
...@@ -293,6 +293,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr, ...@@ -293,6 +293,7 @@ wsrep_innobase_kill_one_trx(void *thd_ptr,
my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); my_bool wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe);
int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); int wsrep_thd_conflict_state(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync); my_bool wsrep_thd_is_BF(void *thd_ptr, my_bool sync);
my_bool wsrep_thd_is_wsrep(void *thd_ptr);
int wsrep_trx_order_before(void *thd1, void *thd2); int wsrep_trx_order_before(void *thd1, void *thd2);
int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, int wsrep_innobase_mysql_sort(int mysql_type, uint charset_number,
unsigned char* str, unsigned int str_length, unsigned char* str, unsigned int str_length,
......
...@@ -1663,8 +1663,12 @@ lock_rec_other_has_expl_req( ...@@ -1663,8 +1663,12 @@ lock_rec_other_has_expl_req(
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
#ifdef WITH_WSREP #ifdef WITH_WSREP
static void static
wsrep_kill_victim(const trx_t * const trx, const 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_BF(trx->mysql_thd, FALSE); my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
...@@ -1675,30 +1679,36 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { ...@@ -1675,30 +1679,36 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
trx->mysql_thd, lock->trx->mysql_thd))) { trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) if (wsrep_debug) {
fprintf(stderr, "WSREP: BF victim waiting\n"); fprintf(stderr, "WSREP: BF victim waiting\n");
}
/* cannot release lock, until our lock /* cannot release lock, until our lock
is in the queue*/ is in the queue*/
} else if (lock->trx != trx) { } else if (lock->trx != trx) {
if (wsrep_log_conflicts) { if (wsrep_log_conflicts) {
mutex_enter(&trx_sys->mutex); mutex_enter(&trx_sys->mutex);
if (bf_this) if (bf_this) {
fputs("\n*** Priority TRANSACTION:\n", fputs("\n*** Priority TRANSACTION:\n",
stderr); stderr);
else } else {
fputs("\n*** Victim TRANSACTION:\n", fputs("\n*** Victim TRANSACTION:\n",
stderr); stderr);
}
trx_print_latched(stderr, trx, 3000); trx_print_latched(stderr, trx, 3000);
if (bf_other) if (bf_other) {
fputs("\n*** Priority TRANSACTION:\n", fputs("\n*** Priority TRANSACTION:\n",
stderr); stderr);
else } else {
fputs("\n*** Victim TRANSACTION:\n", fputs("\n*** Victim TRANSACTION:\n",
stderr); stderr);
}
trx_print_latched(stderr, lock->trx, 3000); trx_print_latched(stderr, lock->trx, 3000);
mutex_exit(&trx_sys->mutex); mutex_exit(&trx_sys->mutex);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
stderr); stderr);
...@@ -1708,6 +1718,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) { ...@@ -1708,6 +1718,7 @@ wsrep_kill_victim(const trx_t * const trx, const lock_t *lock) {
lock_table_print(stderr, lock); lock_table_print(stderr, 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);
} }
...@@ -2049,7 +2060,6 @@ lock_rec_create( ...@@ -2049,7 +2060,6 @@ lock_rec_create(
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
lock_t *hash = (lock_t *)c_lock->hash; lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL; lock_t *prev = NULL;
...@@ -2077,7 +2087,9 @@ lock_rec_create( ...@@ -2077,7 +2087,9 @@ lock_rec_create(
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock); if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
}
trx->lock.que_state = TRX_QUE_LOCK_WAIT; trx->lock.que_state = TRX_QUE_LOCK_WAIT;
lock_set_lock_and_trx_wait(lock, trx); lock_set_lock_and_trx_wait(lock, trx);
...@@ -2091,10 +2103,15 @@ lock_rec_create( ...@@ -2091,10 +2103,15 @@ lock_rec_create(
victim lock release. This will eventually call victim lock release. This will eventually call
lock_grant, which wants to grant trx mutex again lock_grant, which wants to grant trx mutex again
*/ */
if (caller_owns_trx_mutex) trx_mutex_exit(trx); if (caller_owns_trx_mutex) {
trx_mutex_exit(trx);
}
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
c_lock->trx->lock.wait_lock); c_lock->trx->lock.wait_lock);
if (caller_owns_trx_mutex) trx_mutex_enter(trx);
if (caller_owns_trx_mutex) {
trx_mutex_enter(trx);
}
/* trx might not wait for c_lock, but some other lock /* trx might not wait for c_lock, but some other lock
does not matter if wait_lock was released above does not matter if wait_lock was released above
...@@ -2102,12 +2119,15 @@ lock_rec_create( ...@@ -2102,12 +2119,15 @@ lock_rec_create(
if (c_lock->trx->lock.wait_lock == c_lock) { if (c_lock->trx->lock.wait_lock == c_lock) {
lock_reset_lock_and_trx_wait(lock); lock_reset_lock_and_trx_wait(lock);
} }
trx_mutex_exit(c_lock->trx); trx_mutex_exit(c_lock->trx);
if (wsrep_debug) fprintf( if (wsrep_debug) {
fprintf(
stderr, stderr,
"WSREP: c_lock canceled %llu\n", "WSREP: c_lock canceled %llu\n",
(ulonglong) c_lock->trx->id); (ulonglong) c_lock->trx->id);
}
/* have to bail out here to avoid lock_set_lock... */ /* have to bail out here to avoid lock_set_lock... */
return(lock); return(lock);
...@@ -2331,7 +2351,7 @@ lock_rec_add_to_queue( ...@@ -2331,7 +2351,7 @@ lock_rec_add_to_queue(
block, heap_no, trx->id); block, heap_no, trx->id);
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* this can potentionally assert with wsrep */ /* this can potentionally assert with wsrep */
if (wsrep_on(trx->mysql_thd)) { if (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (wsrep_debug && other_lock) { if (wsrep_debug && other_lock) {
fprintf(stderr, fprintf(stderr,
"WSREP: InnoDB assert ignored\n"); "WSREP: InnoDB assert ignored\n");
...@@ -2578,8 +2598,8 @@ lock_rec_lock_slow( ...@@ -2578,8 +2598,8 @@ lock_rec_lock_slow(
/* c_lock is NULL here if jump to enqueue_waiting happened /* c_lock is NULL here if jump to enqueue_waiting happened
but it's ok because lock is not NULL in that case and c_lock but it's ok because lock is not NULL in that case and c_lock
is not used. */ is not used. */
err= err = lock_rec_enqueue_waiting(c_lock,
lock_rec_enqueue_waiting(c_lock, mode, block, heap_no, index, thr); mode, block, heap_no, index, thr);
#else #else
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
mode, block, heap_no, index, thr); mode, block, heap_no, index, thr);
...@@ -4083,16 +4103,18 @@ lock_deadlock_select_victim( ...@@ -4083,16 +4103,18 @@ lock_deadlock_select_victim(
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_BF(ctx->start->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->start); return(ctx->start);
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->wait_lock->trx->mysql_thd, TRUE)) {
return(ctx->start); return(ctx->start);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return(ctx->wait_lock->trx); return(ctx->wait_lock->trx);
...@@ -4226,8 +4248,9 @@ lock_deadlock_search( ...@@ -4226,8 +4248,9 @@ lock_deadlock_search(
ctx->too_deep = TRUE; ctx->too_deep = TRUE;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) if (wsrep_thd_is_BF(ctx->start->mysql_thd, TRUE)) {
return(ctx->wait_lock->trx->id); return(ctx->wait_lock->trx->id);
}
else else
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
/* Select the joining transaction as the victim. */ /* Select the joining transaction as the victim. */
...@@ -4555,6 +4578,7 @@ lock_table_create( ...@@ -4555,6 +4578,7 @@ lock_table_create(
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 (wsrep_thd_is_wsrep(trx->mysql_thd)) {
if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
UT_LIST_INSERT_AFTER( UT_LIST_INSERT_AFTER(
un_member.tab_lock.locks, table->locks, c_lock, lock); un_member.tab_lock.locks, table->locks, c_lock, lock);
...@@ -4562,12 +4586,18 @@ lock_table_create( ...@@ -4562,12 +4586,18 @@ lock_table_create(
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
} }
if (c_lock) trx_mutex_enter(c_lock->trx); if (c_lock) {
trx_mutex_enter(c_lock->trx);
}
if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE;
if (wsrep_debug) wsrep_print_wait_locks(c_lock); if (wsrep_debug) {
wsrep_print_wait_locks(c_lock);
wsrep_print_wait_locks(c_lock->trx->lock.wait_lock);
}
/* have to release trx mutex for the duration of /* have to release trx mutex for the duration of
victim lock release. This will eventually call victim lock release. This will eventually call
...@@ -4590,7 +4620,12 @@ lock_table_create( ...@@ -4590,7 +4620,12 @@ lock_table_create(
(ulonglong) c_lock->trx->id); (ulonglong) c_lock->trx->id);
} }
} }
if (c_lock) trx_mutex_exit(c_lock->trx); if (c_lock) {
trx_mutex_exit(c_lock->trx);
}
} else {
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
}
#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 */
...@@ -4884,11 +4919,15 @@ lock_table_other_has_incompatible( ...@@ -4884,11 +4919,15 @@ lock_table_other_has_incompatible(
&& (wait || !lock_get_wait(lock))) { && (wait || !lock_get_wait(lock))) {
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (wsrep_debug) if(wsrep_thd_is_wsrep(trx->mysql_thd)) {
fprintf(stderr, "WSREP: table lock abort"); if (wsrep_debug) {
fprintf(stderr, "WSREP: trx %ld table lock abort\n",
trx->id);
}
trx_mutex_enter(lock->trx); trx_mutex_enter(lock->trx);
wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); wsrep_kill_victim((trx_t *)trx, (lock_t *)lock);
trx_mutex_exit(lock->trx); trx_mutex_exit(lock->trx);
}
#endif #endif
return(lock); return(lock);
...@@ -6158,6 +6197,7 @@ lock_rec_queue_validate( ...@@ -6158,6 +6197,7 @@ lock_rec_queue_validate(
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
#ifndef WITH_WSREP #ifndef WITH_WSREP
if (wsrep_thd_is_wsrep(lock->trx->mysql_thd)) {
enum lock_mode mode; enum lock_mode mode;
if (lock_get_mode(lock) == LOCK_S) { if (lock_get_mode(lock) == LOCK_S) {
...@@ -6167,6 +6207,7 @@ lock_rec_queue_validate( ...@@ -6167,6 +6207,7 @@ lock_rec_queue_validate(
} }
ut_a(!lock_rec_other_has_expl_req( ut_a(!lock_rec_other_has_expl_req(
mode, 0, 0, block, heap_no, lock->trx)); mode, 0, 0, block, heap_no, lock->trx));
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment