mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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>
This commit is contained in:
@ -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
|
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)
|
|||||||
|
|
||||||
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)
|
|||||||
(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(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#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(
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user