Skip to content

Commit

Permalink
fix resource consumption on empty write transaction (#2018)
Browse files Browse the repository at this point in the history
## Problem
If a write transaction is opened without doing any updates, e.g. 
```
txn := db.NewTransaction(true)
txn.Commit()
```
the read mark is never marked done, because `txn.Discard` has not been
called and neither has the commit logic because of the early return in
`Commit()`:
```
if len(txn.pendingWrites) == 0 {
    return nil // Nothing to do.
}
```
This causes unbounded storage growth until the service is restarted. The
watermark process in `y/watermark.go` never receives a mark for that
transaction, and so never updates the `DoneUntil`. This value is used in
`levels.go` for compaction to determine the `discardTS` value, and since
it never updates, compaction can never occur.

## Solution
The solution here is to call `txn.Discard` in the case when there are no
writes on the transaction. This marks the read as done and allows the
watermark process to properly update.
  • Loading branch information
Zach-Johnson committed Oct 13, 2023
1 parent 27724c4 commit 1741e47
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,9 @@ func (txn *Txn) Commit() error {
// txn.conflictKeys can be zero if conflict detection is turned off. So we
// should check txn.pendingWrites.
if len(txn.pendingWrites) == 0 {
return nil // Nothing to do.
// Discard the transaction so that the read is marked done.
txn.Discard()
return nil
}
// Precheck before discarding txn.
if err := txn.commitPrecheck(); err != nil {
Expand Down

0 comments on commit 1741e47

Please sign in to comment.