Commit 7cf4419f authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-24789: Reduce lock_sys.wait_mutex contention

A performance regression was introduced by
commit e71e6133 (MDEV-24671)
and mostly addressed by
commit 455514c8.

The regression is likely caused by increased contention
lock_sys.latch (former lock_sys.mutex), possibly indirectly
caused by contention on lock_sys.wait_mutex. This change aims to
reduce both, but further improvements will be needed.

lock_wait(): Minimize the lock_sys.wait_mutex hold time.

lock_sys_t::deadlock_check(): Add a parameter for indicating
whether lock_sys.latch is exclusively locked.

trx_t::was_chosen_as_deadlock_victim: Always use atomics.

lock_wait_wsrep(): Assume that no mutex is being held.

Deadlock::report(): Always kill the victim transaction.

lock_sys_t::timeout: New counter to back MONITOR_TIMEOUT.
parent d9898c9a
...@@ -40,7 +40,7 @@ metadata_table_handles_opened metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NU ...@@ -40,7 +40,7 @@ metadata_table_handles_opened metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NU
metadata_table_handles_closed metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of table handles closed metadata_table_handles_closed metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of table handles closed
metadata_table_reference_count metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Table reference counter metadata_table_reference_count metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Table reference counter
lock_deadlocks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of deadlocks lock_deadlocks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of deadlocks
lock_timeouts lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of lock timeouts lock_timeouts lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of lock timeouts
lock_rec_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into record lock wait queue lock_rec_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into record lock wait queue
lock_table_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into table lock wait queue lock_table_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into table lock wait queue
lock_rec_lock_requests lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of record locks requested lock_rec_lock_requests lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of record locks requested
......
...@@ -4494,8 +4494,8 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels) ...@@ -4494,8 +4494,8 @@ static void innobase_kill_query(handlerton*, THD *thd, enum thd_kill_levels)
lock_cancel_waiting_and_release(lock); lock_cancel_waiting_and_release(lock);
trx->mutex_unlock(); trx->mutex_unlock();
} }
lock_sys.deadlock_check(true);
} }
lock_sys.deadlock_check();
mysql_mutex_unlock(&lock_sys.wait_mutex); mysql_mutex_unlock(&lock_sys.wait_mutex);
} }
} }
......
...@@ -710,6 +710,8 @@ class lock_sys_t ...@@ -710,6 +710,8 @@ class lock_sys_t
public: public:
/** number of deadlocks detected; protected by wait_mutex */ /** number of deadlocks detected; protected by wait_mutex */
ulint deadlocks; ulint deadlocks;
/** number of lock wait timeouts; protected by wait_mutex */
ulint timeouts;
/** /**
Constructor. Constructor.
...@@ -814,8 +816,9 @@ class lock_sys_t ...@@ -814,8 +816,9 @@ class lock_sys_t
void close(); void close();
/** Check for deadlocks */ /** Check for deadlocks
static void deadlock_check(); @param locked lock_sys.is_writer() */
static void deadlock_check(bool locked);
/** Note that a record lock wait started */ /** Note that a record lock wait started */
......
...@@ -429,19 +429,12 @@ struct trx_lock_t ...@@ -429,19 +429,12 @@ struct trx_lock_t
trx_t *wait_trx; trx_t *wait_trx;
/** condition variable for !wait_lock; used with lock_sys.wait_mutex */ /** condition variable for !wait_lock; used with lock_sys.wait_mutex */
pthread_cond_t cond; pthread_cond_t cond;
/** lock wait start time, protected only by lock_sys.wait_mutex */ /** lock wait start time */
my_hrtime_t suspend_time; Atomic_relaxed<my_hrtime_t> suspend_time;
#ifdef WITH_WSREP /** 2=high priority WSREP thread has marked this trx to abort;
/** 2=high priority wsrep thread has marked this trx to abort;
1=another transaction chose this as a victim in deadlock resolution. */ 1=another transaction chose this as a victim in deadlock resolution. */
Atomic_relaxed<byte> was_chosen_as_deadlock_victim; Atomic_relaxed<byte> was_chosen_as_deadlock_victim;
#else
/** When the transaction decides to wait for a lock, it clears this;
set if another transaction chooses this transaction as a victim in deadlock
resolution. Protected by lock_sys.latch and lock_sys.wait_mutex. */
bool was_chosen_as_deadlock_victim;
#endif
/** Next available rec_pool[] entry */ /** Next available rec_pool[] entry */
byte rec_cached; byte rec_cached;
......
This diff is collapsed.
...@@ -96,7 +96,8 @@ static monitor_info_t innodb_counter_info[] = ...@@ -96,7 +96,8 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_DEFAULT_START, MONITOR_DEADLOCK}, MONITOR_DEFAULT_START, MONITOR_DEADLOCK},
{"lock_timeouts", "lock", "Number of lock timeouts", {"lock_timeouts", "lock", "Number of lock timeouts",
MONITOR_DEFAULT_ON, static_cast<monitor_type_t>(
MONITOR_EXISTING | MONITOR_DEFAULT_ON | MONITOR_DISPLAY_CURRENT),
MONITOR_DEFAULT_START, MONITOR_TIMEOUT}, MONITOR_DEFAULT_START, MONITOR_TIMEOUT},
{"lock_rec_lock_waits", "lock", {"lock_rec_lock_waits", "lock",
...@@ -1883,6 +1884,9 @@ srv_mon_process_existing_counter( ...@@ -1883,6 +1884,9 @@ srv_mon_process_existing_counter(
case MONITOR_DEADLOCK: case MONITOR_DEADLOCK:
value = lock_sys.deadlocks; value = lock_sys.deadlocks;
break; break;
case MONITOR_TIMEOUT:
value = lock_sys.timeouts;
break;
default: default:
ut_error; ut_error;
......
...@@ -444,9 +444,8 @@ fill_trx_row( ...@@ -444,9 +444,8 @@ fill_trx_row(
ut_ad(!wait_lock == !requested_lock_row); ut_ad(!wait_lock == !requested_lock_row);
row->trx_wait_started = wait_lock const my_hrtime_t suspend_time= trx->lock.suspend_time;
? hrtime_to_time(trx->lock.suspend_time) row->trx_wait_started = wait_lock ? hrtime_to_time(suspend_time) : 0;
: 0;
row->trx_weight = static_cast<uintmax_t>(TRX_WEIGHT(trx)); row->trx_weight = static_cast<uintmax_t>(TRX_WEIGHT(trx));
......
...@@ -22,7 +22,7 @@ metadata_table_handles_opened metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NU ...@@ -22,7 +22,7 @@ metadata_table_handles_opened metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NU
metadata_table_handles_closed metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of table handles closed metadata_table_handles_closed metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of table handles closed
metadata_table_reference_count metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Table reference counter metadata_table_reference_count metadata 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Table reference counter
lock_deadlocks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of deadlocks lock_deadlocks lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of deadlocks
lock_timeouts lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of lock timeouts lock_timeouts lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 value Number of lock timeouts
lock_rec_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into record lock wait queue lock_rec_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into record lock wait queue
lock_table_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into table lock wait queue lock_table_lock_waits lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times enqueued into table lock wait queue
lock_rec_lock_requests lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of record locks requested lock_rec_lock_requests lock 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of record locks requested
......
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