• C
    Track WAL obsoletion when updating empty CF's log number (#7781) · fbce7a38
    Cheng Chang 提交于
    Summary:
    In the write path, there is an optimization: when a new WAL is created during SwitchMemtable, we update the internal log number of the empty column families to the new WAL. `FindObsoleteFiles` marks a WAL as obsolete if the WAL's log number is less than `VersionSet::MinLogNumberWithUnflushedData`. After updating the empty column families' internal log number, `VersionSet::MinLogNumberWithUnflushedData` might change, so some WALs might become obsolete to be purged from disk.
    
    For example, consider there are 3 column families: 0, 1, 2:
    1. initially, all the column families' log number is 1;
    2. write some data to cf0, and flush cf0, but the flush is pending;
    3. now a new WAL 2 is created;
    4. write data to cf1 and WAL 2, now cf0's log number is 1, cf1's log number is 2, cf2's log number is 2 (because cf1 and cf2 are empty, so their log numbers will be set to the highest log number);
    5. now cf0's flush hasn't finished, flush cf1, a new WAL 3 is created, and cf1's flush finishes, now cf0's log number is 1, cf1's log number is 3, cf2's log number is 3, since WAL 1 still contains data for the unflushed cf0, no WAL can be deleted from disk;
    6. now cf0's flush finishes, cf0's log number is 2 (because when cf0 was switching memtable, WAL 3 does not exist yet), cf1's log number is 3, cf2's log number is 3, so WAL 1 can be purged from disk now, but WAL 2 still cannot because `MinLogNumberToKeep()` is 2;
    7. write data to cf2 and WAL 3, because cf0 is empty, its log number is updated to 3, so now cf0's log number is 3, cf1's log number is 3, cf2's log number is 3;
    8. now if the background threads want to purge obsolete files from disk, WAL 2 can be purged because `MinLogNumberToKeep()` is 3. But there are only two flush results written to MANIFEST: the first is for flushing cf1, and the `MinLogNumberToKeep` is 1, the second is for flushing cf0, and the `MinLogNumberToKeep` is 2. So without this PR, if the DB crashes at this point and try to recover, `WalSet` will still expect WAL 2 to exist.
    
    When WAL tracking is enabled, we assume WALs will only become obsolete after a flush result is written to MANIFEST in `MemtableList::TryInstallMemtableFlushResults` (or its atomic flush counterpart). The above situation breaks this assumption.
    
    This PR tracks WAL obsoletion if necessary before updating the empty column families' log numbers.
    
    Pull Request resolved: https://github.com/facebook/rocksdb/pull/7781
    
    Test Plan:
    watch existing tests and stress tests to pass.
    `make -j48 blackbox_crash_test` on devserver
    
    Reviewed By: ltamasi
    
    Differential Revision: D25631695
    
    Pulled By: cheng-chang
    
    fbshipit-source-id: ca7fff967bdb42204b84226063d909893bc0a4ec
    fbce7a38
db_impl_write.cc 73.7 KB