mirror of https://github.com/facebook/rocksdb.git
Fix RangeDeletion bug (#6062)
Summary: Read keys from a snapshot that a range deletion were added after the snapshot was created and this range deletion was inside an immutable memtable, we will get wrong key set. More detail rest in codes. Pull Request resolved: https://github.com/facebook/rocksdb/pull/6062 Differential Revision: D18966785 Pulled By: pdillinger fbshipit-source-id: 38a60bb1e2d0a1dbfc8ec641617200b6a02b86c3
This commit is contained in:
parent
a844591201
commit
c4ce8e637f
|
@ -1,7 +1,9 @@
|
||||||
# Rocksdb Change Log
|
# Rocksdb Change Log
|
||||||
## Unreleased
|
## Unreleased
|
||||||
### Buf Fixes
|
### Bug Fixes
|
||||||
* Fix a bug that can cause unnecessary bg thread to be scheduled(#6104).
|
* Fix a bug that can cause unnecessary bg thread to be scheduled(#6104).
|
||||||
|
* Fix a bug in which a snapshot read could be affected by a DeleteRange after the snapshot (#6062).
|
||||||
|
|
||||||
## 6.6.0 (11/25/2019)
|
## 6.6.0 (11/25/2019)
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
* Fix data corruption caused by output of intra-L0 compaction on ingested file not being placed in correct order in L0.
|
* Fix data corruption caused by output of intra-L0 compaction on ingested file not being placed in correct order in L0.
|
||||||
|
|
|
@ -1427,6 +1427,47 @@ TEST_F(DBRangeDelTest, SnapshotPreventsDroppedKeys) {
|
||||||
db_->ReleaseSnapshot(snapshot);
|
db_->ReleaseSnapshot(snapshot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DBRangeDelTest, SnapshotPreventsDroppedKeysInImmMemTables) {
|
||||||
|
const int kFileBytes = 1 << 20;
|
||||||
|
|
||||||
|
Options options = CurrentOptions();
|
||||||
|
options.compression = kNoCompression;
|
||||||
|
options.disable_auto_compactions = true;
|
||||||
|
options.target_file_size_base = kFileBytes;
|
||||||
|
Reopen(options);
|
||||||
|
|
||||||
|
// block flush thread -> pin immtables in memory
|
||||||
|
SyncPoint::GetInstance()->DisableProcessing();
|
||||||
|
SyncPoint::GetInstance()->LoadDependency({
|
||||||
|
{"SnapshotPreventsDroppedKeysInImmMemTables:AfterNewIterator",
|
||||||
|
"DBImpl::BGWorkFlush"},
|
||||||
|
});
|
||||||
|
SyncPoint::GetInstance()->EnableProcessing();
|
||||||
|
|
||||||
|
ASSERT_OK(Put(Key(0), "a"));
|
||||||
|
std::unique_ptr<const Snapshot, std::function<void(const Snapshot*)>>
|
||||||
|
snapshot(db_->GetSnapshot(),
|
||||||
|
[this](const Snapshot* s) { db_->ReleaseSnapshot(s); });
|
||||||
|
|
||||||
|
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), Key(0),
|
||||||
|
Key(10)));
|
||||||
|
|
||||||
|
ASSERT_OK(dbfull()->TEST_SwitchMemtable());
|
||||||
|
|
||||||
|
ReadOptions read_opts;
|
||||||
|
read_opts.snapshot = snapshot.get();
|
||||||
|
std::unique_ptr<Iterator> iter(db_->NewIterator(read_opts));
|
||||||
|
|
||||||
|
TEST_SYNC_POINT("SnapshotPreventsDroppedKeysInImmMemTables:AfterNewIterator");
|
||||||
|
|
||||||
|
iter->SeekToFirst();
|
||||||
|
ASSERT_TRUE(iter->Valid());
|
||||||
|
ASSERT_EQ(Key(0), iter->key());
|
||||||
|
|
||||||
|
iter->Next();
|
||||||
|
ASSERT_FALSE(iter->Valid());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DBRangeDelTest, RangeTombstoneWrittenToMinimalSsts) {
|
TEST_F(DBRangeDelTest, RangeTombstoneWrittenToMinimalSsts) {
|
||||||
// Adapted from
|
// Adapted from
|
||||||
// https://github.com/cockroachdb/cockroach/blob/de8b3ea603dd1592d9dc26443c2cc92c356fbc2f/pkg/storage/engine/rocksdb_test.go#L1267-L1398.
|
// https://github.com/cockroachdb/cockroach/blob/de8b3ea603dd1592d9dc26443c2cc92c356fbc2f/pkg/storage/engine/rocksdb_test.go#L1267-L1398.
|
||||||
|
|
|
@ -186,11 +186,14 @@ Status MemTableListVersion::AddRangeTombstoneIterators(
|
||||||
const ReadOptions& read_opts, Arena* /*arena*/,
|
const ReadOptions& read_opts, Arena* /*arena*/,
|
||||||
RangeDelAggregator* range_del_agg) {
|
RangeDelAggregator* range_del_agg) {
|
||||||
assert(range_del_agg != nullptr);
|
assert(range_del_agg != nullptr);
|
||||||
|
// Except for snapshot read, using kMaxSequenceNumber is OK because these
|
||||||
|
// are immutable memtables.
|
||||||
|
SequenceNumber read_seq = read_opts.snapshot != nullptr
|
||||||
|
? read_opts.snapshot->GetSequenceNumber()
|
||||||
|
: kMaxSequenceNumber;
|
||||||
for (auto& m : memlist_) {
|
for (auto& m : memlist_) {
|
||||||
// Using kMaxSequenceNumber is OK because these are immutable memtables.
|
|
||||||
std::unique_ptr<FragmentedRangeTombstoneIterator> range_del_iter(
|
std::unique_ptr<FragmentedRangeTombstoneIterator> range_del_iter(
|
||||||
m->NewRangeTombstoneIterator(read_opts,
|
m->NewRangeTombstoneIterator(read_opts, read_seq));
|
||||||
kMaxSequenceNumber /* read_seq */));
|
|
||||||
range_del_agg->AddTombstones(std::move(range_del_iter));
|
range_del_agg->AddTombstones(std::move(range_del_iter));
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
|
|
Loading…
Reference in New Issue