Commit a44d896f authored by sjaakola's avatar sjaakola Committed by Jan Lindström

10.4-MDEV-29684 Fixes for cluster wide write conflict resolving

If two high priority threads have lock conflict, we look at the
order of these transactions and honor the earlier transaction.
for_locking parameter in lock_rec_has_to_wait() has become
obsolete and it is now removed from the code .
Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
parent 0ff7f33c
/* Copyright 2018-2021 Codership Oy <info@codership.com> /* Copyright 2018-2023 Codership Oy <info@codership.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -274,7 +274,9 @@ extern "C" my_bool wsrep_thd_skip_locking(const THD *thd) ...@@ -274,7 +274,9 @@ extern "C" my_bool wsrep_thd_skip_locking(const THD *thd)
extern "C" my_bool wsrep_thd_order_before(const THD *left, const THD *right) extern "C" my_bool wsrep_thd_order_before(const THD *left, const THD *right)
{ {
if (wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) { if (wsrep_thd_is_BF(left, false) &&
wsrep_thd_is_BF(right, false) &&
wsrep_thd_trx_seqno(left) < wsrep_thd_trx_seqno(right)) {
WSREP_DEBUG("BF conflict, order: %lld %lld\n", WSREP_DEBUG("BF conflict, order: %lld %lld\n",
(long long)wsrep_thd_trx_seqno(left), (long long)wsrep_thd_trx_seqno(left),
(long long)wsrep_thd_trx_seqno(right)); (long long)wsrep_thd_trx_seqno(right));
......
...@@ -5230,8 +5230,6 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd) ...@@ -5230,8 +5230,6 @@ thd_need_ordering_with(const MYSQL_THD thd, const MYSQL_THD other_thd)
(e.g. InnoDB does it by keeping lock_sys.mutex locked) (e.g. InnoDB does it by keeping lock_sys.mutex locked)
*/ */
if (WSREP_ON && if (WSREP_ON &&
wsrep_thd_is_BF(thd, false) &&
wsrep_thd_is_BF(other_thd, false) &&
wsrep_thd_order_before(thd, other_thd)) wsrep_thd_order_before(thd, other_thd))
return 0; return 0;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
......
...@@ -819,25 +819,34 @@ lock_rec_has_to_wait( ...@@ -819,25 +819,34 @@ lock_rec_has_to_wait(
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* New lock request from a transaction is using unique key /* New lock request from a transaction is using unique key
scan and this transaction is a wsrep high priority transaction scan and this transaction is a wsrep high priority transaction
(brute force). If conflicting transaction is also wsrep high (brute force). If conflicting transaction is also wsrep high
priority transaction we should avoid lock conflict because priority transaction we should avoid lock conflict because
ordering of these transactions is already decided and ordering of these transactions is already decided and
conflicting transaction will be later replayed. Note conflicting transaction will be later replayed. Note
that thread holding conflicting lock can't be that thread holding conflicting lock can't be
committed or rolled back while we hold committed or rolled back while we hold
lock_sys->mutex. */ lock_sys->mutex. */
if (trx->is_wsrep_UK_scan() if (trx->is_wsrep_UK_scan()
&& wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) { && wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) {
return false; return false;
} }
/* We very well can let bf to wait normally as other /* If BF-BF conflict, we have to look at write set order */
BF will be replayed in case of conflict. For debug if (trx->is_wsrep()
builds we will do additional sanity checks to catch && (type_mode & LOCK_MODE_MASK) == LOCK_X
unsupported bf wait if any. */ && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X
ut_d(wsrep_assert_no_bf_bf_wait(lock2, trx)); && wsrep_thd_order_before(trx->mysql_thd,
lock2->trx->mysql_thd)) {
return false;
}
/* We very well can let bf to wait normally as other
BF will be replayed in case of conflict. For debug
builds we will do additional sanity checks to catch
unsupported bf wait if any. */
ut_d(wsrep_assert_no_bf_bf_wait(lock2, trx));
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
return true; return true;
...@@ -2043,6 +2052,14 @@ lock_rec_has_to_wait_in_queue( ...@@ -2043,6 +2052,14 @@ lock_rec_has_to_wait_in_queue(
if (heap_no < lock_rec_get_n_bits(lock) if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask) && (p[bit_offset] & bit_mask)
&& lock_has_to_wait(wait_lock, lock)) { && lock_has_to_wait(wait_lock, lock)) {
#ifdef WITH_WSREP
if (lock->trx->is_wsrep()
&& wsrep_thd_order_before(wait_lock->trx->mysql_thd,
lock->trx->mysql_thd)) {
/* don't wait for another BF lock */
continue;
}
#endif
return(lock); return(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