Repository navigation
Fix pruning issue in SS causing huge disk spike #4321
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ import ( | |
|
|
||
| dbm "github.com/tendermint/tm-db" | ||
|
|
||
| "github.com/sei-protocol/seilog" | ||
|
|
||
| errorutils "github.com/sei-protocol/sei-chain/sei-db/common/errors" | ||
| seidbmetrics "github.com/sei-protocol/sei-chain/sei-db/common/metrics" | ||
| "github.com/sei-protocol/sei-chain/sei-db/common/utils" | ||
|
|
@@ -33,6 +35,8 @@ import ( | |
|
|
||
| var _ types.ContextIteratorStore = (*Database)(nil) | ||
|
|
||
| var logger = seilog.NewLogger("db", "db-engine", "pebbledb", "mvcc") | ||
|
|
||
| const ( | ||
| VersionSize = 8 | ||
|
|
||
|
|
@@ -953,7 +957,22 @@ func (db *Database) pruneDescending(version int64) (_err error) { | |
| if err != nil { | ||
| return err | ||
| } | ||
| defer func() { _ = itr.Close() }() | ||
| // itr pins Pebble's readState for as long as it's open, which blocks Pebble | ||
| // from deleting any sstable that readState might still need to serve reads | ||
| // from — including ones a concurrent or subsequent compaction (see | ||
| // compactPrunedRange below) has already superseded. itrOpen guards against | ||
| // closing it twice: the scan closes it explicitly as soon as it's done | ||
| // reading, right before compaction, and this defer only still applies if an | ||
| // error returned from inside the loop below. | ||
| itrOpen := true | ||
| closeItr := func() error { | ||
| if !itrOpen { | ||
| return nil | ||
| } | ||
| itrOpen = false | ||
| return itr.Close() | ||
| } | ||
| defer func() { _ = closeItr() }() | ||
|
|
||
| batch := db.storage.NewBatch() | ||
| defer func() { _ = batch.Close() }() | ||
|
|
@@ -1055,6 +1074,15 @@ func (db *Database) pruneDescending(version int64) (_err error) { | |
| itr.Next() | ||
| } | ||
|
|
||
| // Close the scan iterator now rather than leaving it to the deferred close | ||
| // at function return: compactPrunedRange below runs a compaction that can | ||
| // take a long time on a large deleted span, and every obsolete sstable it | ||
| // produces stays undeletable for as long as this iterator's readState is | ||
| // still pinning them. | ||
| if err := closeItr(); err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // Commit any leftover delete ops in batch | ||
| if counter > 0 { | ||
| writeCount := int64(batch.Count()) | ||
|
|
@@ -1066,7 +1094,10 @@ func (db *Database) pruneDescending(version int64) (_err error) { | |
| } | ||
| db.operationMetrics.AddRead(scanReads) | ||
|
|
||
| return db.compactPrunedRange(firstDeletedKey, lastDeletedKey) | ||
| compactStart := time.Now() | ||
| err = db.compactPrunedRange(firstDeletedKey, lastDeletedKey) | ||
| logger.Info("pruneDescending: compacted pruned range", "version", version, "elapsed", time.Since(compactStart), "err", err) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [suggestion] This |
||
| return err | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ascending prune still pins iteratorMedium Severity The early iterator close before Triggered by learned rule: sei-db pebbledb: ascending and descending MVCC iterators must stay aligned Reviewed by Cursor Bugbot for commit 184297f. Configure here. |
||
| } | ||
|
|
||
| func (db *Database) iteratorDescending( | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[suggestion] AGENTS.md ('Structural corrections') asks that this kind of fix be made by naming a step, not by adding an
itrOpenflag, acloseItrclosure, and two long inline comments. Consider moving the scan into its own function, e.g.scanAndDeletePruned(...) (first, last []byte, err error), that opens the iterator and closes it with a plaindefer.pruneDescendingthen reads as scan → commit → compact, and the iterator is closed before compaction by construction. The note about readState pinning belongs in that function's doc comment.pruneAscendinghas the same bug and could use the same shape.