Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

db: scan a readState during format major version upgrades #2186

Merged
merged 1 commit into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 8 additions & 15 deletions format_major_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,31 +521,24 @@ func (d *DB) markFilesLocked(findFn findFilesFunc) error {
jobID := d.mu.nextJobID
d.mu.nextJobID++

vers := d.mu.versions.currentVersion()
// Acquire a read state to have a view of the LSM and a guarantee that none
// of the referenced files will be deleted until we've unreferenced the read
// state. Some findFilesFuncs may read the files, requiring they not be
// deleted.
rs := d.loadReadState()
var (
found bool
files [numLevels][]*fileMetadata
err error
)
func() {
// Disable file deletions. Some migrations that mark files may need to
// read the files themselves. The LSM may be changing while the
// migration is determining which files to mark. That's ok, because
// after re-acquiring the mutex and acquiring the manifest lock, we'll
// discard any sstables that have been removed from the LSM. However, we
// also need to make sure that the files we try to open during the scan
// are not removed before we read them. This is preferable over
// gracefully handling nonexistent files because some environments (eg,
// Windows) error if you attempt to remove an open file.
d.disableFileDeletions()
defer d.enableFileDeletions()

defer rs.unrefLocked()
// Note the unusual locking: unlock, defer Lock(). The scan of the files in
// the version does not need to block other operations that require the
// DB.mu. Drop it for the scan, before re-acquiring it.
d.mu.Unlock()
defer d.mu.Lock()
found, files, err = findFn(vers)
found, files, err = findFn(rs.current)
}()
if err != nil {
return err
Expand All @@ -566,7 +559,7 @@ func (d *DB) markFilesLocked(findFn findFilesFunc) error {
// Lock the manifest for a coherent view of the LSM. The database lock has
// been re-acquired by the defer within the above anonymous function.
d.mu.versions.logLock()
vers = d.mu.versions.currentVersion()
vers := d.mu.versions.currentVersion()
for l, filesToMark := range files {
if len(filesToMark) == 0 {
continue
Expand Down
23 changes: 13 additions & 10 deletions open.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,16 +260,6 @@ func Open(dirname string, opts *Options) (db *DB, _ error) {
}
}

// If the Options specify a format major version higher than the
// loaded database's, upgrade it. If this is a new database, this
// code path also performs an initial upgrade from the starting
// implicit MostCompatible version.
if !d.opts.ReadOnly && opts.FormatMajorVersion > d.mu.formatVers.vers {
if err := d.ratchetFormatMajorVersionLocked(opts.FormatMajorVersion); err != nil {
return nil, err
}
}

// Atomic markers like the one used for the MANIFEST may leave
// behind obsolete files if there's a crash mid-update. Clean these
// up if we're not in read-only mode.
Expand Down Expand Up @@ -433,6 +423,19 @@ func Open(dirname string, opts *Options) (db *DB, _ error) {
}
d.updateReadStateLocked(d.opts.DebugCheck)

// If the Options specify a format major version higher than the
// loaded database's, upgrade it. If this is a new database, this
// code path also performs an initial upgrade from the starting
// implicit MostCompatible version.
//
// We ratchet the version this far into Open so that migrations have a read
// state available.
if !d.opts.ReadOnly && opts.FormatMajorVersion > d.mu.formatVers.vers {
if err := d.ratchetFormatMajorVersionLocked(opts.FormatMajorVersion); err != nil {
return nil, err
}
}

if !d.opts.ReadOnly {
// Write the current options to disk.
d.optionsFileNum = d.mu.versions.getNextFileNum()
Expand Down
6 changes: 3 additions & 3 deletions testdata/checkpoint
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ sync: db/temporary.000001.dbtmp
close: db/temporary.000001.dbtmp
rename: db/temporary.000001.dbtmp -> db/CURRENT
sync: db
sync: db/MANIFEST-000001
create: db/000002.log
sync: db
create: db/marker.manifest.000001.MANIFEST-000001
close: db/marker.manifest.000001.MANIFEST-000001
sync: db
Expand Down Expand Up @@ -52,9 +55,6 @@ sync: db
create: db/marker.format-version.000011.012
close: db/marker.format-version.000011.012
sync: db
sync: db/MANIFEST-000001
create: db/000002.log
sync: db
create: db/temporary.000003.dbtmp
sync: db/temporary.000003.dbtmp
close: db/temporary.000003.dbtmp
Expand Down
64 changes: 32 additions & 32 deletions testdata/event_listener
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ close: db/temporary.000001.dbtmp
rename: db/temporary.000001.dbtmp -> db/CURRENT
sync: db
[JOB 1] MANIFEST created 000001
sync: db/MANIFEST-000001
create: wal/000002.log
sync: wal
[JOB 1] WAL created 000002
create: db/marker.manifest.000001.MANIFEST-000001
close: db/marker.manifest.000001.MANIFEST-000001
sync: db
Expand Down Expand Up @@ -66,10 +70,6 @@ create: db/marker.format-version.000011.012
close: db/marker.format-version.000011.012
sync: db
upgraded to format version: 012
sync: db/MANIFEST-000001
create: wal/000002.log
sync: wal
[JOB 1] WAL created 000002
create: db/temporary.000003.dbtmp
sync: db/temporary.000003.dbtmp
close: db/temporary.000003.dbtmp
Expand All @@ -83,10 +83,10 @@ sync: wal/000002.log
close: wal/000002.log
create: wal/000004.log
sync: wal
[JOB 6] WAL created 000004
[JOB 7] flushing 1 memtable to L0
[JOB 4] WAL created 000004
[JOB 5] flushing 1 memtable to L0
create: db/000005.sst
[JOB 7] flushing: sstable created 000005
[JOB 5] flushing: sstable created 000005
sync: db/000005.sst
close: db/000005.sst
sync: db
Expand All @@ -96,8 +96,8 @@ sync: db/MANIFEST-000006
create: db/marker.manifest.000002.MANIFEST-000006
close: db/marker.manifest.000002.MANIFEST-000006
sync: db
[JOB 7] MANIFEST created 000006
[JOB 7] flushed 1 memtable to L0 [000005] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 5] MANIFEST created 000006
[JOB 5] flushed 1 memtable to L0 [000005] (770 B), in 1.0s (2.0s total), output rate 770 B/s

compact
----
Expand All @@ -106,10 +106,10 @@ sync: wal/000004.log
close: wal/000004.log
reuseForWrite: wal/000002.log -> wal/000007.log
sync: wal
[JOB 8] WAL created 000007 (recycled 000002)
[JOB 9] flushing 1 memtable to L0
[JOB 6] WAL created 000007 (recycled 000002)
[JOB 7] flushing 1 memtable to L0
create: db/000008.sst
[JOB 9] flushing: sstable created 000008
[JOB 7] flushing: sstable created 000008
sync: db/000008.sst
close: db/000008.sst
sync: db
Expand All @@ -119,12 +119,12 @@ sync: db/MANIFEST-000009
create: db/marker.manifest.000003.MANIFEST-000009
close: db/marker.manifest.000003.MANIFEST-000009
sync: db
[JOB 9] MANIFEST created 000009
[JOB 9] flushed 1 memtable to L0 [000008] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 9] MANIFEST deleted 000001
[JOB 10] compacting(default) L0 [000005 000008] (1.5 K) + L6 [] (0 B)
[JOB 7] MANIFEST created 000009
[JOB 7] flushed 1 memtable to L0 [000008] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 7] MANIFEST deleted 000001
[JOB 8] compacting(default) L0 [000005 000008] (1.5 K) + L6 [] (0 B)
create: db/000010.sst
[JOB 10] compacting: sstable created 000010
[JOB 8] compacting: sstable created 000010
sync: db/000010.sst
close: db/000010.sst
sync: db
Expand All @@ -134,11 +134,11 @@ sync: db/MANIFEST-000011
create: db/marker.manifest.000004.MANIFEST-000011
close: db/marker.manifest.000004.MANIFEST-000011
sync: db
[JOB 10] MANIFEST created 000011
[JOB 10] compacted(default) L0 [000005 000008] (1.5 K) + L6 [] (0 B) -> L6 [000010] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 10] sstable deleted 000005
[JOB 10] sstable deleted 000008
[JOB 10] MANIFEST deleted 000006
[JOB 8] MANIFEST created 000011
[JOB 8] compacted(default) L0 [000005 000008] (1.5 K) + L6 [] (0 B) -> L6 [000010] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 8] sstable deleted 000005
[JOB 8] sstable deleted 000008
[JOB 8] MANIFEST deleted 000006

disable-file-deletions
----
Expand All @@ -150,10 +150,10 @@ sync: wal/000007.log
close: wal/000007.log
reuseForWrite: wal/000004.log -> wal/000012.log
sync: wal
[JOB 11] WAL created 000012 (recycled 000004)
[JOB 12] flushing 1 memtable to L0
[JOB 9] WAL created 000012 (recycled 000004)
[JOB 10] flushing 1 memtable to L0
create: db/000013.sst
[JOB 12] flushing: sstable created 000013
[JOB 10] flushing: sstable created 000013
sync: db/000013.sst
close: db/000013.sst
sync: db
Expand All @@ -163,27 +163,27 @@ sync: db/MANIFEST-000014
create: db/marker.manifest.000005.MANIFEST-000014
close: db/marker.manifest.000005.MANIFEST-000014
sync: db
[JOB 12] MANIFEST created 000014
[JOB 12] flushed 1 memtable to L0 [000013] (770 B), in 1.0s (2.0s total), output rate 770 B/s
[JOB 10] MANIFEST created 000014
[JOB 10] flushed 1 memtable to L0 [000013] (770 B), in 1.0s (2.0s total), output rate 770 B/s

enable-file-deletions
----
[JOB 13] MANIFEST deleted 000009
[JOB 11] MANIFEST deleted 000009

ingest
----
link: ext/0 -> db/000015.sst
[JOB 14] ingesting: sstable created 000015
[JOB 12] ingesting: sstable created 000015
sync: db
create: db/MANIFEST-000016
close: db/MANIFEST-000014
sync: db/MANIFEST-000016
create: db/marker.manifest.000006.MANIFEST-000016
close: db/marker.manifest.000006.MANIFEST-000016
sync: db
[JOB 14] MANIFEST created 000016
[JOB 14] MANIFEST deleted 000011
[JOB 14] ingested L0:000015 (826 B)
[JOB 12] MANIFEST created 000016
[JOB 12] MANIFEST deleted 000011
[JOB 12] ingested L0:000015 (826 B)

metrics
----
Expand Down