Mitigate regression bug of options.max_successive_merges hit during DB Recovery
Summary:
After 1b8a2e8fdd
, DB Pointer is passed to WriteBatchInternal::InsertInto() while DB recovery. This can cause deadlock if options.max_successive_merges hits. In that case DB::Get() will be called. Get() will try to acquire the DB mutex, which is already held by the DB::Open(), causing a deadlock condition.
This commit mitigates the problem by not passing the DB pointer unless 2PC is allowed.
Test Plan: Add a new test and run it.
Reviewers: IslamAbdelRahman, andrewkr, kradhakrishnan, horuff
Reviewed By: kradhakrishnan
Subscribers: leveldb, andrewkr, dhruba
Differential Revision: https://reviews.facebook.net/D62625
This commit is contained in:
parent
2701f5c267
commit
a31b8cb7a7
@ -1563,10 +1563,15 @@ Status DBImpl::RecoverLogFiles(const std::vector<uint64_t>& log_numbers,
|
||||
// insert. We don't want to fail the whole write batch in that case --
|
||||
// we just ignore the update.
|
||||
// That's why we set ignore missing column families to true
|
||||
// If we pass DB through and options.max_successive_merges is hit
|
||||
// during recovery, Get() will be issued which will try to acquire
|
||||
// DB mutex and cause deadlock, as DB mutex is already held.
|
||||
// The DB pointer is not needed unless 2PC is used.
|
||||
// TODO(sdong) fix the allow_2pc case too.
|
||||
status = WriteBatchInternal::InsertInto(
|
||||
&batch, column_family_memtables_.get(), &flush_scheduler_, true,
|
||||
log_number, this, false /* concurrent_memtable_writes */,
|
||||
next_sequence);
|
||||
log_number, db_options_.allow_2pc ? this : nullptr,
|
||||
false /* concurrent_memtable_writes */, next_sequence);
|
||||
MaybeIgnoreError(&status);
|
||||
if (!status.ok()) {
|
||||
// We are treating this as a failure while reading since we read valid
|
||||
|
@ -1487,6 +1487,23 @@ TEST_F(DBTest2, SyncPointMarker) {
|
||||
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(DBTest2, MaxSuccessiveMergesInRecovery) {
|
||||
Options options;
|
||||
options = CurrentOptions(options);
|
||||
options.merge_operator = MergeOperators::CreatePutOperator();
|
||||
DestroyAndReopen(options);
|
||||
|
||||
db_->Put(WriteOptions(), "foo", "bar");
|
||||
ASSERT_OK(db_->Merge(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Merge(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Merge(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Merge(WriteOptions(), "foo", "bar"));
|
||||
ASSERT_OK(db_->Merge(WriteOptions(), "foo", "bar"));
|
||||
|
||||
options.max_successive_merges = 3;
|
||||
Reopen(options);
|
||||
}
|
||||
} // namespace rocksdb
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
Loading…
Reference in New Issue
Block a user