Commit dc4e5281 authored by Jan Lindström's avatar Jan Lindström Committed by Julius Goryavsky

MDEV-31062 : Reduce number of wsrep calls to server code from InnoDB

Thread executing wsrep transaction can't change during transaction
execution. Similarly, thread executing high priority brute force
(BF) transaction does not change during transaction execution.
Therefore, in both cases there is no need to call server
code after transaction has initialized.

InnoDB already stores information is this wsrep transaction to
trx_t::wsrep and this is checked using trx->is_wsrep() function.
Because, brute force transaction is always a wsrep transaction
we can extend trx_t::wsrep variable so that value

0 == not wsrep transaction (and not BF)
1 == normal wsrep transaction
2 == high priority BF wsrep transaction
4 == high priority BF transaction is performing unique secondary index scan

These values can be set by calling server code on innobase_trx_init().
After that we can use trx_t::is_wsrep() and new function
introduced in this patch trx_t::is_wsrep_BF(). Unique
secondary index scan is determined later but it implies BF,
so this patch removes unnecessary variable trx_t::wsrep_UK_scan.
Patch introduces new functions trx_t::is_wsrep_UK_scan(),
wsrep_begin_UK_scan() and wsrep_end_UK_scan() to handle
unique secondary index scan.

This change reduces number of calls to server code from InnoDB and
reduces code bloat on performance critical stages like acquiring
record locks. Furthermore, it simplifies code on several locations.

This patch also removes unnecessary trx_t::wsrep_event that
was always set to NULL and not used.
Signed-off-by: default avatarJulius Goryavsky <julius.goryavsky@mariadb.com>
parent a3186c1f
......@@ -3242,17 +3242,16 @@ btr_cur_ins_lock_and_undo(
wsrep high priority threads. To avoid this
GAP-locking we mark that this transaction
is using unique key scan here. */
if ((type & (DICT_CLUSTERED | DICT_UNIQUE)) == DICT_UNIQUE
&& trx->is_wsrep()
&& wsrep_thd_is_BF(trx->mysql_thd, false)) {
trx->wsrep_UK_scan= true;
if ((type & (DICT_CLUSTERED | DICT_UNIQUE)) == DICT_UNIQUE) {
trx->wsrep_begin_UK_scan();
}
#endif /* WITH_WSREP */
err = lock_rec_insert_check_and_lock(
flags, rec, btr_cur_get_block(cursor),
index, thr, mtr, inherit);
#ifdef WITH_WSREP
trx->wsrep_UK_scan= false;
trx->wsrep_end_UK_scan();
#endif /* WITH_WSREP */
}
}
......
......@@ -179,9 +179,8 @@ void dict_stats_update_if_needed_func(dict_table_t *table)
generated row locks and allow BF thread
lock waits to be enqueued at head of waiting
queue. */
if (trx.is_wsrep()
&& !wsrep_thd_is_applying(trx.mysql_thd)
&& wsrep_thd_is_BF(trx.mysql_thd, 0)) {
if (trx.is_wsrep_BF()
&& !wsrep_thd_is_applying(trx.mysql_thd)) {
WSREP_DEBUG("Avoiding background statistics"
" calculation for table %s.",
table->name.m_name);
......
......@@ -2382,7 +2382,9 @@ innobase_trx_init(
trx->check_unique_secondary = !thd_test_options(
thd, OPTION_RELAXED_UNIQUE_CHECKS);
#ifdef WITH_WSREP
trx->wsrep = wsrep_on(thd);
trx->wsrep = wsrep_on(thd) ?
(wsrep_thd_is_BF(thd, true) ? (trx_t::WSREP_BF | trx_t::WSREP)
: trx_t::WSREP) : 0;
#endif
DBUG_VOID_RETURN;
......@@ -4176,7 +4178,7 @@ innobase_commit_low(
} else {
trx->will_lock = false;
#ifdef WITH_WSREP
trx->wsrep = false;
trx->wsrep = 0;
#endif /* WITH_WSREP */
}
......@@ -18905,7 +18907,7 @@ wsrep_innobase_kill_one_trx(
"trx_id: " TRX_ID_FMT " thread: %ld "
"seqno: %lld client_state: %s client_mode: %s "
"trx_state %s query: %s",
wsrep_thd_is_BF(thd, false) ? "BF" : "normal",
victim_trx->is_wsrep_BF() ? "BF" : "normal",
victim_trx->id,
thd_get_thread_id(thd),
wsrep_thd_trx_seqno(thd),
......
......@@ -732,14 +732,33 @@ struct trx_t : ilist_node<> {
Transitions to COMMITTED are protected by trx_t::mutex. */
trx_state_t state;
#ifdef WITH_WSREP
/** whether wsrep_on(mysql_thd) held at the start of transaction */
bool wsrep;
/** wsrep_on(mysql_thd) held at the start of transaction */
static constexpr byte WSREP = byte{1};
/** wsrep_thd_is_BF(mysql_thd) held at start of transaction */
static constexpr byte WSREP_BF = byte{2};
/** BF thread is performing unique secondary index scan */
static constexpr byte WSREP_UK_SCAN = byte{4};
/** combination of the flags WSREP, WSREP_BF, WSREP_UK_SCAN. **/
byte wsrep;
/** true, if thread has wsrep_on */
bool is_wsrep() const { return UNIV_UNLIKELY(wsrep); }
/** true, if thread is high priority brute force (BF) */
bool is_wsrep_BF() const { return UNIV_UNLIKELY(wsrep & trx_t::WSREP_BF); }
/** true, if BF thread is performing unique secondary index scanning */
bool wsrep_UK_scan;
bool is_wsrep_UK_scan() const { return UNIV_UNLIKELY(wsrep_UK_scan); }
bool is_wsrep_UK_scan() const { return UNIV_UNLIKELY(wsrep & trx_t::WSREP_UK_SCAN); }
/** begin unique secondary index scan in wsrep BF thread */
void wsrep_begin_UK_scan()
{
if (is_wsrep_BF())
wsrep |= trx_t::WSREP_UK_SCAN;
}
/** end unique secondary index scan in wsrep BF thread */
void wsrep_end_UK_scan() {wsrep &= static_cast<byte>(~(trx_t::WSREP_UK_SCAN)); }
#else /* WITH_WSREP */
bool is_wsrep() const { return false; }
bool is_wsrep_BF() const {return false; }
void wsrep_begin_UK_scan() const {}
void wsrep_end_UK_scan() const {}
#endif /* WITH_WSREP */
ReadView read_view; /*!< consistent read view used in the
......@@ -930,6 +949,7 @@ struct trx_t : ilist_node<> {
/*------------------------------*/
char* detailed_error; /*!< detailed error message for last
error, or empty. */
rw_trx_hash_element_t *rw_trx_hash_element;
LF_PINS *rw_trx_hash_pins;
ulint magic_n;
......
......@@ -628,8 +628,8 @@ static void wsrep_assert_no_bf_bf_wait(const lock_t *lock, const trx_t *trx)
if (!trx->is_wsrep() || !lock_trx->is_wsrep())
return;
if (UNIV_LIKELY(!wsrep_thd_is_BF(trx->mysql_thd, FALSE))
|| UNIV_LIKELY(!wsrep_thd_is_BF(lock_trx->mysql_thd, FALSE)))
if (UNIV_LIKELY(!trx->is_wsrep_BF())
|| UNIV_LIKELY(!lock_trx->is_wsrep_BF()))
return;
ut_ad(trx->state == TRX_STATE_ACTIVE);
......@@ -798,7 +798,7 @@ lock_rec_has_to_wait(
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)) {
&& lock2->trx->is_wsrep_BF()) {
return false;
}
......@@ -1066,14 +1066,14 @@ static void wsrep_kill_victim(const trx_t * const trx, const lock_t *lock)
ut_ad(trx_mutex_own(lock_trx));
ut_ad(lock_trx != trx);
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE))
if (!trx->is_wsrep_BF())
return;
if (lock_trx->state == TRX_STATE_COMMITTED_IN_MEMORY
|| lock_trx->lock.was_chosen_as_deadlock_victim)
return;
if (!wsrep_thd_is_BF(lock_trx->mysql_thd, FALSE)
if (!lock_trx->is_wsrep_BF()
|| wsrep_thd_order_before(trx->mysql_thd, lock_trx->mysql_thd)) {
if (lock_trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (UNIV_UNLIKELY(wsrep_debug))
......@@ -1370,12 +1370,11 @@ lock_rec_create_low(
ut_ad(index->table->get_ref_count() > 0 || !index->table->can_be_evicted);
#ifdef WITH_WSREP
if (c_lock && trx->is_wsrep()
&& wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (c_lock && trx->is_wsrep_BF()) {
lock_t *hash = (lock_t *)c_lock->hash;
lock_t *prev = NULL;
while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, FALSE)
while (hash && hash->trx->is_wsrep_BF()
&& wsrep_thd_order_before(hash->trx->mysql_thd,
trx->mysql_thd)) {
prev = hash;
......@@ -1806,8 +1805,8 @@ lock_rec_add_to_queue(
if (UNIV_LIKELY_NULL(other_lock) && trx->is_wsrep()) {
/* Only BF transaction may be granted lock
before other conflicting lock request. */
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)
&& !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) {
if (!trx->is_wsrep_BF()
&& !other_lock->trx->is_wsrep_BF()) {
/* If it is not BF, this case is a bug. */
wsrep_report_bf_lock_wait(trx->mysql_thd, trx->id);
wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id);
......@@ -3516,7 +3515,7 @@ lock_table_create(
#ifdef WITH_WSREP
if (c_lock && trx->is_wsrep()) {
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (trx->is_wsrep_BF()) {
ut_list_insert(table->locks, c_lock, lock,
TableLockGetNode());
if (UNIV_UNLIKELY(wsrep_debug)) {
......@@ -5066,8 +5065,8 @@ lock_rec_queue_validate(
/* Only BF transaction may be granted
lock before other conflicting lock
request. */
if (!wsrep_thd_is_BF(lock->trx->mysql_thd, FALSE)
&& !wsrep_thd_is_BF(other_lock->trx->mysql_thd, FALSE)) {
if (!lock->trx->is_wsrep_BF()
&& !other_lock->trx->is_wsrep_BF()) {
/* If no BF, this case is a bug. */
wsrep_report_bf_lock_wait(lock->trx->mysql_thd, lock->trx->id);
wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id);
......@@ -5766,8 +5765,7 @@ lock_sec_rec_modify_check_and_lock(
there is a probability for lock conflicts between two wsrep
high priority threads. To avoid this GAP-locking we mark that
this transaction is using unique key scan here. */
if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, false))
trx->wsrep_UK_scan= true;
trx->wsrep_begin_UK_scan();
#endif /* WITH_WSREP */
/* Another transaction cannot have an implicit lock on the record,
......@@ -5779,7 +5777,7 @@ lock_sec_rec_modify_check_and_lock(
block, heap_no, index, thr);
#ifdef WITH_WSREP
trx->wsrep_UK_scan= false;
trx->wsrep_end_UK_scan();
#endif /* WITH_WSREP */
#ifdef UNIV_DEBUG
......@@ -5870,7 +5868,7 @@ lock_sec_rec_read_check_and_lock(
if (!lock_table_has(trx, index->table, LOCK_X)
&& !page_rec_is_supremum(rec)
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
&& lock_rec_convert_impl_to_expl(trx, block, rec,
index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
......@@ -5885,15 +5883,14 @@ lock_sec_rec_read_check_and_lock(
there is a probability for lock conflicts between two wsrep
high priority threads. To avoid this GAP-locking we mark that
this transaction is using unique key scan here. */
if (trx->is_wsrep() && wsrep_thd_is_BF(trx->mysql_thd, false))
trx->wsrep_UK_scan= true;
trx->wsrep_begin_UK_scan();
#endif /* WITH_WSREP */
err = lock_rec_lock(FALSE, gap_mode | mode,
block, heap_no, index, thr);
#ifdef WITH_WSREP
trx->wsrep_UK_scan= false;
trx->wsrep_end_UK_scan();
#endif /* WITH_WSREP */
ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
......@@ -6741,7 +6738,7 @@ DeadlockChecker::select_victim() const
/* The joining transaction is 'smaller',
choose it as the victim and roll it back. */
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(m_start->mysql_thd, FALSE)) {
if (m_start->is_wsrep_BF()) {
return(m_wait_lock->trx);
}
#endif /* WITH_WSREP */
......@@ -6749,7 +6746,7 @@ DeadlockChecker::select_victim() const
}
#ifdef WITH_WSREP
if (wsrep_thd_is_BF(m_wait_lock->trx->mysql_thd, FALSE)) {
if (m_wait_lock->trx->is_wsrep_BF()) {
return(m_start);
}
#endif /* WITH_WSREP */
......
......@@ -192,8 +192,8 @@ wsrep_is_BF_lock_timeout(
const trx_t* trx)
{
bool long_wait= (trx->error_state != DB_DEADLOCK &&
srv_monitor_timer && trx->is_wsrep() &&
wsrep_thd_is_BF(trx->mysql_thd, false));
srv_monitor_timer &&
trx->is_wsrep_BF());
bool was_wait= true;
DBUG_EXECUTE_IF("wsrep_instrument_BF_lock_wait",
......
......@@ -165,7 +165,6 @@ trx_init(
trx->lock.table_cached = 0;
#ifdef WITH_WSREP
ut_ad(!trx->wsrep);
ut_ad(!trx->wsrep_UK_scan);
#endif /* WITH_WSREP */
}
......@@ -375,10 +374,6 @@ trx_t *trx_create()
ut_ad(trx->lock.rec_cached == 0);
ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
#ifdef WITH_WSREP
ut_ad(!trx->wsrep_UK_scan);
#endif /* WITH_WSREP */
trx_sys.register_trx(trx);
return(trx);
......@@ -476,10 +471,6 @@ void trx_t::free()
MEM_NOACCESS(&xid, sizeof xid);
MEM_NOACCESS(&mod_tables, sizeof mod_tables);
MEM_NOACCESS(&detailed_error, sizeof detailed_error);
#ifdef WITH_WSREP
ut_ad(!wsrep_UK_scan);
MEM_NOACCESS(&wsrep_UK_scan, sizeof wsrep_UK_scan);
#endif /* WITH_WSREP */
MEM_NOACCESS(&magic_n, sizeof magic_n);
trx_pools->mem_free(this);
}
......@@ -1407,7 +1398,7 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
order critical section. */
if (wsrep)
{
wsrep= false;
wsrep= 0;
wsrep_commit_ordered(mysql_thd);
}
lock.was_chosen_as_wsrep_victim= false;
......
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