diff --git a/mysql-test/suite/rocksdb/r/issue111.result b/mysql-test/suite/rocksdb/r/issue111.result new file mode 100644 index 000000000000..315d2d2b50bc --- /dev/null +++ b/mysql-test/suite/rocksdb/r/issue111.result @@ -0,0 +1,32 @@ +create table t1 ( +pk int not null primary key, +col1 int not null, +col2 int not null, +key(col1) +) engine=rocksdb; +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; +insert into t1 select a,a,a from one_k; +# Start the transaction, get the snapshot +begin; +select * from t1 where col1<10; +pk col1 col2 +0 0 0 +1 1 1 +2 2 2 +3 3 3 +4 4 4 +5 5 5 +6 6 6 +7 7 7 +8 8 8 +9 9 9 +# Connect with another connection and make a conflicting change +begin; +update t1 set col2=123456 where pk=0; +commit; +update t1 set col2=col2+1 where col1 < 10 limit 5; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +drop table t1, ten, one_k; diff --git a/mysql-test/suite/rocksdb/t/issue111.test b/mysql-test/suite/rocksdb/t/issue111.test new file mode 100644 index 000000000000..671ea4708d60 --- /dev/null +++ b/mysql-test/suite/rocksdb/t/issue111.test @@ -0,0 +1,38 @@ +--source include/have_rocksdb.inc + +connect (con2,localhost,root,,); +connection default; + +create table t1 ( + pk int not null primary key, + col1 int not null, + col2 int not null, + key(col1) +) engine=rocksdb; + +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; + +insert into t1 select a,a,a from one_k; + +--echo # Start the transaction, get the snapshot +begin; +select * from t1 where col1<10; + +--echo # Connect with another connection and make a conflicting change +connection con2; + +begin; +update t1 set col2=123456 where pk=0; +commit; + +connection default; + +--error ER_LOCK_DEADLOCK +update t1 set col2=col2+1 where col1 < 10 limit 5; + +disconnect con2; +drop table t1, ten, one_k; diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 613b4c3b6145..2b0c573971de 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -3750,6 +3750,9 @@ int ha_rocksdb::secondary_index_read(int keyno, uchar *buf) { stats.rows_requested++; + /* Use STATUS_NOT_FOUND when record not found or some error occurred */ + table->status= STATUS_NOT_FOUND; + if (scan_it->Valid()) { rocksdb::Slice key= scan_it->key(); @@ -3783,11 +3786,10 @@ int ha_rocksdb::secondary_index_read(int keyno, uchar *buf) stats.rows_read++; stats.rows_index_next++; update_row_stats(ROWS_READ); - return rc; } + return rc; } } - table->status= STATUS_NOT_FOUND; return HA_ERR_END_OF_FILE; } @@ -4186,7 +4188,7 @@ int ha_rocksdb::index_read_map_impl(uchar *buf, const uchar *key, if (rc) { - table->status= STATUS_NOT_FOUND; /* Only not found error is possible */ + table->status= STATUS_NOT_FOUND; /* This status is returned on any error */ io_perf_end_and_record(); DBUG_RETURN(rc); } @@ -4627,11 +4629,13 @@ int ha_rocksdb::get_row_by_rowid(uchar *buf, const char *rowid, uint rowid_size) } found= !s.IsNotFound(); + table->status= STATUS_NOT_FOUND; if (found) { last_rowkey.copy((const char*)rowid, rowid_size, &my_charset_bin); rc= convert_record_from_storage_format(&key_slice, buf); - table->status= 0; + if (!rc) + table->status= 0; } else { @@ -4639,7 +4643,6 @@ int ha_rocksdb::get_row_by_rowid(uchar *buf, const char *rowid, uint rowid_size) Note: we don't need to unlock the row. It is intentional that we keep locks on rows that don't exist. */ - table->status= STATUS_NOT_FOUND; rc= HA_ERR_KEY_NOT_FOUND; }