diff options
Diffstat (limited to 'storage/innobase/include/trx0sys.h')
-rw-r--r-- | storage/innobase/include/trx0sys.h | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 437459865fe..e80b222d260 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -514,8 +514,10 @@ class rw_trx_hash_t { ut_ad(!trx->read_only || !trx->rsegs.m_redo.rseg); ut_ad(!trx_is_autocommit_non_locking(trx)); + /* trx->state can be anything except TRX_STATE_NOT_STARTED */ mutex_enter(&trx->mutex); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || + trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) || trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || trx_state_eq(trx, TRX_STATE_PREPARED)); mutex_exit(&trx->mutex); @@ -626,12 +628,7 @@ public: The caller should already have handled trx_id==0 specially. */ ut_ad(trx_id); - if (caller_trx && caller_trx->id == trx_id) - { - if (do_ref_count) - caller_trx->reference(); - return caller_trx; - } + ut_ad(!caller_trx || caller_trx->id != trx_id || !do_ref_count); trx_t *trx= 0; LF_PINS *pins= caller_trx ? get_pins(caller_trx) : lf_hash_get_pins(&hash); @@ -646,9 +643,25 @@ public: lf_hash_search_unpin(pins); if ((trx= element->trx)) { DBUG_ASSERT(trx_id == trx->id); - if (do_ref_count) - trx->reference(); ut_d(validate_element(trx)); + if (do_ref_count) + { + /* + We have an early state check here to avoid committer + starvation in a wait loop for transaction references, + when there's a stream of trx_sys.find() calls from other + threads. The trx->state may change to COMMITTED after + trx->mutex is released, and it will have to be rechecked + by the caller after reacquiring the mutex. + */ + trx_mutex_enter(trx); + const trx_state_t state= trx->state; + trx_mutex_exit(trx); + if (state == TRX_STATE_COMMITTED_IN_MEMORY) + trx= NULL; + else + trx->reference(); + } } mutex_exit(&element->mutex); } @@ -932,7 +945,7 @@ public: /** Takes MVCC snapshot. - To reduce malloc probablility we reserver rw_trx_hash.size() + 32 elements + To reduce malloc probablility we reserve rw_trx_hash.size() + 32 elements in ids. For details about get_rw_trx_hash_version() != get_max_trx_id() spin |