summaryrefslogtreecommitdiff
path: root/storage/innobase/lock
diff options
context:
space:
mode:
authorVlad Lesin <vlad_lesin@mail.ru>2022-03-07 18:42:47 +0300
committerVlad Lesin <vlad_lesin@mail.ru>2022-03-07 18:42:47 +0300
commit202316a38fef8b9042e03ddf828e394f32cc51a2 (patch)
treead391c8b6e4c29a84325aca7c5452fc13673453d /storage/innobase/lock
parentb6a2472489accf0ae9ac3655ffe9b2997ab267ba (diff)
parent0b92c7b0e046df98136c7009c6ce7e6ff1974849 (diff)
downloadmariadb-git-202316a38fef8b9042e03ddf828e394f32cc51a2.tar.gz
Merge 10.5 into 10.6
Diffstat (limited to 'storage/innobase/lock')
-rw-r--r--storage/innobase/lock/lock0lock.cc145
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();