diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2011-09-12 10:12:15 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@oracle.com> | 2011-09-12 10:12:15 +0300 |
commit | cc496eb7466487747d26d272f0559df9a07f2e34 (patch) | |
tree | aa87288a228c83a53ffe1f3dfc1851cef20dbc4f /storage | |
parent | 13fefeb04ade34418cd9d99aa93bffb69fdae27e (diff) | |
download | mariadb-git-cc496eb7466487747d26d272f0559df9a07f2e34.tar.gz |
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
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innodb_plugin/ChangeLog | 5 | ||||
-rw-r--r-- | storage/innodb_plugin/row/row0sel.c | 20 |
2 files changed, 22 insertions, 3 deletions
diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 130a0f9afa2..ff6bd10dbe6 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +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: diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index aa3f6283c4f..c9b409cbedd 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -1,6 +1,6 @@ /***************************************************************************** -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; |