Commit ae68af40 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX

When there is a secondary index on a column prefix of an externally
stored column and an entry in the secondary index is shorter than the
reserved prefix length, it should mean that the secondary index entry
is holding the complete column value. When comparing this secondary
index column value to the column in the clustered index row, we must
compare the entire prefix that was fetched from the clustered
index. The bug was that we would just compare that the column in the
clustered index starts with the value found in the secondary index
column.

This bug affects only the InnoDB Barracuda formats (ROW_FORMAT=DYNAMIC
and ROW_FORMAT=COMPRESSED), in which columns that are stored off-page
in the clustered index do not contain any prefix in the clustered
index record.

row_sel_sec_rec_is_for_blob(): Add the parameter prefix_len, for
ifield->prefix_len. Add some assertions.

Sorry, I did not manage to produce a test case. This patch does
produce correct results on the data set that Michael isolated on our
test machine. That was with the purge and background rollback
suspended, because they would make the bug go away.

rb:760 approved by Sunny Bains
parent 1fa37ae4
2011-09-12 The InnoDB Team
* row/row0sel.c:
Fix Bug#12601439 CONSISTENT READ FAILURE IN COLUMN PREFIX INDEX
2011-09-08 The InnoDB Team
* btr/btr0cur.c, include/page0page.h, include/row0upd.ic:
......
/*****************************************************************************
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
......@@ -107,12 +107,17 @@ row_sel_sec_rec_is_for_blob(
ulint clust_len, /*!< in: length of clust_field */
const byte* sec_field, /*!< in: column in secondary index */
ulint sec_len, /*!< in: length of sec_field */
ulint prefix_len, /*!< in: index column prefix length
in bytes */
ulint zip_size) /*!< in: compressed page size, or 0 */
{
ulint len;
byte buf[DICT_MAX_INDEX_COL_LEN];
ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE);
ut_ad(prefix_len >= sec_len);
ut_ad(prefix_len > 0);
ut_a(prefix_len <= sizeof buf);
if (UNIV_UNLIKELY
(!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE,
......@@ -124,7 +129,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE);
}
len = btr_copy_externally_stored_field_prefix(buf, sizeof buf,
len = btr_copy_externally_stored_field_prefix(buf, prefix_len,
zip_size,
clust_field, clust_len);
......@@ -138,7 +143,7 @@ row_sel_sec_rec_is_for_blob(
}
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen,
sec_len, len, (const char*) buf);
prefix_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
}
......@@ -225,11 +230,20 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) {
/* This function should never be
invoked on an Antelope format table,
because they should always contain
enough prefix in the clustered index
record. */
ut_ad(dict_table_get_format(clust_index->table)
>= DICT_TF_FORMAT_ZIP);
if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen,
clust_field, clust_len,
sec_field, sec_len,
ifield->prefix_len,
dict_table_zip_size(
clust_index->table))) {
goto inequal;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment