Skip to content

[GAP-21] Add transaction reverse scan and range deletion #435

Description

@s2x

Risk for enterprise users: Low
Labels: enhancement, feature-gap, area/txnkv
Reference implementations: client-rust src/transaction/snapshot.rs (scan_reverse), client-go txnkv/txnsnapshot/scan.go, client-java org/tikv/common/Snapshot.java

What is missing

Transaction::scan() is forward-only (src/Client/TxnKv/Transaction.php:195); TxnReader::executeScanForRegion() never sets KvScanRequest.reverse (src/Client/TxnKv/TxnReader.php:292). There is no transactional range delete: KvDeleteRange and UnsafeDestroyRange are generated in src/Proto/Tikvpb/TikvClient.php but unused.

How the official clients do it

All three official clients provide reverse scanning on the transactional snapshot: client-rust Snapshot::scan_reverse (src/transaction/snapshot.rs), client-go through its scanner with a reverse flag, client-java via Snapshot. UnsafeDestroyRange is exposed by client-go (tikv/gc.go:347) and client-rust (src/transaction/client.rs:374) as a GC-worker operation.

Impact of not having it

Reverse-ordered transactional reads — "latest N events for this key prefix" is the canonical case — must be emulated by scanning forward and reversing in PHP, which reads the whole range into memory. For a large range this is a memory and latency problem. Range deletion must be done key by key, which for a large range is slow and produces a very large transaction, running straight into GAP-16.

Workaround available today

Scan forward and reverse in application code, accepting the memory cost. For deletion, scan then delete in bounded batches across several transactions, accepting non-atomicity.

Implementation sketch

Reverse scan is a small change: add a $reverse parameter to TxnReader::scan() and executeScanForRegion(), set KvScanRequest.reverse, and iterate regions in reverse order — RegionRangeClipper::clipReverse() already exists and is used by RawKvScanner::reverseScan() (src/Client/RawKv/RawKvScanner.php:90). Range deletion is a separate, more careful piece of work because UnsafeDestroyRange bypasses MVCC and must not be exposed casually.

Effort estimate

Small for reverse scan; Medium for range deletion including safety guards.

Acceptance criteria

  • Transaction::scan() accepts a reverse flag with bound semantics matching RawKvClient::reverseScan().
  • Read-your-own-writes from the transaction buffer works correctly in reverse order.
  • Region iteration order is correct across region boundaries.
  • Tests cover reverse scan across at least two regions with buffered writes.

Filed from the Feature gaps vs official clients audit (audit-feature-gaps.md), finding GAP-21.
See the consolidated summary for the root-cause grouping this belongs to.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    auditAdded by audit issue importenhancementNew feature or requestfeature-gapAdded by audit issue importseverity:lowAdded by audit issue import

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions