diff --git a/row/row0mysql.c b/row/row0mysql.c index ce50aefbd24..b00b2718cdf 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -1452,8 +1452,6 @@ row_unlock_for_mysql( btr_pcur_t* pcur = prebuilt->pcur; btr_pcur_t* clust_pcur = prebuilt->clust_pcur; trx_t* trx = prebuilt->trx; - rec_t* rec; - mtr_t mtr; ut_ad(prebuilt && trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1475,6 +1473,11 @@ row_unlock_for_mysql( if (prebuilt->new_rec_locks >= 1) { + rec_t* rec; + dict_index_t* index; + dulint rec_trx_id; + mtr_t mtr; + mtr_start(&mtr); /* Restore the cursor position and find the record */ @@ -1484,27 +1487,63 @@ row_unlock_for_mysql( } rec = btr_pcur_get_rec(pcur); + index = btr_pcur_get_btr_cur(pcur)->index; - lock_rec_unlock(trx, btr_pcur_get_block(pcur), - rec, prebuilt->select_lock_type); + if (prebuilt->new_rec_locks >= 2) { + /* Restore the cursor position and find the record + in the clustered index. */ - mtr_commit(&mtr); - } + if (!has_latches_on_recs) { + btr_pcur_restore_position(BTR_SEARCH_LEAF, + clust_pcur, &mtr); + } - if (prebuilt->new_rec_locks >= 2) { - mtr_start(&mtr); - - /* Restore the cursor position and find the record */ - - if (!has_latches_on_recs) { - btr_pcur_restore_position(BTR_SEARCH_LEAF, clust_pcur, - &mtr); + rec = btr_pcur_get_rec(clust_pcur); + index = btr_pcur_get_btr_cur(clust_pcur)->index; } - rec = btr_pcur_get_rec(clust_pcur); + /* If the record has been modified by this + transaction, do not unlock it. */ + ut_a(index->type & DICT_CLUSTERED); - lock_rec_unlock(trx, btr_pcur_get_block(clust_pcur), - rec, prebuilt->select_lock_type); + if (index->trx_id_offset) { + rec_trx_id = trx_read_trx_id(rec + + index->trx_id_offset); + } else { + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + ulint* offsets = offsets_; + + rec_offs_init(offsets_); + offsets = rec_get_offsets(rec, index, offsets, + ULINT_UNDEFINED, &heap); + + rec_trx_id = row_get_rec_trx_id(rec, index, offsets); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + } + + if (ut_dulint_cmp(rec_trx_id, trx->id) != 0) { + /* We did not update the record: unlock it */ + + rec = btr_pcur_get_rec(pcur); + index = btr_pcur_get_btr_cur(pcur)->index; + + lock_rec_unlock(trx, btr_pcur_get_block(pcur), + rec, prebuilt->select_lock_type); + + if (prebuilt->new_rec_locks >= 2) { + rec = btr_pcur_get_rec(clust_pcur); + index = btr_pcur_get_btr_cur(clust_pcur)->index; + + lock_rec_unlock(trx, + btr_pcur_get_block(clust_pcur), + rec, + prebuilt->select_lock_type); + } + } mtr_commit(&mtr); }