Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Clone in Desktop Download ZIP

Loading…

UPDATE for table with VARCHAR pk gives "Can't find record" error #99

Closed
spetrunia opened this Issue · 5 comments

1 participant

@spetrunia
Collaborator

Testcase:

create table ten(a int primary key);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

create table one_k(a int primary key);
insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;

create table t8 (
  a varchar(32) primary key,
  col1 int
) engine=rocksdb;

insert into t8 
select concat('v-', 10000 + A.a*1000 + B.a), 12345
from ten A, one_k B;

select * from t8 limit 40;

update t8 set a=concat('x-', a) where a between 'v-10012' and 'v-10016';

This gives an error:

mysqltest: At line 20: query 'update t8 set a=concat('x-', a) where a between 'v-10012' and 'v-10016'' failed: 1032: Can't find record in 't8'
@spetrunia
Collaborator

The reason for this is as follows:

  • rowids are mem-comparable forms of PK.

  • mem-comparable forms of PK used to be fixed-length for MyRocks, but since "efficient varchar encoding" they are variable-length.

  • However, MySQL assumes that rowids have fixed length. Currently rowids are zero-padded.

  • When MyRocks attempt to do a PK lookup for rnd_pos(zero-padded-rowid), the record is not found and we have an error.

@spetrunia
Collaborator

Possible solutions:

S1. Let the rowid be PK in KeyTupleFormat. KeyTupleFormat is fixed-length.

  • We will have to provide ha_rocksdb::cmp_ref() function
  • (TODO: is it possible to provide the original (non-mem-comparable) form of PK columns in all cases where MyRocks needs to return a rowid?)

S2. Keep the rowid being mem-comparable form.

  • We will have to know how much end-space bytes are padding, and ha_rocksdb::rnd_pos() should strip them off before doing the index lookup.
@spetrunia
Collaborator

is it possible to provide the original (non-mem-comparable) form of PK columns in all cases where MyRocks needs to return a rowid?)

This doesn't work in all cases.
Consider a case where the PK column uses case-sensitive collation (so one can't restore the value from its mem-comparable form).
Then, suppose we're doing an index-only scan on a secondary index.

In this case, secondary index only gives mem-comparable form of PK columns. We can't restore the original values, and so we can return them in KeyTupleFormat

@spetrunia spetrunia self-assigned this
@spetrunia
Collaborator

We will have to know how much end-space bytes are padding, and ha_rocksdb::rnd_pos() should strip them off before doing the index lookup.

This looks feasible. mem-comparable images of keys are traversed by skip_func which has two possible values:
A. skip_max_length
B. skip_variable_length

skip_variable_length skips data in "varchar encoding". Varchar encoding means 9-byte groups, where the 9th byte varies between 0xFF (no padding bytes) to 0xF7 (all 8 bytes were padding bytes).

That is, if the next 9-byte group is padding it has all zeros, it is zero-padding, otherwise it is not.
If there is less than 9-byte data, it is zero-padding.

@spetrunia spetrunia referenced this issue from a commit
@spetrunia spetrunia Issue #100: UPDATE may hang when it does a full table scan and update…
…s PK values

Summary:
Do set handler::key_used_on_scan in ha_rocksdb::open. This informs the
SQL layer that MyRocks uses primary key when doing a full table scan.
When the SQL layer knows this, it will buffer updates that change the
value of the primary key.

Note: after this patch, rocksdb.rocksdb test fails with this error:
Can't find record in 't8'.  This is Issue #99.

Test Plan: Run MTR

Reviewers: hermanlee4, maykov, jtolmer, yoshinorim

Reviewed By: yoshinorim

Differential Revision: https://reviews.facebook.net/D45519
3d1ae11
@spetrunia spetrunia referenced this issue from a commit
@spetrunia spetrunia Issue #99: UPDATE for table with VARCHAR pk gives "Can't find record"…
… error

Summary:
MyRocks uses mem-comparable form of Primary Key as rowid. SQL layer assumes
that rowids have fixed size. However, "Efficient Varchar encoding" feature
in MyRocks makes mem-comparable forms to have varying lengths.
This causes rowids to be "garbage-padded", and possible "Record not found"
errors whenever SQL layer calls ha_rocksdb::rnd_pos().

Fixed by making ::position() to pad rowid with zeros,
and making ::rnd_pos() remove the zeros before doing the PK lookup.

Test Plan: Ran MTR

Reviewers: maykov, jtolmer, jkedgar, yoshinorim, hermanlee4

Reviewed By: hermanlee4

Differential Revision: https://reviews.facebook.net/D45639
6b5a0dd
@spetrunia spetrunia closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.