summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0sel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0sel.cc')
-rw-r--r--storage/innobase/row/row0sel.cc196
1 files changed, 65 insertions, 131 deletions
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 6c7a54ece7d..f0f1206ea82 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -963,12 +963,10 @@ row_sel_get_clust_rec(
trx = thr_get_trx(thr);
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED or lower isolation level
+ /* At READ UNCOMMITTED or READ COMMITTED isolation level
we lock only the record, i.e., next-key locking is
not used. */
- if (srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
lock_type = LOCK_REC_NOT_GAP;
} else {
lock_type = LOCK_ORDINARY;
@@ -1738,16 +1736,11 @@ rec_loop:
true,
ULINT_UNDEFINED, &heap);
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED or lower isolation
- level, we lock only the record, i.e., next-key
- locking is not used. */
- if (srv_locks_unsafe_for_binlog
- || trx->isolation_level
- <= TRX_ISO_READ_COMMITTED) {
-
+ /* At READ UNCOMMITTED or READ COMMITTED
+ isolation level, we lock only the record,
+ i.e., next-key locking is not used. */
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
if (page_rec_is_supremum(next_rec)) {
-
goto skip_lock;
}
@@ -1805,12 +1798,10 @@ skip_lock:
trx = thr_get_trx(thr);
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using READ COMMITTED or lower isolation level,
+ /* At READ UNCOMMITTED or READ COMMITTED isolation level,
we lock only the record, i.e., next-key locking is
not used. */
- if (srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|| dict_index_is_spatial(index)) {
if (page_rec_is_supremum(rec)) {
@@ -4197,29 +4188,18 @@ row_search_mvcc(
const rec_t* result_rec = NULL;
const rec_t* clust_rec;
Row_sel_get_clust_rec_for_mysql row_sel_get_clust_rec_for_mysql;
- dberr_t err = DB_SUCCESS;
ibool unique_search = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
ibool moves_up = FALSE;
- ibool set_also_gap_locks = TRUE;
- /* if the query is a plain locking SELECT, and the isolation level
- is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */
- ibool did_semi_consistent_read = FALSE;
/* if the returned record was locked and we did a semi-consistent
read (fetch the newest committed version), then this is set to
TRUE */
ulint next_offs;
ibool same_user_rec;
- mtr_t mtr;
- mem_heap_t* heap = NULL;
- ulint offsets_[REC_OFFS_NORMAL_SIZE];
- ulint* offsets = offsets_;
ibool table_lock_waited = FALSE;
byte* next_buf = 0;
bool spatial_search = false;
- rec_offs_init(offsets_);
-
ut_ad(index && pcur && search_tuple);
ut_a(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
ut_a(prebuilt->magic_n2 == ROW_PREBUILT_ALLOCATED);
@@ -4253,8 +4233,8 @@ row_search_mvcc(
&& (prebuilt->read_just_key
|| prebuilt->m_read_virtual_key);
- /* Reset the new record lock info if srv_locks_unsafe_for_binlog
- is set or session is using a READ COMMITED isolation level. Then
+ /* Reset the new record lock info if READ UNCOMMITTED or
+ READ COMMITED isolation level is used. Then
we are able to remove the record locks set here on an individual
row. */
prebuilt->new_rec_locks = 0;
@@ -4297,20 +4277,18 @@ row_search_mvcc(
row_sel_dequeue_cached_row_for_mysql(buf, prebuilt);
prebuilt->n_rows_fetched++;
-
- err = DB_SUCCESS;
- goto func_exit;
+ trx->op_info = "";
+ DBUG_RETURN(DB_SUCCESS);
}
if (prebuilt->fetch_cache_first > 0
&& prebuilt->fetch_cache_first < MYSQL_FETCH_CACHE_SIZE) {
-
+early_not_found:
/* The previous returned row was popped from the fetch
cache, but the cache was not full at the time of the
popping: no more rows can exist in the result set */
-
- err = DB_RECORD_NOT_FOUND;
- goto func_exit;
+ trx->op_info = "";
+ DBUG_RETURN(DB_RECORD_NOT_FOUND);
}
prebuilt->n_rows_fetched++;
@@ -4354,22 +4332,28 @@ row_search_mvcc(
if (UNIV_UNLIKELY(direction != 0
&& !prebuilt->used_in_HANDLER)) {
-
- err = DB_RECORD_NOT_FOUND;
- goto func_exit;
+ goto early_not_found;
}
}
/* We don't support sequencial scan for Rtree index, because it
is no meaning to do so. */
- if (dict_index_is_spatial(index)
- && !RTREE_SEARCH_MODE(mode)) {
- err = DB_END_OF_INDEX;
- goto func_exit;
+ if (dict_index_is_spatial(index) && !RTREE_SEARCH_MODE(mode)) {
+ trx->op_info = "";
+ DBUG_RETURN(DB_END_OF_INDEX);
}
+ /* if the query is a plain locking SELECT, and the isolation level
+ is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */
+ bool did_semi_consistent_read = false;
+ mtr_t mtr;
mtr.start();
+ mem_heap_t* heap = NULL;
+ ulint offsets_[REC_OFFS_NORMAL_SIZE];
+ ulint* offsets = offsets_;
+ rec_offs_init(offsets_);
+
#ifdef BTR_CUR_HASH_ADAPT
/*-------------------------------------------------------------*/
/* PHASE 2: Try fast adaptive hash index search if possible */
@@ -4399,6 +4383,7 @@ row_search_mvcc(
let us try a search shortcut through the hash
index. */
+ dberr_t err = DB_SUCCESS;
switch (row_sel_try_search_shortcut_for_mysql(
&rec, prebuilt, &offsets, &heap,
&mtr)) {
@@ -4418,9 +4403,10 @@ row_search_mvcc(
case ICP_OUT_OF_RANGE:
case ICP_ABORTED_BY_USER:
case ICP_ERROR:
- goto shortcut_mismatch;
+ err = DB_RECORD_NOT_FOUND;
+ goto shortcut_done;
case ICP_MATCH:
- goto shortcut_match;
+ goto shortcut_done;
}
}
@@ -4443,21 +4429,19 @@ row_search_mvcc(
break;
}
- shortcut_match:
- mtr.commit();
-
- /* NOTE that we do NOT store the cursor
- position */
- err = DB_SUCCESS;
- goto func_exit;
+ goto shortcut_done;
case SEL_EXHAUSTED:
- shortcut_mismatch:
+ err = DB_RECORD_NOT_FOUND;
+ shortcut_done:
mtr.commit();
+
/* NOTE that we do NOT store the cursor
position */
- err = DB_RECORD_NOT_FOUND;
- goto func_exit;
+ trx->op_info = "";
+ ut_ad(!sync_check_iterate(sync_check()));
+ ut_ad(!did_semi_consistent_read);
+ DBUG_RETURN(err);
case SEL_RETRY:
break;
@@ -4495,22 +4479,16 @@ row_search_mvcc(
|| prebuilt->table->no_rollback()
|| srv_read_only_mode);
- if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
- && prebuilt->select_lock_type != LOCK_NONE
- && trx->mysql_thd != NULL
- && thd_is_select(trx->mysql_thd)) {
- /* It is a plain locking SELECT and the isolation
- level is low: do not lock gaps */
-
- set_also_gap_locks = FALSE;
- }
+ /* Do not lock gaps for plain SELECT
+ at READ UNCOMMITTED or READ COMMITTED isolation level */
+ const bool set_also_gap_locks =
+ prebuilt->select_lock_type != LOCK_NONE
+ && (trx->isolation_level > TRX_ISO_READ_COMMITTED
+ || !thd_is_select(trx->mysql_thd))
#ifdef WITH_WSREP
- else if (wsrep_thd_skip_locking(trx->mysql_thd)) {
- ut_ad(!strcmp(wsrep_get_sr_table_name(),
- prebuilt->table->name.m_name));
- set_also_gap_locks = FALSE;
- }
+ && !wsrep_thd_skip_locking(trx->mysql_thd)
#endif /* WITH_WSREP */
+ ;
/* Note that if the search mode was GE or G, then the cursor
naturally moves upward (in fetch next) in alphabetical order,
@@ -4531,6 +4509,8 @@ row_search_mvcc(
clust_index = dict_table_get_first_index(prebuilt->table);
+ dberr_t err = DB_SUCCESS;
+
/* Do some start-of-statement preparations */
if (prebuilt->table->no_rollback()) {
@@ -4599,18 +4579,9 @@ wait_table_again:
pcur->btr_cur.thr = thr;
if (dict_index_is_spatial(index)) {
- bool need_pred_lock;
-
- need_pred_lock = (set_also_gap_locks
- && !(srv_locks_unsafe_for_binlog
- || trx->isolation_level
- <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type
- != LOCK_NONE);
-
if (!prebuilt->rtr_info) {
prebuilt->rtr_info = rtr_create_rtr_info(
- need_pred_lock, true,
+ set_also_gap_locks, true,
btr_pcur_get_btr_cur(pcur), index);
prebuilt->rtr_info->search_tuple = search_tuple;
prebuilt->rtr_info->search_mode = mode;
@@ -4619,7 +4590,7 @@ wait_table_again:
} else {
rtr_info_reinit_in_cursor(
btr_pcur_get_btr_cur(pcur),
- index, need_pred_lock);
+ index, set_also_gap_locks);
prebuilt->rtr_info->search_tuple = search_tuple;
prebuilt->rtr_info->search_mode = mode;
}
@@ -4640,11 +4611,8 @@ wait_table_again:
ut_ad(page_rec_is_leaf(rec));
if (!moves_up
- && !page_rec_is_supremum(rec)
&& set_also_gap_locks
- && !(srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE
+ && !page_rec_is_supremum(rec)
&& !dict_index_is_spatial(index)) {
/* Try to place a gap lock on the next index record
@@ -4724,16 +4692,14 @@ rec_loop:
if (page_rec_is_supremum(rec)) {
if (set_also_gap_locks
- && !(srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE
+ && trx->isolation_level > TRX_ISO_READ_COMMITTED
&& !dict_index_is_spatial(index)) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using a READ COMMITTED or lower isolation
- level we do not lock gaps. Supremum record is really
+ /* If the transaction isolation level is
+ READ UNCOMMITTED or READ COMMITTED,
+ we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
offsets = rec_get_offsets(rec, index, offsets, true,
@@ -4872,17 +4838,7 @@ wrong_offs:
if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
if (set_also_gap_locks
- && !(srv_locks_unsafe_for_binlog
- || trx->isolation_level
- <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE
&& !dict_index_is_spatial(index)) {
-
- /* Try to place a gap lock on the index
- record only if innodb_locks_unsafe_for_binlog
- option is not set or this session is not
- using a READ COMMITTED or lower isolation level. */
-
err = sel_set_rec_lock(
pcur,
rec, index, offsets,
@@ -4917,17 +4873,7 @@ wrong_offs:
if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
if (set_also_gap_locks
- && !(srv_locks_unsafe_for_binlog
- || trx->isolation_level
- <= TRX_ISO_READ_COMMITTED)
- && prebuilt->select_lock_type != LOCK_NONE
&& !dict_index_is_spatial(index)) {
-
- /* Try to place a gap lock on the index
- record only if innodb_locks_unsafe_for_binlog
- option is not set or this session is not
- using a READ COMMITTED or lower isolation level. */
-
err = sel_set_rec_lock(
pcur,
rec, index, offsets,
@@ -4967,15 +4913,9 @@ wrong_offs:
is a non-delete marked record, then it is enough to lock its
existence with LOCK_REC_NOT_GAP. */
- /* If innodb_locks_unsafe_for_binlog option is used
- or this session is using a READ COMMITED isolation
- level we lock only the record, i.e., next-key locking is
- not used. */
-
ulint lock_type;
- if (srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
/* At READ COMMITTED or READ UNCOMMITTED
isolation levels, do not lock committed
delete-marked records. */
@@ -5056,9 +4996,7 @@ no_gap_lock:
switch (err) {
const rec_t* old_vers;
case DB_SUCCESS_LOCKED_REC:
- if (srv_locks_unsafe_for_binlog
- || trx->isolation_level
- <= TRX_ISO_READ_COMMITTED) {
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
/* Note that a record of
prebuilt->index was locked. */
prebuilt->new_rec_locks = 1;
@@ -5121,7 +5059,7 @@ no_gap_lock:
goto next_rec;
}
- did_semi_consistent_read = TRUE;
+ did_semi_consistent_read = true;
rec = old_vers;
break;
case DB_RECORD_NOT_FOUND:
@@ -5308,9 +5246,7 @@ requires_clust_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) {
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) {
/* Note that the clustered index record
was locked. */
prebuilt->new_rec_locks = 2;
@@ -5326,8 +5262,7 @@ requires_clust_rec:
/* The record is delete marked: we can skip it */
- if ((srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& prebuilt->select_lock_type != LOCK_NONE) {
/* No need to keep a lock on a delete-marked
@@ -5551,7 +5486,7 @@ next_rec:
== ROW_READ_DID_SEMI_CONSISTENT)) {
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
}
- did_semi_consistent_read = FALSE;
+ did_semi_consistent_read = false;
prebuilt->new_rec_locks = 0;
vrow = NULL;
@@ -5650,7 +5585,7 @@ page_read_error:
== ROW_READ_DID_SEMI_CONSISTENT)) {
prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;
}
- did_semi_consistent_read = FALSE;
+ did_semi_consistent_read = false;
lock_table_wait:
mtr.commit();
@@ -5686,8 +5621,7 @@ lock_table_wait:
moves_up, &mtr);
}
- if ((srv_locks_unsafe_for_binlog
- || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
+ if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
&& !same_user_rec) {
/* Since we were not able to restore the cursor