From f235f4b0a3236037905ef5fec2a28bbb74121770 Mon Sep 17 00:00:00 2001 From: Yanqin Jin Date: Tue, 24 Aug 2021 18:17:32 -0700 Subject: [PATCH] Fix a bug of secondary instance sequence going backward (#8653) Summary: Recent refactor of `ReactiveVersionSet::ReadAndApply()` uses `ManifestTailer` whose `Iterate()` method can cause the db's `last_sequence_` to go backward. Consequently, read requests can see out-dated data. For example, latest changes to the primary will not be seen on the secondary even after a `TryCatchUpWithPrimary()` if no new write batches are read from the WALs and no new MANIFEST entries are read from the MANIFEST. Fix the bug so that `VersionEditHandler::CheckIterationResult` will never decrease `last_sequence_`, `last_allocated_sequence_` and `last_published_sequence_`. Pull Request resolved: https://github.com/facebook/rocksdb/pull/8653 Test Plan: make check Reviewed By: jay-zhuang Differential Revision: D30272084 Pulled By: riversand963 fbshipit-source-id: c6a49c534b2509b93ef62d8936ed0acd5b860eaa --- HISTORY.md | 1 + db/db_secondary_test.cc | 33 +++++++++++++++++++++++++++++++++ db/version_edit_handler.cc | 19 ++++++++++++++----- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index ba89774c5..25c1d7999 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -2,6 +2,7 @@ ## Unreleased ### Bug Fixes * Allow secondary instance to refresh iterator. Assign read seq after referencing SuperVersion. +* Fixed a bug of secondary instance's last_sequence going backward, and reads on the secondary fail to see recent updates from the primary. ### New Features * RemoteCompaction's interface now includes `db_name`, `db_id`, `session_id`, which could help the user uniquely identify compaction job between db instances and sessions. diff --git a/db/db_secondary_test.cc b/db/db_secondary_test.cc index 178844ff7..902f1ec2c 100644 --- a/db/db_secondary_test.cc +++ b/db/db_secondary_test.cc @@ -560,6 +560,39 @@ TEST_F(DBSecondaryTest, OpenAsSecondaryWALTailing) { verify_db_func("new_foo_value_1", "new_bar_value"); } +TEST_F(DBSecondaryTest, SecondaryTailingBug_ISSUE_8467) { + Options options; + options.env = env_; + Reopen(options); + for (int i = 0; i < 3; ++i) { + ASSERT_OK(Put("foo", "foo_value" + std::to_string(i))); + ASSERT_OK(Put("bar", "bar_value" + std::to_string(i))); + } + + Options options1; + options1.env = env_; + options1.max_open_files = -1; + OpenSecondary(options1); + + const auto verify_db = [&](const std::string& foo_val, + const std::string& bar_val) { + std::string value; + ReadOptions ropts; + Status s = db_secondary_->Get(ropts, "foo", &value); + ASSERT_OK(s); + ASSERT_EQ(foo_val, value); + + s = db_secondary_->Get(ropts, "bar", &value); + ASSERT_OK(s); + ASSERT_EQ(bar_val, value); + }; + + for (int i = 0; i < 2; ++i) { + ASSERT_OK(db_secondary_->TryCatchUpWithPrimary()); + verify_db("foo_value2", "bar_value2"); + } +} + TEST_F(DBSecondaryTest, RefreshIterator) { Options options; options.env = env_; diff --git a/db/version_edit_handler.cc b/db/version_edit_handler.cc index 7a2996a59..5631cda48 100644 --- a/db/version_edit_handler.cc +++ b/db/version_edit_handler.cc @@ -427,11 +427,20 @@ void VersionEditHandler::CheckIterationResult(const log::Reader& reader, assert(version_set_->manifest_file_size_ > 0); version_set_->next_file_number_.store( version_edit_params_.next_file_number_ + 1); - version_set_->last_allocated_sequence_ = - version_edit_params_.last_sequence_; - version_set_->last_published_sequence_ = - version_edit_params_.last_sequence_; - version_set_->last_sequence_ = version_edit_params_.last_sequence_; + SequenceNumber last_seq = version_edit_params_.last_sequence_; + assert(last_seq != kMaxSequenceNumber); + if (last_seq != kMaxSequenceNumber && + last_seq > version_set_->last_allocated_sequence_.load()) { + version_set_->last_allocated_sequence_.store(last_seq); + } + if (last_seq != kMaxSequenceNumber && + last_seq > version_set_->last_published_sequence_.load()) { + version_set_->last_published_sequence_.store(last_seq); + } + if (last_seq != kMaxSequenceNumber && + last_seq > version_set_->last_sequence_.load()) { + version_set_->last_sequence_.store(last_seq); + } version_set_->prev_log_number_ = version_edit_params_.prev_log_number_; } }