Skip to content
This repository has been archived by the owner on Jul 26, 2022. It is now read-only.

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

Closed
spetrunia opened this issue Aug 25, 2015 · 5 comments
Closed

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

spetrunia opened this issue Aug 25, 2015 · 5 comments
Assignees

Comments

@spetrunia
Copy link

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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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 Aug 25, 2015
@spetrunia
Copy link
Author

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
Copy link
Author

spetrunia added a commit that referenced this issue Sep 2, 2015
…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
spetrunia added a commit that referenced this issue Sep 2, 2015
… 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
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant