summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsjaakola <seppo.jaakola@iki.fi>2022-10-12 14:13:49 +0300
committerJan Lindström <jan.lindstrom@mariadb.com>2023-01-14 07:50:04 +0200
commita44d896f98f2d2a3ebf0f1393bf84fd659ecd225 (patch)
tree1a7c04f773aa01e0f3f246f45dd7ebb83d669535
parent0ff7f33c7b5d0b5373472f4706aff4d19dc84258 (diff)
downloadmariadb-git-a44d896f98f2d2a3ebf0f1393bf84fd659ecd225.tar.gz
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: Jan Lindström <jan.lindstrom@mariadb.com>
-rw-r--r--sql/service_wsrep.cc6
-rw-r--r--sql/sql_class.cc2
-rw-r--r--storage/innobase/lock/lock0lock.cc53
3 files changed, 39 insertions, 22 deletions
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index 7b0a1e5495e..722c22809de 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -1,4 +1,4 @@
-/* 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
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)
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",
(long long)wsrep_thd_trx_seqno(left),
(long long)wsrep_thd_trx_seqno(right));
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index b516791b6da..464d64db73b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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)
*/
if (WSREP_ON &&
- wsrep_thd_is_BF(thd, false) &&
- wsrep_thd_is_BF(other_thd, false) &&
wsrep_thd_order_before(thd, other_thd))
return 0;
#endif /* WITH_WSREP */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index e10d0c9f2b5..26388ad95e2 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -819,25 +819,34 @@ lock_rec_has_to_wait(
}
#ifdef WITH_WSREP
- /* New lock request from a transaction is using unique key
- scan and this transaction is a wsrep high priority transaction
- (brute force). If conflicting transaction is also wsrep high
- priority transaction we should avoid lock conflict because
- ordering of these transactions is already decided and
- conflicting transaction will be later replayed. Note
- that thread holding conflicting lock can't be
- committed or rolled back while we hold
- lock_sys->mutex. */
- if (trx->is_wsrep_UK_scan()
- && wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) {
- return false;
- }
+ /* New lock request from a transaction is using unique key
+ scan and this transaction is a wsrep high priority transaction
+ (brute force). If conflicting transaction is also wsrep high
+ priority transaction we should avoid lock conflict because
+ ordering of these transactions is already decided and
+ conflicting transaction will be later replayed. Note
+ that thread holding conflicting lock can't be
+ committed or rolled back while we hold
+ lock_sys->mutex. */
+ if (trx->is_wsrep_UK_scan()
+ && wsrep_thd_is_BF(lock2->trx->mysql_thd, false)) {
+ 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));
+ /* If BF-BF conflict, we have to look at write set order */
+ if (trx->is_wsrep()
+ && (type_mode & LOCK_MODE_MASK) == LOCK_X
+ && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X
+ && 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 */
return true;
@@ -2043,6 +2052,14 @@ lock_rec_has_to_wait_in_queue(
if (heap_no < lock_rec_get_n_bits(lock)
&& (p[bit_offset] & bit_mask)
&& 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);
}
}