summaryrefslogtreecommitdiff
path: root/storage/innobase/lock/lock0lock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/lock/lock0lock.cc')
-rw-r--r--storage/innobase/lock/lock0lock.cc68
1 files changed, 35 insertions, 33 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 2b30b9b1a03..3c7c3d348af 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1064,13 +1064,16 @@ lock_sec_rec_some_has_impl(
const trx_id_t max_trx_id= page_get_max_trx_id(page_align(rec));
- if ((caller_trx->id > max_trx_id &&
- !trx_sys.find_same_or_older(caller_trx, max_trx_id)) ||
+ /* Note: It is possible to have caller_trx->id == 0 in a locking read
+ if caller_trx has not modified any persistent tables. */
+ if (!trx_sys.find_same_or_older(caller_trx, max_trx_id) ||
!lock_check_trx_id_sanity(max_trx_id, rec, index, offsets))
return nullptr;
- /* In this case it is possible that some transaction has an implicit
- x-lock. We have to look in the clustered index. */
+ /* We checked above that some active (or XA PREPARE) transaction exists
+ that is older than PAGE_MAX_TRX_ID. That is, some transaction may be
+ holding an implicit lock on the record. We have to look up the
+ clustered index record to find if it is (or was) the case. */
return row_vers_impl_x_locked(caller_trx, rec, index, offsets);
}
@@ -5157,20 +5160,24 @@ has an implicit lock on the record. The transaction instance must have a
reference count > 0 so that it can't be committed and freed before this
function has completed. */
static
-void
+bool
lock_rec_convert_impl_to_expl_for_trx(
/*==================================*/
+ trx_t* trx, /*!< in/out: active transaction */
const page_id_t id, /*!< in: page identifier */
const rec_t* rec, /*!< in: user record on page */
- dict_index_t* index, /*!< in: index of record */
- trx_t* trx, /*!< in/out: active transaction */
- ulint heap_no)/*!< in: rec heap number to lock */
+ dict_index_t* index) /*!< in: index of record */
{
+ if (!trx)
+ return false;
+
ut_ad(trx->is_referenced());
ut_ad(page_rec_is_leaf(rec));
ut_ad(!rec_is_metadata(rec, *index));
DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx");
+ ulint heap_no= page_rec_get_heap_no(rec);
+
{
LockGuard g{lock_sys.rec_hash, id};
trx->mutex_lock();
@@ -5187,6 +5194,7 @@ lock_rec_convert_impl_to_expl_for_trx(
trx->release_reference();
DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx");
+ return false;
}
@@ -5260,7 +5268,6 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx,
}
#endif /* UNIV_DEBUG */
-
/** If an implicit x-lock exists on a record, convert it to an explicit one.
Often, this is called by a transaction that is about to enter a lock wait
@@ -5272,12 +5279,14 @@ This may also be called by the same transaction that is already holding
an implicit exclusive lock on the record. In this case, no explicit lock
should be created.
+@tparam is_primary whether the index is the primary key
@param[in,out] caller_trx current transaction
@param[in] id index tree leaf page identifier
@param[in] rec record on the leaf page
@param[in] index the index of the record
@param[in] offsets rec_get_offsets(rec,index)
@return whether caller_trx already holds an exclusive lock on rec */
+template<bool is_primary>
static
bool
lock_rec_convert_impl_to_expl(
@@ -5295,8 +5304,9 @@ lock_rec_convert_impl_to_expl(
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
ut_ad(page_rec_is_leaf(rec));
ut_ad(!rec_is_metadata(rec, *index));
+ ut_ad(index->is_primary() == is_primary);
- if (dict_index_is_clust(index)) {
+ if (is_primary) {
trx_id_t trx_id;
trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
@@ -5322,20 +5332,7 @@ lock_rec_convert_impl_to_expl(
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec, id));
}
- if (trx) {
- ulint heap_no = page_rec_get_heap_no(rec);
-
- ut_ad(trx->is_referenced());
-
- /* If the transaction is still active and has no
- explicit x-lock set on the record, set one for it.
- trx cannot be committed until the ref count is zero. */
-
- lock_rec_convert_impl_to_expl_for_trx(
- id, rec, index, trx, heap_no);
- }
-
- return false;
+ return lock_rec_convert_impl_to_expl_for_trx(trx, id, rec, index);
}
/*********************************************************************//**
@@ -5374,8 +5371,9 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one
for it */
- if (lock_rec_convert_impl_to_expl(thr_get_trx(thr), block->page.id(),
- rec, index, offsets)) {
+ if (lock_rec_convert_impl_to_expl<true>(thr_get_trx(thr),
+ block->page.id(),
+ rec, index, offsets)) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
}
@@ -5532,15 +5530,17 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
- const page_id_t id{block->page.id()};
-
ut_ad(!rec_is_metadata(rec, *index));
trx_t *trx = thr_get_trx(thr);
+
+ if (lock_table_has(trx, index->table, mode)) {
+ return DB_SUCCESS;
+ }
+
if (!page_rec_is_supremum(rec)
- && !lock_table_has(trx, index->table, LOCK_X)
- && lock_rec_convert_impl_to_expl(thr_get_trx(thr), id, rec,
- index, offsets)
+ && lock_rec_convert_impl_to_expl<false>(
+ trx, block->page.id(), rec, index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
@@ -5565,7 +5565,8 @@ lock_sec_rec_read_check_and_lock(
if (trx->wsrep == 3) trx->wsrep = 1;
#endif /* WITH_WSREP */
- ut_ad(lock_rec_queue_validate(false, id, rec, index, offsets));
+ ut_ad(lock_rec_queue_validate(false, block->page.id(),
+ rec, index, offsets));
return(err);
}
@@ -5622,7 +5623,8 @@ lock_clust_rec_read_check_and_lock(
trx_t *trx = thr_get_trx(thr);
if (!lock_table_has(trx, index->table, LOCK_X)
&& heap_no != PAGE_HEAP_NO_SUPREMUM
- && lock_rec_convert_impl_to_expl(trx, id, rec, index, offsets)
+ && lock_rec_convert_impl_to_expl<true>(trx, id,
+ rec, index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;