]> git-server-git.apps.pok.os.sepia.ceph.com Git - rocksdb.git/commitdiff
Fix WAL corruption from checkpoint/backup race condition
authorAndrew Kryczka <andrewkr@fb.com>
Fri, 16 Mar 2018 21:08:01 +0000 (14:08 -0700)
committerAndrew Kryczka <andrewkr@fb.com>
Fri, 16 Mar 2018 21:08:01 +0000 (14:08 -0700)
Summary:
`Writer::WriteBuffer` was always called at the beginning of checkpoint/backup. But that log writer has no internal synchronization, which meant the same buffer could be flushed twice in a race condition case, causing a WAL entry to be duplicated. Then subsequent WAL entries would be at unexpected offsets, causing the 32KB block boundaries to be overlapped and manifesting as a corruption.

This PR fixes the behavior to only use `WriteBuffer` (via `FlushWAL`) in checkpoint/backup when manual WAL flush is enabled. In that case, users are responsible for providing synchronization between WAL flushes. We can also consider removing the call entirely.
Closes https://github.com/facebook/rocksdb/pull/3603

Differential Revision: D7277447

Pulled By: ajkr

fbshipit-source-id: 1b15bd7fd930511222b075418c10de0aaa70a35a

HISTORY.md
utilities/checkpoint/checkpoint_impl.cc

index 7c2d70d96eafd55135493799c7fd8e5f2031b099..f876015903319dcaea2fddd5162f2029c28824e5 100644 (file)
@@ -6,6 +6,9 @@
 ### New Features
 * Avoid unnecessarily flushing in `CompactRange()` when the range specified by the user does not overlap unflushed memtables.
 
+### Bug Fixes
+* Fix WAL corruption caused by race condition between user write thread and backup/checkpoint thread.
+
 ## 5.12.0 (2/14/2018)
 ### Public API Change
 * Iterator::SeekForPrev is now a pure virtual method. This is to prevent user who implement the Iterator interface fail to implement SeekForPrev by mistake.
index d93c7095f19ecd394ffc82a290a5aa2b95c7f595..d3c0ae1e460036894bd7623f9de3d5f47052522f 100644 (file)
@@ -222,7 +222,9 @@ Status CheckpointImpl::CreateCustomCheckpoint(
 
     TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles1");
     TEST_SYNC_POINT("CheckpointImpl::CreateCheckpoint:SavedLiveFiles2");
-    db_->FlushWAL(false /* sync */);
+    if (db_options.manual_wal_flush) {
+      db_->FlushWAL(false /* sync */);
+    }
   }
   // if we have more than one column family, we need to also get WAL files
   if (s.ok()) {