summaryrefslogtreecommitdiff
path: root/db/compaction
diff options
context:
space:
mode:
authorYanqin Jin <yanqin@fb.com>2021-11-09 13:07:33 -0800
committerFacebook GitHub Bot <facebook-github-bot@users.noreply.github.com>2021-11-09 13:08:55 -0800
commita113cecfc9e41aada9eb483f25566ea664aeb04b (patch)
tree0fb7e958470fdd60abad9182234a4bd10d6b9e61 /db/compaction
parent2fbe32b0c1f239f21506fd3b0debab6bf40d625a (diff)
Fix a bug in timestamp-related GC (#9116)
Summary: For multiple versions (ts + seq) of the same user key, if they cross the boundary of `full_history_ts_low_`, we should retain the version that is visible to the `full_history_ts_low_`. Namely, we keep the internal key with the largest timestamp smaller than `full_history_ts_low`. Pull Request resolved: https://github.com/facebook/rocksdb/pull/9116 Test Plan: make check Reviewed By: ltamasi Differential Revision: D32261514 Pulled By: riversand963 fbshipit-source-id: e10f47c254c04c05261440051e4f50cb7d95474e
Diffstat (limited to 'db/compaction')
-rw-r--r--db/compaction/compaction_iterator.cc12
-rw-r--r--db/compaction/compaction_iterator_test.cc7
-rw-r--r--db/compaction/compaction_job_test.cc1
3 files changed, 15 insertions, 5 deletions
diff --git a/db/compaction/compaction_iterator.cc b/db/compaction/compaction_iterator.cc
index 002f2f839..cd6a28d8f 100644
--- a/db/compaction/compaction_iterator.cc
+++ b/db/compaction/compaction_iterator.cc
@@ -407,6 +407,12 @@ void CompactionIterator::NextFromInput() {
// Copy key for output
key_ = current_key_.SetInternalKey(key_, &ikey_);
+ int prev_cmp_with_ts_low =
+ !full_history_ts_low_ ? 0
+ : curr_ts_.empty()
+ ? 0
+ : cmp_->CompareTimestamp(curr_ts_, *full_history_ts_low_);
+
// If timestamp_size_ > 0, then copy from ikey_ to curr_ts_ for the use
// in next iteration to compare with the timestamp of next key.
UpdateTimestampAndCompareWithFullHistoryLow();
@@ -416,14 +422,16 @@ void CompactionIterator::NextFromInput() {
// (2) timestamp is disabled, OR
// (3) all history will be preserved, OR
// (4) user key (excluding timestamp) is different from previous key, OR
- // (5) timestamp is NO older than *full_history_ts_low_
+ // (5) timestamp is NO older than *full_history_ts_low_, OR
+ // (6) timestamp is the largest one older than full_history_ts_low_,
// then current_user_key_ must be treated as a different user key.
// This means, if a user key (excluding ts) is the same as the previous
// user key, and its ts is older than *full_history_ts_low_, then we
// consider this key for GC, e.g. it may be dropped if certain conditions
// match.
if (!has_current_user_key_ || !timestamp_size_ || !full_history_ts_low_ ||
- !user_key_equal_without_ts || cmp_with_history_ts_low_ >= 0) {
+ !user_key_equal_without_ts || cmp_with_history_ts_low_ >= 0 ||
+ prev_cmp_with_ts_low >= 0) {
// Initialize for future comparison for rule (A) and etc.
current_user_key_sequence_ = kMaxSequenceNumber;
current_user_key_snapshot_ = 0;
diff --git a/db/compaction/compaction_iterator_test.cc b/db/compaction/compaction_iterator_test.cc
index a699b840d..d6cc899f5 100644
--- a/db/compaction/compaction_iterator_test.cc
+++ b/db/compaction/compaction_iterator_test.cc
@@ -1171,9 +1171,10 @@ TEST_P(CompactionIteratorTsGcTest, NewHidesOldSameSnapshot) {
std::string full_history_ts_low;
// Keys whose timestamps larger than or equal to 102 will be preserved.
PutFixed64(&full_history_ts_low, 102);
- const std::vector<std::string> expected_keys = {input_keys[0],
- input_keys[1]};
- const std::vector<std::string> expected_values = {"", "a2"};
+ const std::vector<std::string> expected_keys = {
+ input_keys[0], input_keys[1], input_keys[2]};
+ const std::vector<std::string> expected_values = {"", input_values[1],
+ input_values[2]};
RunTest(input_keys, input_values, expected_keys, expected_values,
/*last_committed_seq=*/kMaxSequenceNumber,
/*merge_operator=*/nullptr, /*compaction_filter=*/nullptr,
diff --git a/db/compaction/compaction_job_test.cc b/db/compaction/compaction_job_test.cc
index 6fee80f6a..4d46b0f5d 100644
--- a/db/compaction/compaction_job_test.cc
+++ b/db/compaction/compaction_job_test.cc
@@ -1398,6 +1398,7 @@ TEST_F(CompactionJobTimestampTest, SomeKeysExpired) {
auto expected_results =
mock::MakeMockFile({{KeyStr("a", 5, ValueType::kTypeValue, 50), "a5"},
+ {KeyStr("a", 0, ValueType::kTypeValue, 0), "a3"},
{KeyStr("b", 6, ValueType::kTypeValue, 49), "b6"}});
const auto& files = cfd_->current()->storage_info()->LevelFiles(0);