Skip to content

Commit 5fe832a

Browse files
do not hold mutex for SyncClosedLogs
Signed-off-by: Little-Wallace <[email protected]>
1 parent ab6edb4 commit 5fe832a

File tree

4 files changed

+63
-28
lines changed

4 files changed

+63
-28
lines changed

db/db_impl/db_impl.cc

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,19 +1398,37 @@ Status DBImpl::SyncWAL() {
13981398
TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:2");
13991399

14001400
TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:1");
1401+
VersionEdit synced_wals;
14011402
{
14021403
InstrumentedMutexLock l(&log_write_mutex_);
14031404
if (status.ok()) {
1404-
status = MarkLogsSynced(current_log_number, need_log_dir_sync);
1405+
MarkLogsSynced(current_log_number, need_log_dir_sync, &synced_wals);
14051406
} else {
14061407
MarkLogsNotSynced(current_log_number);
14071408
}
14081409
}
1410+
if (status.ok() && synced_wals.IsWalAddition()) {
1411+
InstrumentedMutexLock l(&mutex_);
1412+
status = ApplyWALToManifest(&synced_wals);
1413+
}
1414+
14091415
TEST_SYNC_POINT("DBImpl::SyncWAL:BeforeMarkLogsSynced:2");
14101416

14111417
return status;
14121418
}
14131419

1420+
Status DBImpl::ApplyWALToManifest(VersionEdit* synced_wals) {
1421+
// not empty, write to MANIFEST.
1422+
mutex_.AssertHeld();
1423+
Status status =
1424+
versions_->LogAndApplyToDefaultColumnFamily(synced_wals, &mutex_);
1425+
if (!status.ok() && versions_->io_status().IsIOError()) {
1426+
status = error_handler_.SetBGError(versions_->io_status(),
1427+
BackgroundErrorReason::kManifestWrite);
1428+
}
1429+
return status;
1430+
}
1431+
14141432
Status DBImpl::LockWAL() {
14151433
log_write_mutex_.Lock();
14161434
auto cur_log_writer = logs_.back().writer;
@@ -1430,20 +1448,20 @@ Status DBImpl::UnlockWAL() {
14301448
return Status::OK();
14311449
}
14321450

1433-
Status DBImpl::MarkLogsSynced(uint64_t up_to, bool synced_dir) {
1451+
void DBImpl::MarkLogsSynced(uint64_t up_to, bool synced_dir,
1452+
VersionEdit* synced_wals) {
14341453
log_write_mutex_.AssertHeld();
14351454
if (synced_dir && logfile_number_ == up_to) {
14361455
log_dir_synced_ = true;
14371456
}
1438-
VersionEdit synced_wals;
14391457
for (auto it = logs_.begin(); it != logs_.end() && it->number <= up_to;) {
14401458
auto& wal = *it;
14411459
assert(wal.getting_synced);
14421460
if (logs_.size() > 1) {
14431461
if (immutable_db_options_.track_and_verify_wals_in_manifest &&
14441462
wal.writer->file()->GetFileSize() > 0) {
1445-
synced_wals.AddWal(wal.number,
1446-
WalMetadata(wal.writer->file()->GetFileSize()));
1463+
synced_wals->AddWal(wal.number,
1464+
WalMetadata(wal.writer->file()->GetFileSize()));
14471465
}
14481466
logs_to_free_.push_back(wal.ReleaseWriter());
14491467
it = logs_.erase(it);
@@ -1454,22 +1472,11 @@ Status DBImpl::MarkLogsSynced(uint64_t up_to, bool synced_dir) {
14541472
}
14551473
assert(logs_.empty() || logs_[0].number > up_to ||
14561474
(logs_.size() == 1 && !logs_[0].getting_synced));
1457-
1458-
Status s;
1459-
if (synced_wals.IsWalAddition()) {
1460-
// not empty, write to MANIFEST.
1461-
s = versions_->LogAndApplyToDefaultColumnFamily(&synced_wals, &mutex_);
1462-
if (!s.ok() && versions_->io_status().IsIOError()) {
1463-
s = error_handler_.SetBGError(versions_->io_status(),
1464-
BackgroundErrorReason::kManifestWrite);
1465-
}
1466-
}
14671475
log_sync_cv_.SignalAll();
1468-
return s;
14691476
}
14701477

14711478
void DBImpl::MarkLogsNotSynced(uint64_t up_to) {
1472-
mutex_.AssertHeld();
1479+
log_write_mutex_.AssertHeld();
14731480
for (auto it = logs_.begin(); it != logs_.end() && it->number <= up_to;
14741481
++it) {
14751482
auto& wal = *it;

db/db_impl/db_impl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,7 +1606,7 @@ class DBImpl : public DB {
16061606
void ReleaseFileNumberFromPendingOutputs(
16071607
std::unique_ptr<std::list<uint64_t>::iterator>& v);
16081608

1609-
IOStatus SyncClosedLogs(JobContext* job_context);
1609+
IOStatus SyncClosedLogs(JobContext* job_context, VersionEdit* synced_wals);
16101610

16111611
// Flush the in-memory write buffer to storage. Switches to a new
16121612
// log-file/memtable and writes a new descriptor iff successful. Then
@@ -1877,7 +1877,8 @@ class DBImpl : public DB {
18771877
std::unique_ptr<TaskLimiterToken>* token, LogBuffer* log_buffer);
18781878

18791879
// helper function to call after some of the logs_ were synced
1880-
Status MarkLogsSynced(uint64_t up_to, bool synced_dir);
1880+
void MarkLogsSynced(uint64_t up_to, bool synced_dir, VersionEdit* edit);
1881+
Status ApplyWALToManifest(VersionEdit* edit);
18811882
// WALs with log number up to up_to are not synced successfully.
18821883
void MarkLogsNotSynced(uint64_t up_to);
18831884

db/db_impl/db_impl_compaction_flush.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ bool DBImpl::RequestCompactionToken(ColumnFamilyData* cfd, bool force,
8282
return false;
8383
}
8484

85-
IOStatus DBImpl::SyncClosedLogs(JobContext* job_context) {
85+
IOStatus DBImpl::SyncClosedLogs(JobContext* job_context,
86+
VersionEdit* synced_wals) {
8687
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Start");
8788
InstrumentedMutexLock l(&log_write_mutex_);
8889
autovector<log::Writer*, 1> logs_to_sync;
@@ -134,7 +135,7 @@ IOStatus DBImpl::SyncClosedLogs(JobContext* job_context) {
134135
// "number <= current_log_number - 1" is equivalent to
135136
// "number < current_log_number".
136137
if (io_s.ok()) {
137-
io_s = status_to_io_status(MarkLogsSynced(current_log_number - 1, true));
138+
MarkLogsSynced(current_log_number - 1, true, synced_wals);
138139
} else {
139140
MarkLogsNotSynced(current_log_number - 1);
140141
}
@@ -201,8 +202,15 @@ Status DBImpl::FlushMemTableToOutputFile(
201202
bool need_cancel = false;
202203
IOStatus log_io_s = IOStatus::OK();
203204
if (needs_to_sync_closed_wals) {
204-
// SyncClosedLogs() may unlock and re-lock the db_mutex.
205-
log_io_s = SyncClosedLogs(job_context);
205+
// SyncClosedLogs() may unlock and re-lock the db_log_write_mutex.
206+
VersionEdit synced_wals;
207+
mutex_.Unlock();
208+
log_io_s = SyncClosedLogs(job_context, &synced_wals);
209+
mutex_.Lock();
210+
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
211+
log_io_s = status_to_io_status(ApplyWALToManifest(&synced_wals));
212+
}
213+
206214
if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
207215
!log_io_s.IsColumnFamilyDropped()) {
208216
error_handler_.SetBGError(log_io_s, BackgroundErrorReason::kFlush);
@@ -459,7 +467,14 @@ Status DBImpl::AtomicFlushMemTablesToOutputFiles(
459467
if (logfile_number_ > 0) {
460468
// TODO (yanqin) investigate whether we should sync the closed logs for
461469
// single column family case.
462-
log_io_s = SyncClosedLogs(job_context);
470+
VersionEdit synced_wals;
471+
mutex_.Unlock();
472+
log_io_s = SyncClosedLogs(job_context, &synced_wals);
473+
mutex_.Lock();
474+
if (log_io_s.ok() && synced_wals.IsWalAddition()) {
475+
log_io_s = status_to_io_status(ApplyWALToManifest(&synced_wals));
476+
}
477+
463478
if (!log_io_s.ok() && !log_io_s.IsShutdownInProgress() &&
464479
!log_io_s.IsColumnFamilyDropped()) {
465480
if (total_log_size_ > 0) {

db/db_impl/db_impl_write.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -491,13 +491,20 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
491491
}
492492

493493
if (log_context.need_log_sync) {
494+
VersionEdit synced_wals;
494495
log_write_mutex_.Lock();
495496
if (status.ok()) {
496-
status = MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync);
497+
MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync,
498+
&synced_wals);
497499
} else {
498500
MarkLogsNotSynced(logfile_number_);
499501
}
500502
log_write_mutex_.Unlock();
503+
if (status.ok() && synced_wals.IsWalAddition()) {
504+
InstrumentedMutexLock l(&mutex_);
505+
status = ApplyWALToManifest(&synced_wals);
506+
}
507+
501508
// Requesting sync with two_write_queues_ is expected to be very rare. We
502509
// hence provide a simple implementation that is not necessarily efficient.
503510
if (two_write_queues_) {
@@ -631,16 +638,20 @@ Status DBImpl::PipelinedWriteImpl(const WriteOptions& write_options,
631638
}
632639
}
633640

641+
VersionEdit synced_wals;
634642
if (log_context.need_log_sync) {
635643
InstrumentedMutexLock l(&log_write_mutex_);
636644
if (w.status.ok()) {
637-
w.status =
638-
MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync);
645+
MarkLogsSynced(logfile_number_, log_context.need_log_dir_sync,
646+
&synced_wals);
639647
} else {
640648
MarkLogsNotSynced(logfile_number_);
641649
}
642650
}
643-
651+
if (w.status.ok() && synced_wals.IsWalAddition()) {
652+
InstrumentedMutexLock l(&mutex_);
653+
w.status = ApplyWALToManifest(&synced_wals);
654+
}
644655
write_thread_.ExitAsBatchGroupLeader(wal_write_group, w.status);
645656
}
646657

@@ -1064,6 +1075,7 @@ Status DBImpl::PreprocessWrite(const WriteOptions& write_options,
10641075
if (write_options.no_slowdown) {
10651076
status = Status::Incomplete("Write stall");
10661077
} else {
1078+
InstrumentedMutexLock l(&mutex_);
10671079
WriteBufferManagerStallWrites();
10681080
}
10691081
}

0 commit comments

Comments
 (0)