rocksdb
rocksdb copied to clipboard
DeleteRange doesn't work well with row_cache
Expected behavior & Actual behavior
when row_cache is enabled,
after we delete a key by a DeleteRange call,
we can still Get the key and its value from the db
Steps to reproduce the behavior
#include <iostream>
#include <rocksdb/db.h>
int main() {
rocksdb::Options ops;
ops.max_write_buffer_number = 1;
ops.create_if_missing = true;
ops.row_cache = rocksdb::NewLRUCache(1024);
rocksdb::DB *db = nullptr;
auto s = rocksdb::DB::Open(ops, "./db", &db);
assert(s.ok());
const std::string key = "mykey";
s = db->Put(rocksdb::WriteOptions(), key, "myvalue");
assert(s.ok());
// flush so we can use the row cache, not memtable
s = db->Flush(rocksdb::FlushOptions());
assert(s.ok());
std::string value;
s = db->Get(rocksdb::ReadOptions(), key, &value);
assert(s.ok());
s = db->DeleteRange(rocksdb::WriteOptions(), db->DefaultColumnFamily(), "a", "z");
assert(s.ok());
value.clear();
s = db->Get(rocksdb::ReadOptions(), key, &value);
// status should be NotFound, but the program's output is an OK
std::cout << "status: " << s.ToString() << ", value: " << value << std::endl;
return 0;
}
Thanks for reporting. I think the most we can promise right now is making it explicitly unsupported, i.e., disallow range deletions when row cache is enabled. If you want to contribute code for purging the row cache when DeleteRange
happens, we should be able to review and land it.
Thank for your reply @ajkr , I'll look into this and try to fix it.
@ajkr Could you tell me which PR fix this BUG, thanks?
Re-open the issue so we remember to add some safeguard before it's supported.
The above test passes now. But if DeleteRange() and row key is from the same SST file, then it still fails.
const Snapshot* snap = db_->GetSnapshot();
ASSERT_OK(db_->DeleteRange(rocksdb::WriteOptions(),
db_->DefaultColumnFamily(), "a", "z"));
ASSERT_OK(Flush());
std::string value;
Status s = db_->Get(ReadOptions(), "a", &value);
std::cout << "status: " << s.ToString() << ", value: " << value << std::endl;
value.clear();
s = db_->Get(ReadOptions(), "a", &value);
// status should be NotFound, but the program's output is an OK
std::cout << "status: " << s.ToString() << ", value: " << value << std::endl;
status: NotFound: , value:
status: OK, value: myval