#20085·tikv

Enhance transactional RPC compatibility protection

Author: zyguanCreated Sep 15, 2026Updated Sep 16, 2026
Labelstype/enhancement

Background

Transactional RPC and lock-format evolution can introduce semantics that older clients cannot safely interpret. Shared locks are the recent confirmed example: an old client may misinterpret a LockInfo.shared_lock_infos wrapper as a fake lock, then issue invalid follow-up requests such as CheckTxnStatus(lock_ts=0) or ResolveLock(start_version=0).

This tracking issue covers a fail-closed compatibility defense for transactional RPCs. When a caller cannot safely process a transaction-protocol semantic, tikv must reject that path explicitly rather than expose data that can be misinterpreted or return partial success.

Core design

  • Introduce a request-level compatibility declaration for transactional RPC callers, together with a structured incompatible-request error. The concrete encoding and governance model still require design review; candidates include a monotonic transaction protocol version and capability-based alternatives.
  • Keep compatibility checks feature-specific. tikv checks the caller declaration at paths that would expose, consume, or incorrectly mutate new transaction semantics; the shared-lock paths are the first implementation scope.
  • For an incompatible caller, return a fail-closed response: no shared-lock wrapper, fake lock, partial success, or usable normal result.
  • Independently reject invalid transactional parameters, especially fake zero-timestamp transaction requests, before they reach transaction state mutation or assertion paths.
  • Use Context.request_origin for caller auditing and observability. It is not an authentication or authorization mechanism, and Unknown callers are audited rather than rejected in the first phase.
  • Ensure both new and legacy callers fail safely: new callers recognize the structured error as terminal, while legacy callers must not treat an incompatible path as successful.

Development Task

  • kvproto — Define the compatibility declaration, structured incompatible-request error, required transaction-protocol constants, and any required RequestOrigin / Store metadata extensions; regenerate and validate language bindings.
  • pd — If the selected design requires Store-side compatibility metadata, persist and return it correctly through PutStore, GetStore, and GetAllStores, including existing Store updates, restart/rollback behavior, and legacy Stores.
  • tikv — Implement RPC admission, shared-lock-specific fail-closed checks, structured error encoding with legacy-safe behavior, invalid transaction-request validation, caller-audit observability, and end-to-end regression coverage for affected transactional RPCs.
  • tiflash (including client-c) — Set RequestOriginTiFlash, inject and dynamically select the compatibility declaration for direct transactional RPCs, handle incompatible responses safely, and validate that the separate ReadIndex path does not expose shared-lock wrappers.
  • client-go — Centrally inject the process-level compatibility declaration and request origin for unary and BatchCommands requests; surface incompatible responses as terminal typed errors and cover lock-resolver request paths.
  • tidb (including br) — Configure tidb and standalone br caller identity/declaration at process initialization, validate tidb transaction paths and embedded-br behavior, and raise the declared compatibility level only after all relevant paths support the required semantics.
  • ticdc — Upgrade/configure client-go integration, set RequestOriginTiCDC, and validate both logpuller and unsafe resolve-lock paths, including shared-lock expansion and propagated resolver requests.