summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0sel.c
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2010-06-02 14:37:33 +0300
committerMarko Mäkelä <marko.makela@oracle.com>2010-06-02 14:37:33 +0300
commita2b95321882072cfd0725d4b5f261586d3483400 (patch)
tree5f0948b1fa327bad05d1d187e939614b83d91bca /storage/innobase/row/row0sel.c
parent8f5d78c28b901ad118b2540d3394787e141365ba (diff)
downloadmariadb-git-a2b95321882072cfd0725d4b5f261586d3483400.tar.gz
Merge from mysql-5.1-innodb:
------------------------------------------------------------ revno: 3495 committer: Marko Mäkelä <marko.makela@oracle.com> branch nick: 5.1-innodb timestamp: Wed 2010-06-02 13:37:14 +0300 message: Bug#53674: InnoDB: Error: unlock row could not find a 4 mode lock on the record In semi-consistent read, only unlock freshly locked non-matching records. lock_rec_lock_fast(): Return LOCK_REC_SUCCESS, LOCK_REC_SUCCESS_CREATED, or LOCK_REC_FAIL instead of TRUE/FALSE. enum db_err: Add DB_SUCCESS_LOCKED_REC for indicating a successful operation where a record lock was created. lock_sec_rec_read_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_enqueue_waiting(), lock_rec_lock_slow(), lock_rec_lock(), row_ins_set_shared_rec_lock(), row_ins_set_exclusive_rec_lock(), sel_set_rec_lock(), row_sel_get_clust_rec_for_mysql(): Return DB_SUCCESS_LOCKED_REC if a new record lock was created. Adjust callers. row_unlock_for_mysql(): Correct the function documentation. row_prebuilt_t::new_rec_locks: Correct the documentation.
Diffstat (limited to 'storage/innobase/row/row0sel.c')
-rw-r--r--storage/innobase/row/row0sel.c132
1 files changed, 85 insertions, 47 deletions
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index 4d19ed93a49..a5bf361661b 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -863,8 +863,14 @@ row_sel_get_clust_rec(
clust_rec, index, offsets,
node->row_lock_mode, lock_type, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
+ /* Declare the variable uninitialized in Valgrind.
+ It should be set to DB_SUCCESS at func_exit. */
+ UNIV_MEM_INVALID(&err, sizeof err);
+ break;
+ default:
goto err_exit;
}
} else {
@@ -934,9 +940,9 @@ err_exit:
/*********************************************************************//**
Sets a lock on a record.
-@return DB_SUCCESS or error code */
+@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
UNIV_INLINE
-ulint
+enum db_err
sel_set_rec_lock(
/*=============*/
const buf_block_t* block, /*!< in: buffer block of rec */
@@ -948,8 +954,8 @@ sel_set_rec_lock(
LOC_REC_NOT_GAP */
que_thr_t* thr) /*!< in: query thread */
{
- trx_t* trx;
- ulint err;
+ trx_t* trx;
+ enum db_err err;
trx = thr_get_trx(thr);
@@ -1482,11 +1488,15 @@ rec_loop:
node->row_lock_mode,
lock_type, thr);
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
the lock for */
-
goto lock_wait_or_error;
}
}
@@ -1538,8 +1548,12 @@ skip_lock:
rec, index, offsets,
node->row_lock_mode, lock_type, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -2801,9 +2815,9 @@ row_sel_build_prev_vers_for_mysql(
Retrieves the clustered index record corresponding to a record in a
non-clustered index. Does the necessary locking. Used in the MySQL
interface.
-@return DB_SUCCESS or error code */
+@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */
static
-ulint
+enum db_err
row_sel_get_clust_rec_for_mysql(
/*============================*/
row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */
@@ -2830,7 +2844,7 @@ row_sel_get_clust_rec_for_mysql(
dict_index_t* clust_index;
const rec_t* clust_rec;
rec_t* old_vers;
- ulint err;
+ enum db_err err;
trx_t* trx;
*out_rec = NULL;
@@ -2889,6 +2903,7 @@ row_sel_get_clust_rec_for_mysql(
clust_rec = NULL;
+ err = DB_SUCCESS;
goto func_exit;
}
@@ -2904,8 +2919,11 @@ row_sel_get_clust_rec_for_mysql(
0, btr_pcur_get_block(prebuilt->clust_pcur),
clust_rec, clust_index, *offsets,
prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
+ break;
+ default:
goto err_exit;
}
} else {
@@ -2965,6 +2983,8 @@ row_sel_get_clust_rec_for_mysql(
rec, sec_index, clust_rec, clust_index));
#endif
}
+
+ err = DB_SUCCESS;
}
func_exit:
@@ -2977,7 +2997,6 @@ func_exit:
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
- err = DB_SUCCESS;
err_exit:
return(err);
}
@@ -3702,8 +3721,12 @@ shortcut_fails_too_big_rec:
prebuilt->select_lock_type,
LOCK_GAP, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3801,8 +3824,12 @@ rec_loop:
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3932,8 +3959,11 @@ wrong_offs:
prebuilt->select_lock_type, LOCK_GAP,
thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -3968,8 +3998,11 @@ wrong_offs:
prebuilt->select_lock_type, LOCK_GAP,
thr);
- if (err != DB_SUCCESS) {
-
+ switch (err) {
+ case DB_SUCCESS_LOCKED_REC:
+ case DB_SUCCESS:
+ break;
+ default:
goto lock_wait_or_error;
}
}
@@ -4039,15 +4072,21 @@ no_gap_lock:
switch (err) {
const rec_t* old_vers;
- case DB_SUCCESS:
+ case DB_SUCCESS_LOCKED_REC:
if (srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ || trx->isolation_level
+ <= TRX_ISO_READ_COMMITTED) {
/* Note that a record of
prebuilt->index was locked. */
prebuilt->new_rec_locks = 1;
}
+ err = DB_SUCCESS;
+ case DB_SUCCESS:
break;
case DB_LOCK_WAIT:
+ /* Never unlock rows that were part of a conflict. */
+ prebuilt->new_rec_locks = 0;
+
if (UNIV_LIKELY(prebuilt->row_read_type
!= ROW_READ_TRY_SEMI_CONSISTENT)
|| unique_search
@@ -4077,7 +4116,6 @@ no_gap_lock:
if (UNIV_LIKELY(trx->wait_lock != NULL)) {
lock_cancel_waiting_and_release(
trx->wait_lock);
- prebuilt->new_rec_locks = 0;
} else {
mutex_exit(&kernel_mutex);
@@ -4089,9 +4127,6 @@ no_gap_lock:
ULINT_UNDEFINED,
&heap);
err = DB_SUCCESS;
- /* Note that a record of
- prebuilt->index was locked. */
- prebuilt->new_rec_locks = 1;
break;
}
mutex_exit(&kernel_mutex);
@@ -4228,27 +4263,30 @@ requires_clust_rec:
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
thr, &clust_rec,
&offsets, &heap, &mtr);
- if (err != DB_SUCCESS) {
+ switch (err) {
+ case DB_SUCCESS:
+ if (clust_rec == NULL) {
+ /* The record did not exist in the read view */
+ ut_ad(prebuilt->select_lock_type == LOCK_NONE);
+ goto next_rec;
+ }
+ break;
+ case DB_SUCCESS_LOCKED_REC:
+ ut_a(clust_rec != NULL);
+ if (srv_locks_unsafe_for_binlog
+ || trx->isolation_level
+ <= TRX_ISO_READ_COMMITTED) {
+ /* Note that the clustered index record
+ was locked. */
+ prebuilt->new_rec_locks = 2;
+ }
+ err = DB_SUCCESS;
+ break;
+ default:
goto lock_wait_or_error;
}
- if (clust_rec == NULL) {
- /* The record did not exist in the read view */
- ut_ad(prebuilt->select_lock_type == LOCK_NONE);
-
- goto next_rec;
- }
-
- if ((srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE) {
- /* Note that both the secondary index record
- and the clustered index record were locked. */
- ut_ad(prebuilt->new_rec_locks == 1);
- prebuilt->new_rec_locks = 2;
- }
-
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
/* The record is delete marked: we can skip it */