Skip to content

Commit 1463838

Browse files
committed
db: add implementation warning about requirement imposed by SingleDelete
1 parent 6edd850 commit 1463838

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

batch.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ func (b *Batch) DeleteSizedDeferred(keyLen int, deletedValueSize uint32) *Deferr
956956
}
957957

958958
// SingleDelete adds an action to the batch that single deletes the entry for key.
959-
// See Writer.SingleDelete for more details on the semantics of SingleDelete.
959+
// WARNING: See the detailed warning in Writer.SingleDelete before using this.
960960
//
961961
// It is safe to modify the contents of the arguments after SingleDelete returns.
962962
func (b *Batch) SingleDelete(key []byte, _ *WriteOptions) error {
@@ -976,6 +976,8 @@ func (b *Batch) SingleDelete(key []byte, _ *WriteOptions) error {
976976
// operation to the batch, except it only takes in key/value lengths instead of
977977
// complete slices, letting the caller encode into those objects and then call
978978
// Finish() on the returned object.
979+
//
980+
// WARNING: See the detailed warning in Writer.SingleDelete before using this.
979981
func (b *Batch) SingleDeleteDeferred(keyLen int) *DeferredBatchOp {
980982
b.prepareDeferredKeyRecord(keyLen, InternalKeyKindSingleDelete)
981983
b.deferredOp.index = b.index

db.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,25 @@ type Writer interface {
139139
// properly. Only use if you have a workload where the performance gain is critical and you
140140
// can guarantee that a record is written once and then deleted once.
141141
//
142-
// SingleDelete is internally transformed into a Delete if the most recent record for a key is either
143-
// a Merge or Delete record.
142+
// Note that SINGLEDEL, SET, SINGLEDEL, SET, DEL/RANGEDEL, ... from most
143+
// recent to older will work as intended since there is a single SET
144+
// sandwiched between SINGLEDEL/DEL/RANGEDEL.
145+
//
146+
// IMPLEMENTATION WARNING: By offering SingleDelete, Pebble must guarantee
147+
// that there is no duplication of writes inside Pebble. That is, idempotent
148+
// application of writes is insufficient. For example, if a SET operation
149+
// gets duplicated inside Pebble, resulting in say SET#20 and SET#17, the
150+
// caller may issue a SINGLEDEL#25 and it will not have the desired effect.
151+
// This guarantee is partially achieved by ensuring that a WAL and a
152+
// flushable are usually in one-to-one correspondence, and atomically
153+
// updating the MANIFEST when the flushable is flushed (which ensures the
154+
// WAL will never be replayed). There is one exception: a flushableBatch is
155+
// written to the end of the WAL that it shares with the preceding memtable.
156+
// This is safe because the memtable and the flushableBatch are part of the
157+
// same flush (see DB.flush1 where this invariant is maintained). If the
158+
// memtable were to be flushed without the flushableBatch, the WAL cannot
159+
// yet be deleted and if a crash happened, the WAL would be replayed despite
160+
// the memtable already being flushed.
144161
//
145162
// It is safe to modify the contents of the arguments after SingleDelete returns.
146163
SingleDelete(key []byte, o *WriteOptions) error
@@ -682,6 +699,8 @@ func (d *DB) DeleteSized(key []byte, valueSize uint32, opts *WriteOptions) error
682699
// SingleDelete adds an action to the batch that single deletes the entry for key.
683700
// See Writer.SingleDelete for more details on the semantics of SingleDelete.
684701
//
702+
// WARNING: See the detailed warning in Writer.SingleDelete before using this.
703+
//
685704
// It is safe to modify the contents of the arguments after SingleDelete returns.
686705
func (d *DB) SingleDelete(key []byte, opts *WriteOptions) error {
687706
b := newBatch(d)

0 commit comments

Comments
 (0)