diff options
author | Vlad Lesin <vlad_lesin@mail.ru> | 2022-03-07 18:42:47 +0300 |
---|---|---|
committer | Vlad Lesin <vlad_lesin@mail.ru> | 2022-03-07 18:42:47 +0300 |
commit | 202316a38fef8b9042e03ddf828e394f32cc51a2 (patch) | |
tree | ad391c8b6e4c29a84325aca7c5452fc13673453d /storage/innobase/lock | |
parent | b6a2472489accf0ae9ac3655ffe9b2997ab267ba (diff) | |
parent | 0b92c7b0e046df98136c7009c6ce7e6ff1974849 (diff) | |
download | mariadb-git-202316a38fef8b9042e03ddf828e394f32cc51a2.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'storage/innobase/lock')
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 145 |
1 files changed, 39 insertions, 106 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 5551c85db0b..bebd2acfa0d 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1004,43 +1004,24 @@ func_exit: /*********************************************************************//** Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. -@param[in] mode LOCK_S or LOCK_X, possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP, -LOCK_INSERT_INTENTION -@param[in] cell lock hash table cell -@param[in] id page identifier -@param[in] heap_no heap number of the record -@param[in] trx our transaction -@param[out] was_ignored true if conflicting locks waiting for the current -transaction were ignored -@return conflicting lock and the flag which indicated if conflicting locks -which wait for the current transaction were ignored */ -static lock_t *lock_rec_other_has_conflicting(unsigned mode, - const hash_cell_t &cell, - const page_id_t id, - ulint heap_no, const trx_t *trx, - bool *was_ignored= nullptr) +@return lock or NULL */ +static +lock_t* +lock_rec_other_has_conflicting( +/*===========================*/ + unsigned mode, /*!< in: LOCK_S or LOCK_X, + possibly ORed to LOCK_GAP or + LOC_REC_NOT_GAP, + LOCK_INSERT_INTENTION */ + const hash_cell_t& cell, /*!< in: lock hash table cell */ + const page_id_t id, /*!< in: page identifier */ + ulint heap_no,/*!< in: heap number of the record */ + const trx_t* trx) /*!< in: our transaction */ { bool is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM); for (lock_t* lock = lock_sys_t::get_first(cell, id, heap_no); lock; lock = lock_rec_get_next(heap_no, lock)) { - /* There is no need to lock lock_sys.wait_mutex to check - trx->lock.wait_trx here because the current function is - executed under the cell latch, and trx->lock.wait_trx - transaction can change wait_trx field only under the cell - latch, wait_trx trx_t object can not be deinitialized before - releasing all its locks, and during releasing the locks the - cell latch will also be requested. So while the cell latch is - held, lock->trx->lock.wait_trx can't be changed. There also - can't be lock loops for one record, because all waiting locks - of the record will always wait for the same lock of the record - in a cell array, and check for conflicting lock will always - start with the first lock for the heap_no, and go ahead with - the same order(the order of the locks in the cell array) */ - if (lock->is_waiting() && lock->trx->lock.wait_trx == trx) { - if (was_ignored) *was_ignored= true; - continue; - } if (lock_rec_has_to_wait(true, trx, mode, lock, is_supremum)) { return(lock); } @@ -1166,10 +1147,6 @@ without checking for deadlocks or conflicts. @param[in] index the index tree @param[in,out] trx transaction @param[in] holds_trx_mutex whether the caller holds trx->mutex -@param[in] insert_before_waiting if true, inserts new B-tree record lock -just after the last non-waiting lock of the current transaction which is -located before the first waiting for the current transaction lock, otherwise -the lock is inserted at the end of the queue @return created lock */ lock_t* lock_rec_create_low( @@ -1180,8 +1157,7 @@ lock_rec_create_low( ulint heap_no, dict_index_t* index, trx_t* trx, - bool holds_trx_mutex, - bool insert_before_waiting) + bool holds_trx_mutex) { lock_t* lock; ulint n_bytes; @@ -1256,36 +1232,7 @@ lock_rec_create_low( ut_ad(index->table->get_ref_count() || !index->table->can_be_evicted); const auto lock_hash = &lock_sys.hash_get(type_mode); - hash_cell_t& cell = *lock_hash->cell_get(page_id.fold()); - - if (insert_before_waiting - && !(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE))) { - /* Try to insert the lock just after the last non-waiting - lock of the current transaction which immediately - precedes the first waiting lock request. */ - - lock_t* last_non_waiting = nullptr; - - for (lock_t* l = lock_sys_t::get_first(cell, page_id, heap_no); - l; l = lock_rec_get_next(heap_no, l)) { - if (l->is_waiting() && l->trx->lock.wait_trx == trx) { - break; - } - if (l->trx == trx) { - last_non_waiting = l; - } - } - - if (!last_non_waiting) { - goto append_last; - } - - cell.insert_after(*last_non_waiting, *lock, &lock_t::hash); - } - else { -append_last: - cell.append(*lock, &lock_t::hash); - } + HASH_INSERT(lock_t, hash, lock_hash, page_id.fold(), lock); if (type_mode & LOCK_WAIT) { if (trx->lock.wait_trx) { @@ -1410,22 +1357,24 @@ on the record, and the request to be added is not a waiting request, we can reuse a suitable record lock object already existing on the same page, just setting the appropriate bit in its bitmap. This is a low-level function which does NOT check for deadlocks or lock compatibility! -@param[in] type_mode lock mode, wait, gap etc. flags -@param[in,out] cell first hash table cell -@param[in] id page identifier -@param[in] page buffer block containing the record -@param[in] heap_no heap number of the record -@param[in] index index of record -@param[in,out] trx transaction -@param[in] caller_owns_trx_mutex TRUE if caller owns the transaction mutex -@param[in] insert_before_waiting true=insert B-tree record lock right -before a waiting lock request; false=insert the lock at the end of the queue */ +@return lock where the bit was set */ TRANSACTIONAL_TARGET -static void lock_rec_add_to_queue(unsigned type_mode, hash_cell_t &cell, - const page_id_t id, const page_t *page, - ulint heap_no, dict_index_t *index, - trx_t *trx, bool caller_owns_trx_mutex, - bool insert_before_waiting= false) +static +void +lock_rec_add_to_queue( +/*==================*/ + unsigned type_mode,/*!< in: lock mode, wait, gap + etc. flags */ + hash_cell_t& cell, /*!< in,out: first hash table cell */ + const page_id_t id, /*!< in: page identifier */ + const page_t* page, /*!< in: buffer block containing + the record */ + ulint heap_no,/*!< in: heap number of the record */ + dict_index_t* index, /*!< in: index of record */ + trx_t* trx, /*!< in/out: transaction */ + bool caller_owns_trx_mutex) + /*!< in: TRUE if caller owns the + transaction mutex */ { ut_d(lock_sys.hash_get(type_mode).assert_locked(id)); ut_ad(xtest() || caller_owns_trx_mutex == trx->mutex_is_owner()); @@ -1520,7 +1469,7 @@ create: lock_rec_create_low(nullptr, type_mode, id, page, heap_no, index, trx, - caller_owns_trx_mutex, insert_before_waiting); + caller_owns_trx_mutex); } /*********************************************************************//** @@ -1587,10 +1536,8 @@ lock_rec_lock( /* Do nothing if the trx already has a strong enough lock on rec */ if (!lock_rec_has_expl(mode, g.cell(), id, heap_no, trx)) { - bool was_ignored = false; if (lock_t *c_lock= lock_rec_other_has_conflicting(mode, g.cell(), id, - heap_no, trx, - &was_ignored)) + heap_no, trx)) /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not @@ -1603,7 +1550,7 @@ lock_rec_lock( { /* Set the requested lock on the record. */ lock_rec_add_to_queue(mode, g.cell(), id, block->page.frame, heap_no, - index, trx, true, was_ignored); + index, trx, true); err= DB_SUCCESS_LOCKED_REC; } } @@ -4707,7 +4654,7 @@ func_exit: wsrep_report_bf_lock_wait(impl_trx->mysql_thd, impl_trx->id); wsrep_report_bf_lock_wait(other_lock->trx->mysql_thd, other_lock->trx->id); - if (!lock_rec_has_expl(LOCK_S | LOCK_REC_NOT_GAP, + if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, cell, id, heap_no, impl_trx)) { ib::info() << "WSREP impl BF lock conflict"; @@ -4716,22 +4663,8 @@ func_exit: #endif /* WITH_WSREP */ { ut_ad(other_lock->is_waiting()); - /* After MDEV-27025 fix the following case is - possible: - 1. trx 1 acquires S-lock; - 2. trx 2 creates X-lock waiting for trx 1; - 3. trx 1 creates implicit lock, as - lock_rec_other_has_conflicting() returns no - conflicting trx 2 X-lock, the explicit lock - will not be created; - 4. trx 3 creates waiting X-lock, - it will wait for S-lock of trx 1. - That is why we relaxing the condition here and - check only for S-lock. - */ - ut_ad(lock_rec_has_expl(LOCK_S - | LOCK_REC_NOT_GAP, - cell, id, heap_no, + ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, + cell, id, heap_no, impl_trx)); } } @@ -5127,7 +5060,7 @@ lock_rec_convert_impl_to_expl_for_trx( !lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, heap_no, trx)) lock_rec_add_to_queue(LOCK_X | LOCK_REC_NOT_GAP, g.cell(), id, - page_align(rec), heap_no, index, trx, true, true); + page_align(rec), heap_no, index, trx, true); } trx->mutex_unlock(); |