Skip to content

Commit 3e712ab

Browse files
Manuel Unginikep
authored andcommitted
Fix handling of consecutive sentinel values
Summary: For partial indexes, it is possible to have consecutive sentinel values, and the code to skip over sentinel values during iteration does not handle this correctly. eg. If we have have the following data: ``` a b 1 1 (sentinel) 1 2 (sentinel) 1 2 1 1 2 2 ``` `get_prefix_from_start` returns `(1, 2)` as the group we expect to see (since `(1, 1)` group is empty on the primary key). A seek to `a >=1` on the secondary key would land on `(1, 1)`, but we skip this key since we detect that it's a sentinel value. The cursor is then on `(1, 2)` which matches the expected prefix, and we start reading from the SK from that position. However, this is also a sentinel value, and will not decode correctly. This leads to these errors: ``` ERROR 1296 (HY000): Got error 505 'Found data corruption.' from ROCKSDB ``` The fix is to use a while loop to skip over sentinel values. There are two other places where we skip over sentinel values, but they are not problematic since they are used for iterating over a non-empty groups (so consecutive sentinel values are not possible). I decided not to add while loops defensively in the other places, so that we fail loudly if something unexpected happens. Ideally, we should just seek directly to the first group that we got from the PK (which guarantees a non-empty group, similar to other cases), but this is a more involved change for later. Differential Revision: D46352747
1 parent 51b7372 commit 3e712ab

File tree

4 files changed

+18
-1
lines changed

4 files changed

+18
-1
lines changed

mysql-test/suite/rocksdb/r/partial_index.result

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,5 +231,6 @@ rocksdb_partial_index_rows_sorted 1
231231
include/assert.inc [Check that materialized groups are zero.]
232232
include/assert.inc [Check that materialized rows are zero.]
233233
DROP TABLE t1, t2;
234+
DELETE FROM sentinel where c2 <= 2;
234235
DROP TABLE sentinel;
235236
set optimizer_force_index_for_range = off;

mysql-test/suite/rocksdb/t/partial_index.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ SELECT variable_name, t2.variable_value - t1.variable_value AS diff FROM t1 JOIN
7777

7878
DROP TABLE t1, t2;
7979

80+
#
81+
# Test consecutive sentinel values
82+
#
83+
DELETE FROM sentinel where c2 <= 2;
84+
85+
--let $query1= SELECT c1, c2 FROM sentinel FORCE INDEX(c1);
86+
--let $query2= SELECT c1, c2 FROM sentinel FORCE INDEX(PRIMARY);
87+
--source include/diff_queries.inc
88+
8089
DROP TABLE sentinel;
8190

8291
set optimizer_force_index_for_range = off;

mysql-test/suite/rocksdb/t/partial_index_link.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ while ($i < 10) {
4747
inc $i;
4848
}
4949

50+
--let $query1= SELECT DISTINCT link_type FROM link_table FORCE INDEX (id1_type)
51+
--let $query2= SELECT DISTINCT link_type FROM link_table FORCE INDEX (id1_type2)
52+
--source include/diff_queries.inc
53+
5054
# Rebuild the table so that nothing is materialized anymore.
5155
ALTER TABLE link_table ENGINE=ROCKSDB;
5256

storage/rocksdb/rdb_iterator.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,10 @@ int Rdb_iterator_partial::seek(enum ha_rkey_function find_flag,
854854
rc = Rdb_iterator_base::seek(find_flag, start_key, true, end_key,
855855
read_current);
856856

857-
if (rc == 0 && Rdb_iterator_base::key().size() == m_cur_prefix_key_len) {
857+
while (rc == 0 && Rdb_iterator_base::key().size() == m_cur_prefix_key_len) {
858+
if (thd_killed(m_thd)) {
859+
return HA_ERR_QUERY_INTERRUPTED;
860+
}
858861
rc = direction ? Rdb_iterator_base::next() : Rdb_iterator_base::prev();
859862
}
860863

0 commit comments

Comments
 (0)