Skip to content

MergeOperator: allow FullMergeV3 to produce a deletion result #14593

Description

@zaidoon1

Summary

MergeOperator::FullMergeV3 can produce a new plain value, a new wide-column value, or return an existing operand — but it cannot express "this key should be deleted." This makes the abstraction incomplete: a read-modify-write primitive should be able to conclude that a key no longer needs to exist.

Motivation

The limitation is already being worked around in the codebase. The Cassandra integration uses a two-phase pattern: CassandraValueMergeOperator resolves columns during merge, then CassandraCompactionFilter::FilterV2 checks if the result is empty and returns Decision::kRemove (cassandra_compaction_filter.cc:51-52 (https://github.com/facebook/rocksdb/blob/main/utilities/cassandra/cassandra_compaction_filter.cc#L51-L52)). This works but has drawbacks:

  • The key remains visible with a sentinel/empty value between compactions — reads see stale data until the CompactionFilter runs
  • The deletion logic is split across two unrelated abstractions (MergeOperator + CompactionFilter)
  • It only takes effect during compaction, not at read time
    There is also a related FIXME in merge_helper.cc:511 (https://github.com/facebook/rocksdb/blob/main/db/merge_helper.cc#L511) noting that kRemove is not properly checked during merge operand processing, suggesting the merge/deletion interaction is known to be incomplete.

Use cases

  • Conditional mutations: delete or update a key only if the current value meets a condition, resolved at read/compaction time with zero write-path overhead (instead of using transactions/optimistic transaction)
  • Counter auto-delete at zero: a merge-based counter that deletes the key when it reaches zero
  • Simplifying the Cassandra pattern: collapse the MergeOperator + CompactionFilter two-phase workaround into just MergeOperator

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions