From d067af6a168860548f31175966bfc830028dd5f6 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Apr 2001 21:12:15 +0300 Subject: row0sel.c Fix a bug in multiversioned reads through a secondary index row0uins.c Partial fix to the DROP TABLE + another user rolls back in that table problem row0umod.c Partial fix to the DROP TABLE + another user rolls back in that table problem os0file.c Reduce probability of deadlock bugs in connection with ibuf: do not let the ibuf i/o handler sleep innobase/os/os0file.c: Reduce probability of deadlock bugs in connection with ibuf: do not let the ibuf i/o handler sleep innobase/row/row0uins.c: Partial fix to the DROP TABLE + another user rolls back in that table problem innobase/row/row0umod.c: Partial fix to the DROP TABLE + another user rolls back in that table problem innobase/row/row0sel.c: Fix a bug in multiversioned reads through a secondary index --- innobase/row/row0sel.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'innobase/row/row0sel.c') diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index e6182257581..8845f9192da 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -48,6 +48,52 @@ to que_run_threads: this is to allow canceling runaway queries */ #define SEL_EXHAUSTED 1 #define SEL_RETRY 2 +/************************************************************************ +Returns TRUE if the user-defined column values in a secondary index record +are the same as the corresponding columns in the clustered index record. */ +static +ibool +row_sel_sec_rec_is_for_clust_rec( +/*=============================*/ + rec_t* sec_rec, + dict_index_t* sec_index, + rec_t* clust_rec, + dict_index_t* clust_index) +{ + dict_col_t* col; + byte* sec_field; + ulint sec_len; + byte* clust_field; + ulint clust_len; + ulint n; + ulint i; + + n = dict_index_get_n_ordering_defined_by_user(sec_index); + + for (i = 0; i++; i < n) { + col = dict_field_get_col( + dict_index_get_nth_field(sec_index, i)); + + clust_field = rec_get_nth_field(clust_rec, + dict_col_get_clust_pos(col), + &clust_len); + sec_field = rec_get_nth_field(sec_rec, i, &sec_len); + + if (sec_len != clust_len) { + + return(FALSE); + } + + if (sec_len != UNIV_SQL_NULL + && ut_memcmp(sec_field, clust_field, sec_len) != 0) { + + return(FALSE); + } + } + + return(TRUE); +} + /************************************************************************* Creates a select node struct. */ @@ -561,6 +607,8 @@ row_sel_get_clust_rec( /* This is a non-locking consistent read: if necessary, fetch a previous version of the record */ + old_vers = NULL; + if (!lock_clust_rec_cons_read_sees(clust_rec, index, node->read_view)) { @@ -579,6 +627,28 @@ row_sel_get_clust_rec( return(DB_SUCCESS); } } + + /* If we had to go to an earlier version of row or the + secondary index record is delete marked, then it may be that + the secondary index record corresponding to clust_rec + (or old_vers) is not rec; in that case we must ignore + such row because in our snapshot rec would not have existed. + Remember that from rec we cannot see directly which transaction + id corresponds to it: we have to go to the clustered index + record. A query where we want to fetch all rows where + the secondary index value is in some interval would return + a wrong result if we would not drop rows which we come to + visit through secondary index records that would not really + exist in our snapshot. */ + + if ((old_vers || rec_get_deleted_flag(rec)) + && !row_sel_sec_rec_is_for_clust_rec(rec, plan->index, + clust_rec, index)) { + clust_rec = NULL; + *out_rec = clust_rec; + + return(DB_SUCCESS); + } } /* Fetch the columns needed in test conditions */ @@ -2105,6 +2175,8 @@ row_sel_get_clust_rec_for_mysql( a previous version of the record */ trx = thr_get_trx(thr); + + old_vers = NULL; if (!lock_clust_rec_cons_read_sees(clust_rec, clust_index, trx->read_view)) { @@ -2121,6 +2193,25 @@ row_sel_get_clust_rec_for_mysql( clust_rec = old_vers; } + + /* If we had to go to an earlier version of row or the + secondary index record is delete marked, then it may be that + the secondary index record corresponding to clust_rec + (or old_vers) is not rec; in that case we must ignore + such row because in our snapshot rec would not have existed. + Remember that from rec we cannot see directly which transaction + id corrsponds to it: we have to go to the clustered index + record. A query where we want to fetch all rows where + the secondary index value is in some interval would return + a wrong result if we would not drop rows which we come to + visit through secondary index records that would not really + exist in our snapshot. */ + + if ((old_vers || rec_get_deleted_flag(rec)) + && !row_sel_sec_rec_is_for_clust_rec(rec, sec_index, + clust_rec, clust_index)) { + clust_rec = NULL; + } } *out_rec = clust_rec; -- cgit v1.2.1 From 10f869455fde6d87fb8194a356c029b72d3ba85d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 May 2001 18:05:15 +0300 Subject: row0sel.c Fixed a typo in the fix to consistent read through a secondary index innobase/row/row0sel.c: Fixed a typo in the fix to consistent read through a secondary index --- innobase/row/row0sel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'innobase/row/row0sel.c') diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 8845f9192da..36ecdce545c 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -70,7 +70,7 @@ row_sel_sec_rec_is_for_clust_rec( n = dict_index_get_n_ordering_defined_by_user(sec_index); - for (i = 0; i++; i < n) { + for (i = 0; i < n; i++) { col = dict_field_get_col( dict_index_get_nth_field(sec_index, i)); -- cgit v1.2.1 From 50d5bb5bbfc5187df68a53044ed08b7f09d93a07 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 May 2001 23:06:52 +0300 Subject: row0sel.c Fix a bug in consistent read through secondary key innobase/row/row0sel.c: Fix a bug in consistent read through secondary key --- innobase/row/row0sel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'innobase/row/row0sel.c') diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 36ecdce545c..58e0d053947 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2700,8 +2700,10 @@ rec_loop: goto next_rec; } - - rec = clust_rec; + + if (prebuilt->need_to_access_clustered) { + rec = clust_rec; + } } /* We found a qualifying row */ -- cgit v1.2.1